我对python很新,并尝试按照面向对象的方法构建一个简单的GUI。因此,我让我的widget类继承自 tk.Frame 并创建一个应用程序控制器来构建GUI。
我的应用程序包含以下两个文件:
mainModule.py
>>> import demjson
>>> data_string = """
... {
... server_id: 1,
... server_status: 200,
... client: "client2",
... content: [ {id: 0, info: "info0"}, {id: 2, info: "info2"} ]
... }
... """
>>> demjson.decode(data_string, strict=False)
{'server_id': 1, 'server_status': 200, 'client': 'client2', 'content': [{'id': 0, 'info': 'info0'}, {'id': 2, 'info': 'info2'}]}
myGUI.py
# coding: utf8
from testPackage import myGUI
import Tkinter as tk
root = tk.Tk() # Main window
my_gui = myGUI.MainApplication(root)
root.mainloop() # Hold window open until we close it
最初在MainApplication类定义中没有 self.pack() (标记为#Code)的情况下运行我的代码只给了我没有Label的root基本窗口从MainWindow类创建。
答案可能简单但是为什么?
我使用了一些资源来进入上面的主题,其中一些没有在根窗口上使用任何几何管理器(或者我很难看到它。来自下面的示例)。
来源:
https://www.begueradj.com/tkinter-best-practices.html
Tkinter example code for multiple windows, why won't buttons load correctly?
只有在阅读了关于小部件创建的以下答案后,我才意识到缺少部分:
Best way to structure a tkinter application
creating a custom widget in tkinter
确定初始化时的pack()与
相同# coding: utf8
import Tkinter as tk
# Application initializer
class MainApplication(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, master)
self.configure_gui()
self.pack() # <--- CODE IN QUESTION
self.create_widgets()
def configure_gui(self):
self.master.title("Any title")
self.master.geometry('800x600')
self.master.minsize(600, 100)
def create_widgets(self):
self.main_window = MainWindow(self)
self.main_window.pack()
# Main Data Window
class MainWindow(tk.Frame):
def __init__(self, master):
self.master = master
tk.Frame.__init__(self, master)
self.main_window = tk.Label(self, text="This is a test")
self.main_window.pack(side="top", fill="x")
或
MainApplication(root).pack(side="top", fill="both", expand=True)
用于基于网格的布局。
我想这是一个非常简单或明显的元素,我没有看到与继承有关但我不完全确定为什么必须打包()MainApplication Frame以及为什么它似乎在没有这一步的情况下工作。 / p>
答案 0 :(得分:1)
由于MainWindow
继承自Frame
,因此它本身就是一个框架。如果您从未在其上调用pack
,place
或grid
,则该内容将不可见。这与您创建按钮或滚动条或任何其他小部件然后不要在其上调用其中一种方法没什么不同。
由于所有其他窗口小部件都是此框架的子窗口,因此它们将不可见,因为它们的父窗口是不可见的。
与被问到的问题有些无关,self.pack()
是代码味道。一般来说,课程不应该单独调用pack
,place
或grid
。这将自己紧密地耦合到调用者(意思是,这个小部件必须知道调用者正在使用这些方法之一)。
换句话说,如果您确定MainApplication
想要为其所有子女切换pack
到grid
,则无法更新MainApplication
,您还必须更新MainWindow
。在这种情况下,根窗口只有一个孩子所以问题相当小,但通过这样做你开始一个不好的做法,最终会导致你的问题。
经验法则是创建窗口小部件的功能应该负责将其添加到屏幕。这意味着最好这样做:
root = tk.Tk()
my_gui = myGUI.MainApplication(root)
my_gui.pack(fill="both", expand=True)
然后,您需要从self.pack()
中删除MainApplication.__init__
。
您还有一些非常具有误导性的代码可能导致混淆。看看这段代码:
# Main Data Window
class MainWindow(tk.Frame):
def __init__(self, master):
...
self.main_window = tk.Label(self, text="This is a test")
self.main_window.pack(side="top", fill="x")
注意你是如何拥有一个名为MainWindow
的类。在其中,您有一个名为self.main_window
的标签,但self.main_window
不一个MainWindow
。这尤其令人困惑,因为创建MainWindow
的函数还会创建名为self.main_window
的实例变量。
您可能需要考虑将此标签重命名为其他内容(例如:self.label
,self.greeting
等)。