python 模块化大型tkinter程序

kmbjn2e3  于 2023-01-11  发布在  Python
关注(0)|答案(2)|浏览(199)

我用tkinter设计了一个GUI。我把它构建在一个类中。我通常使用的结构是创建一个框架,并把我所有的小部件打包到其中。然后当我需要显示一个不同的屏幕时,我破坏那个框架,并调用一个函数来创建一个新的父框架和新的小部件。下面是一个简单的例子来阐明这个结构。

import tkinter as tk

class Window():
    def __init__(self, master):
        self.master = master
        self.master.geometry('300x300')
        frame = tk.Frame(self.master)
        frame.pack()
        self.main(frame)

    def goto(self, destination, frame):
        frame.destroy()
        frame = tk.Frame(self.master)
        frame.pack()
        goto = {
            'main': self.main,
            'a': self.a,
            'b': self.b
        }
        goto[destination](frame)

    def main(self, frame):
        tk.Label(frame, text='Main').pack()
        tk.Button(frame, text='Goto A', command=lambda: self.goto('a', frame)).pack()
        tk.Button(frame, text='Goto B', command=lambda: self.goto('b', frame)).pack()

    def a(self, frame):
        tk.Label(frame, text='A').pack()
        tk.Button(frame, text='Back to Main', command=lambda: self.goto('main', frame)).pack()

    def b(self, frame):
        tk.Label(frame, text='B').pack()
        tk.Button(frame, text='Back to Main', command=lambda: self.goto('main', frame)).pack()

root = tk.Tk()
Window(root)
root.mainloop()

我更喜欢这种结构的顶层窗口,因为我有问题,与他们在过去的工作(Windows落在其他打开的窗口后面,焦点问题等)。但我真的很怀念Toplevel Windows让构建模块变得多么容易,而不是把所有的代码放在一个脚本中。有没有一种方法可以不使用Toplevel就很容易地模块化这样的结构?这对组织和可读性都很好。我尝试过将不同的"屏幕创建"函数放到模块中,但是我遇到了循环依赖问题。
main.py

import tkinter as tk
import module

class Window():
    def __init__(self, master):
        self.master = master
        self.master.geometry('300x300')
        frame = tk.Frame(self.master)
        frame.pack()
        self.main(frame)

    def goto(self, destination, frame):
        frame.destroy()
        frame = tk.Frame(self.master)
        frame.pack()
        goto = {
            'main': self.main,
            'a': module.a,
        }
        goto[destination](frame)

    def main(self, frame):
        tk.Label(frame, text='Main').pack()
        tk.Button(frame, text='Goto A', command=lambda: self.goto('a', frame)).pack()

root = tk.Tk()
window = Window(root)
root.mainloop()

module.py

import tkinter as tk
import main

def a(frame):
    tk.Label(frame, text='A').pack()
    tk.Button(frame, text='Back to Main', command=lambda: main.window.goto('main', frame)).pack()

当我点击应该带我到模块中内置的框架的按钮时,我得到:
属性错误:部分初始化的模块"module"没有属性"a"(很可能是由于循环导入)

nkhmeac6

nkhmeac61#

您可以避免由于循环导入而导致的部分初始化模块错误,只需在主脚本末尾附近的代码周围添加一个if __name__ == '__main__':保护,如下所示(这样可以防止在由module.py导入代码时执行它后面的语句)。
main.py

import tkinter as tk
import module

class Window():
    def __init__(self, master):
        self.master = master
        self.master.geometry('300x300')
        frame = tk.Frame(self.master)
        frame.pack()
        self.main(frame)

    def goto(self, destination, frame):
        frame.destroy()
        frame = tk.Frame(self.master)
        frame.pack()
        goto = {
            'main': self.main,
            'a': module.a,
        }
        goto[destination](frame)

    def main(self, frame):
        tk.Label(frame, text='Main').pack()
        tk.Button(frame, text='Goto A', command=lambda: self.goto('a', frame)).pack()

if __name__ == '__main__':  # ADDED
    root = tk.Tk()
    window = Window(root)
    root.mainloop()

module.py (no重大变更)

import tkinter as tk
import main

def a(frame):
    tk.Label(frame, text='A').pack()
    tk.Button(frame, text='Back to Main',
              command=lambda: main.window.goto('main', frame)).pack()
k2fxgqgv

k2fxgqgv2#

这段代码给我这个错误-Tkinter回调异常-Traceback(最近的最后调用):

  • 文件-“C:\用户\19417\应用数据\本地\程序\Python\Python 310\lib\tkinter_* 初始化 *_.py”,-第1921行,在调用
  • 返回自身函数(*args)
  • 文件“C:\Code\ATE APAS\module.py”,第6行,位于
  • tk.按钮(框架,文本=“返回主菜单”,命令=lambda:主窗口.后藤(“主”,-框架)).pack()-属性错误:模块“main”没有属性“window”

相关问题