问题
I'm generally new to python and tkinter. I've been programming maybe about a year or so, and I've just started to try to make each tkinter toplevel window its own class because I've heard that it's the right way to do it.
I'm making a program in which I have a treeview with a button to add contents to it. The button opens up a new window that allows the user to input the contents. The problem I'm having is when I have to instantiate the first window to update the treeview, it seems like it's doubling all of the widgets on the first window. This causes it to keep building up and it looks strange.
Is this normal or is there a better way to do it?
Thank you. I can post a picture or my code if necessary.
edit: shortened code
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()
回答1:
You are calling class MainWindow:
every time you press the New
Button. This is remaking all the widgets over and over. And they way you are creating the MainWindow is affecting how you can interact with MainWindow.
Change:
def main():
root = Tk()
MainWindow(root)
root.mainloop()
if __name__ == "__main__":
main()
To:
if __name__ == "__main__":
root = Tk()
main = MainWindow(root)
root.mainloop()
Once you have made this change you are able to interact with the instance attributes and methods of main
Below is a modified version of your code. You will notice when you press the button I added to the TopLevel window it will print information from an atribute and method of main
variable. It will also place some text in the entry box in the MainWindow.
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()
来源:https://stackoverflow.com/questions/44701488/new-instance-of-toplevel-classes-make-overlapping-widgets