tkinter主循环是否负责?将UI与逻辑分开

时间:2018-03-13 13:55:10

标签: python python-3.x tkinter

我还在试图弄清楚如何将我的UI与我的程序逻辑分开。我对Python很新,也许你可以帮助我。

我试图将我的UI与我的程序分开,希望以后我可以从tkinter切换到其他GUI。所以我想让我的主程序做东西并调用tk Frame来显示我的数据。

所以,这是我的显示类,它工作正常:

import tkinter as tk

class TestClass(tk.Frame):
    def __init__(self, master=None):
        super().__init__(master)
        self.label1 = tk.Label(text="Label1")
        self.label1.pack()
        self.changeLabel1("change from within") # <-- this works 

    def changeLabel1(self, changeText):
        self.label1.config(text=changeText)
        self.update_idletasks()

    def writeSomething(self, outputText):
        print(outputText)

我自己做了一些测试程序来实例化这个类:

# starter for TestClass
import TestClass
x = TestClass.TestClass()
x.mainloop()

x.writeSomething("Test") <-- nothing happens
x.changeLabel1("Test") <-- nothing happens

我把这些调用放在mainloop之后的函数中,只是为了表明在调用mainloop之后我无法改变它。

当我尝试使用changeLabel1函数更改label1时,它可以在类中运行,但不能从我的启动类中运行。我从writeSomething(文本)获得一些输出,但只有当我关闭窗口时。并且有一条错误消息显示:

_tkinter.TclError: invalid command name ".!label"

(它实际上更长,只是追溯的最后一行。)

搜索让我得出结论,它可能与mainloop()有关,但我不知道如何处理这个问题。

什么是最佳做法?我是否在我的tkinter类或调用tkinter类的测试文件中调用mainloop?

这是一种分离UI和逻辑的方法,还是我出错了,是否应该以相反的方式完成(从UI类中调用程序逻辑)?

我希望自己足够清楚......

1 个答案:

答案 0 :(得分:2)

在典型的GUI中,主循环负责处理用户事件(通过将它们分派给事件处理程序回调)。在您的代码段中,代码之后调用x.mainloop()仅在主窗口关闭且循环退出时执行。

所以是的,显而易见的答案是它是负责调用&#34;逻辑&#34;的UI代码(事件处理程序回调)。代码(可以更好地命名&#34;域模型&#34;代码 - 在UI中也有一些&#34;逻辑&#34; - 当您考虑它时,这一点最为明显:您的域模型代码应该对UI一无所知,因此您可以将其用于不同的UI(GUI,基于文本,Web,命令行脚本等)。

如果您希望自己的UI更新自己以响应您的域模型层中发生的事情(这是任何非平凡的GUI应用程序的常见要求),您最好的选择是good old Model-View-Controller模式(真实的这个&#34;模型&#34;是你的域模型(或它的一些包装),&#34;控制器&#34;是您的事件处理程序回调和&#34;视图&#34;是你的UI组件(或它们周围的一些包装)。这里的关键是使用Observer pattern,让UI订阅模型发送的事件。