我还在试图弄清楚如何将我的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类中调用程序逻辑)?
我希望自己足够清楚......
答案 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订阅模型发送的事件。