Python tkinter 来自单独文件的多个窗口

问题描述 投票:0回答:1

我继续在 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)从第一个窗口打开?

python tkinter window
1个回答
0
投票

注意,当直接执行

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)
© www.soinside.com 2019 - 2024. All rights reserved.