我继续在 tkinter 中与多个窗口作斗争。 它现在正在开发成一个应用程序,其中每个窗口都位于其自己的单独文件中。
我需要从第一个窗口打开第二个窗口,因为这就是应用程序的工作原理。
我还需要独立于第一个窗口打开第二个窗口,即单独打开,这样我就可以在它开发时进行单元测试。
当第二个窗口打开时,这个问题会破坏前一个窗口。 不是我想要的:Python tkinter 多个窗口
我自己的上一个问题在第二个窗口打开时关闭第一个窗口。 不是我想要的。 尽管评论指出了一个拼写错误(省略了
()
),但接受的答案使用了withdraw
和deiconify
,这最终会有所帮助,但不是解决这个问题的方法。 Python tkinter 关闭第一个窗口,同时打开第二个窗口
这是最接近的,因为它从第一个窗口打开第二个窗口,但它没有解决(i)从单独的文件打开第二个窗口和(ii)也能够独立打开第二个窗口:Python tkinter类多个窗口
这是名为 Location.py 的文件中的第二个窗口,它可以独立打开:
import tkinter as tk
from tkinter import ttk
class Location(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
root.title("Location")
root.geometry('400x275')
# Frames
self.mainframe = ttk.Frame(self.master)
self.mainframe.grid(column = 0, row=0)
ttk.Label(self.mainframe, text = "Second Window").grid(column=1, row=1, sticky=(tk.W, tk.E))
if __name__ == "__main__":
root = tk.Tk()
Location(root)
root.mainloop()
这是第一个窗口,它也可以正常打开,问题是当我按任一按钮调用文件以打开第二个窗口时:
import tkinter as tk
from tkinter import ttk
import Location
class Building_Info(tk.Frame):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Frames
self.infoframe = ttk.Frame(self.master, height=400, width=200, padding="50 100 50 100", borderwidth=10)
self.infoframe['relief'] = 'raised'
self.infoframe.grid(column = 0, row=0, sticky=(tk.E, tk.N))
self.buttonframe = ttk.Frame(self.master, height=400, width=200, padding="50 100 50 100", borderwidth=10)
self.buttonframe['relief'] = 'raised'
self.buttonframe.grid(column = 1, row=0, sticky=(tk.E, tk.N))
# BUTTONS
confirm_button = ttk.Button(self.infoframe, text = 'Stakeholders', command = self.open_location)
confirm_button.grid(column=0, row=2)
confirm_button = ttk.Button(self.buttonframe, text = 'Location', command = self.open_location)
confirm_button.grid(column=0, row=2)
for child in self.infoframe.winfo_children():
child.grid_configure(padx=5, pady=5)
for child in self.buttonframe.winfo_children():
child.grid_configure(padx=5, pady=5)
# METHODS
def open_location(self):
Location.Location()
if __name__ == "__main__":
root = tk.Tk()
root.title("Building Information")
root.geometry('600x400')
Building_Info(root)
root.mainloop()
当我尝试通过
Location.Location()
或 Location.Location(root)
或 Location.Location(self)
或 Location.Location(self.master)
时,我收到此错误:
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "c:\Users\User\Documents\Python\Tutorials\BuildingInfo_Stay_Open.py", line 32, in open_location
Location_Stay_Open.Location()
File "c:\Users\User\Documents\Python\Tutorials\Location_Stay_Open.py", line 9, in __init__
root.title("Location")
^^^^
NameError: name 'root' is not defined
但是当我尝试通过
Location.Location(self.root)
时,有人问我是否是指root
。
Traceback (most recent call last):
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 1948, in __call__
return self.func(*args)
^^^^^^^^^^^^^^^^
File "c:\Users\User\Documents\Python\Tutorials\BuildingInfo_Stay_Open.py", line 32, in open_location
Location_Stay_Open.Location(self.root)
^^^^^^^^^
AttributeError: 'Building_Info' object has no attribute 'root'. Did you mean: '_root'?
现在,如果我返回第二个窗口
class Location(tk.Frame)
并尝试class Location(tk.Tk)
,那么第二个窗口不会独立打开,并给出以下错误:
Traceback (most recent call last):
File "c:\Users\User\Documents\Python\Tutorials\Location_Stay_Open.py", line 29, in <module>
Location(root)
File "c:\Users\User\Documents\Python\Tutorials\Location_Stay_Open.py", line 7, in __init__
super().__init__(*args, **kwargs)
File "C:\Users\User\AppData\Local\Programs\Python\Python312\Lib\tkinter\__init__.py", line 2326, in __init__
self.tk = _tkinter.create(screenName, baseName, className, interactive, wantobjects, useTk, sync, use)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TypeError: create() argument 1 must be str or None, not Tk
尝试
class Location(tk.Toplevel)
会打开两个窗口:一个标题为 Location,另一个标题为 tk。 关闭一个窗口会同时关闭两个窗口。 我只想要其中一扇窗户。
我需要做什么才能让第二个窗口(位置)(i)独立打开并(ii)从第一个窗口打开?
注意,当直接执行
Location.py
时,root
内的Location.__init__()
指的是在root
块中创建的全局窗口if __name__ == "__main__"
。
但是,当导入
Location.py
时,if
块中的代码将不会被执行,因此没有定义root
,因为在主脚本中创建的root
窗口无法被导入的模块直接访问。
您需要明确地将
root
参数添加到类 Location
中:
class Location(tk.Frame):
# added root argument
def __init__(self, root, *args, **kwargs):
super().__init__(root, *args, **kwargs)
...
然后你需要在
Toplevel
内部创建一个Building_Info.open_location()
并将其传递给Location
:
class Building_Info(tk.Frame):
...
def open_location(self):
# create a toplevel window
win = tk.Toplevel()
# and pass it to Location class
Location.Location(win)