【问题标题】:New instance of toplevel classes make overlapping widgets顶级类的新实例使小部件重叠
【发布时间】:2017-06-22 13:55:01
【问题描述】:

我通常是 python 和 tkinter 的新手。我已经编程了大约一年左右,我刚刚开始尝试让每个 tkinter 顶级窗口成为自己的类,因为我听说这是正确的做法。

我正在制作一个程序,其中有一个带有按钮的树视图,可以向其中添加内容。该按钮打开一个新窗口,允许用户输入内容。我遇到的问题是当我必须实例化第一个窗口来更新树视图时,它似乎将第一个窗口上的所有小部件都加倍了。这会导致它不断堆积,看起来很奇怪。

这是正常现象还是有更好的方法?

谢谢。如有必要,我可以发布图片或我的代码。

编辑:缩短的代码

from tkinter import *
from tkinter import ttk


class MainWindow:
    Items = {'test': ['Material', '500']}
    def __init__(self, master):
        self.master = master

        self.style = ttk.Style()
        self.style.configure('TLabel', font=12)

        ttk.Label(self.master, text="Items").grid(row=0, column=0, columnspan=3)

        self.frmItems = ttk.Frame(self.master)
        self.frmItems.grid(row=1, column=0, padx=5, pady=5, columnspan=3)

        self.treeItems = ttk.Treeview(self.frmItems, columns=(0, 1, 2))
        self.treeItems.column('#0', width=0, minwidth=0)
        self.treeItems.column(1, width=80)
        self.treeItems.column(2, width=80)
        self.treeItems.heading(0, text="Name")
        self.treeItems.heading(1, text="Type")
        self.treeItems.heading(2, text="Price")
        self.treeItems.grid(row=0, column=0)

        self.itemscroll = ttk.Scrollbar(self.frmItems, command=self.treeItems.yview)
        self.itemscroll.grid(row=0, column=1, sticky='ns')
        self.treeItems.config(yscrollcommand=self.itemscroll.set)

        ttk.Button(self.master, text="New", command=self.item_input_show).grid(row=2, column=0, padx=5, pady=5,
                                                                              sticky='e')
        ttk.Button(self.master, text="Edit").grid(row=2, column=1, padx=5, pady=5)
        ttk.Button(self.master, text="Remove").grid(row=2, column=2, padx=5, pady=5, sticky='w')

    def item_input_show(self):
        ItemInput(self.master)


class ItemInput:
    def __init__(self, master):
        self.master = master
        self.MainWindow = MainWindow(master)

        self.topItemInput = Toplevel(self.master)
        self.topItemInput.title("Input Item Properties")


def main():
    root = Tk()
    MainWindow(root)
    root.mainloop()

if __name__ == "__main__":
    main()

【问题讨论】:

  • 不正常。您的代码正在做某事导致此问题。如果我们无法看到重现问题的代码,我们就无法提供帮助。请阅读并遵循此处的建议:minimal reproducible example
  • 我添加了代码。很抱歉我没能把它缩短。我不确定是什么原因造成的,但这是我在特定程序上做错了
  • 请缩短。那里有太多不相关的代码。例如,如果问题出在小部件的外观上,则不需要进行实际转换的代码。此外,不应该需要从文件中读取数据;例如,您可以硬编码一两行数据。
  • 好的,怎么样。我想我把它限制在 MainWindow 类

标签: python class tkinter treeview toplevel


【解决方案1】:

每次按下New 按钮时,您都在呼叫class MainWindow:。这是一遍又一遍地重新制作所有小部件。您创建 MainWindow 的方式会影响您与 MainWindow 交互的方式。

变化:

def main():
    root = Tk()
    MainWindow(root)
    root.mainloop()

if __name__ == "__main__":
    main()

收件人:

 if __name__ == "__main__":
    root = Tk()
    main = MainWindow(root)
    root.mainloop()

完成此更改后,您就可以与main 的实例属性和方法进行交互

以下是您的代码的修改版本。您会注意到,当您按下我添加到 TopLevel 窗口的按钮时,它将打印来自 main 变量的属性和方法的信息。它还会在主窗口的输入框中放置一些文本。

from tkinter import *
from tkinter import ttk

class MainWindow:
    def __init__(self, master):
        self.master = master
        self.btn = ttk.Button(self.master, text="New", command=self.item_input_show)
        self.btn.pack(side = TOP)
        self.entry = Entry(self.master)
        self.entry.pack(side = BOTTOM)
        self.numbers = 200

    def two_plus_x(self, x):
        math = 2 + x
        return math

    def item_input_show(self):
        ItemInput(self.master)


class ItemInput:
    def __init__(self, master):
        self.master = master
        self.topItemInput = Toplevel(master)
        self.btn = ttk.Button(self.topItemInput, text="Use method in MainWindow", command = self.do_something_from_main)
        self.btn.pack()

    def do_something_from_main(self):
        print(main.numbers)
        print(main.two_plus_x(10))
        main.entry.delete(0, END)
        main.entry.insert(0, "From ItemInput Class")

# notice I removed def main(): as it was preventing us from interacting with the main variable.
if __name__ == "__main__":
    root = Tk()
    main = MainWindow(root)
    root.mainloop()

【讨论】:

  • 我必须从 ItemInput 类的 MainWindow 类中运行方法
  • 有理由使用 2 个单独的类吗?您可以将顶级窗口放在 MainWindow 的方法中。
  • 是的,我正在考虑。我只是想习惯让每个窗口都有自己的类,因为人们说它更干净,更容易使用
  • 嗯,你说你遇到的问题是加倍self.MainWindow = MainWindow(master) 是加倍的原因。让我看看我能做些什么来解决另一个问题。
  • 我可能只是将其他窗口放入您所说的方法中。我只是对如何从另一个类运行方法而不使小部件加倍感到困惑。顺便谢谢你的帮助
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多