Python Tkinter-记住已创建新窗口的状态(复选框)



我有一个名为view的按钮,当点击它时,它将创建一个新窗口,其中包含列表框中的列表和与列表框对应的复选框列表。当切换列表框中的项目时,您将看到列表框项目彼此独立,并有自己的复选框值。截至目前,它将记住每个列表框项目的复选框值,除非您关闭创建的窗口。当您关闭创建的第二个窗口时,当您尝试再次打开该窗口时,所有信息都会消失。我需要一种方法来创建第二个窗口,用列表框和复选框做它现在所做的一切,但当关闭时,它可以再次打开,并从你停止的地方重新开始。

例如,如果我高亮显示列表框中的第一个项目并选中第一个复选框,我应该能够关闭该窗口并再次打开它,当列表框中第一个项目高亮显示时,我会看到第一个复选复选框中有一个复选框。

import tkinter
from tkinter import *

def myfunction(event):
canvas1.configure(scrollregion=canvas1.bbox("all"))
def onselect(evt):
# Note here that Tkinter passes an event object to onselect()
w = evt.widget
x = 0
index = int(w.curselection()[0])
value = w.get(index)
print('You selected item %d: "%s"' % (index, value))
for y in enable:
for item in list_for_listbox:
checkbuttons[item][y][1].grid_forget()
checkbuttons[value][y][1].grid(row=x, column=0)
# Label(frame2, text="some text").grid(row=x, column=1)
x += 1
def printcommand():
for item in list_for_listbox:
for y in enable:
print(item + " [" + y + "] " + str(checkbuttons[item][y][0].get()))
def create_new_window():
global new_window
new_window = tkinter.Toplevel()
new_window.geometry("750x500")
new_window_commands()
master = tkinter.Tk()
master.title("Checkboxes test")
master.geometry("750x500")
button1 = Button(master, command =create_new_window,text="View")
button1.place(x=50,y=250)
def new_window_commands():
# enable = ['button 1', 'button 2', 'button 3', 'button 4', 'button 5', 'button 6', 'button 7']
global list_for_listbox
global enable
global checkbuttons
global canvas1
enable = []
for x_number_of_items in range(1, 15):
enable.append("button " + str(x_number_of_items))
list_for_listbox = ["one", "two", "three", "four"]
listbox = Listbox(new_window)
listbox.place(x=5, y=5, width=100, height=10 + 16*len(list_for_listbox))
listbox.update()
frame1 = Frame(new_window, borderwidth=1, relief=GROOVE, highlightthickness=1, highlightbackground="black",
highlightcolor="black")
frame1.place(x=listbox.winfo_width() + 10, y=5, width=300, height=listbox.winfo_height())
canvas1 = Canvas(frame1)
frame2 = Frame(canvas1, height=500)
scrollbar1 = Scrollbar(frame1, orient="vertical", command=canvas1.yview)
canvas1.configure(yscrollcomman=scrollbar1.set)
scrollbar1.pack(side="right", fill="y")
canvas1.pack(side="left")
canvas1.create_window((0, 0), window=frame2, anchor='nw')
frame2.bind("<Configure>", myfunction)
printbutton = Button(new_window, text="Print", command=printcommand)
printbutton.place(x=100, y=250)
checkbuttons = {}
for item in list_for_listbox:
listbox.insert(END, item)
checkbuttons[item] = (dict())
for y in enable:
temp_var = BooleanVar()
checkbuttons[item][y] = [temp_var, Checkbutton(frame2, text=y, variable=temp_var)]
listbox.bind('<<ListboxSelect>>', onselect)
print(enable)
mainloop()
printcommand()

对于您当前的结构,最简单的修复方法是:

  1. 只创建一次new_window
  2. withdraw()new_window,而不是每次都让它关闭
  3. 调用时再次打开new_window的同一实例

您需要实现以下内容:

# Default your new_window to None
new_window = None
def create_new_window():
global new_window
# If new_window doesn't exist, create a new one
if not new_window:
new_window = tkinter.Toplevel()
new_window.geometry("750x500")
# add a new protocol to redirect on closing the window.
new_window.protocol("WM_DELETE_WINDOW", hide_window)
new_window_commands()
else:
# if new_window already exist, just unhide it
new_window.deiconify()
# add a new function for when window is closing
def hide_window():
global new_window
new_window.withdraw()

您可能还想在master下添加相同的protocol方法,以便在它关闭时销毁masternew_window对象:

master.protocol('WM_DELETE_WINDOW', destroy_all)
def destroy_all():
global master
global new_window
master.destroy()
new_window.destroy()

如果可能的话,对于您的下一个tkinter代码,我建议考虑一种面向对象的方法。我稍后会看看能否在这里提供一个简短的样品。

顺便说一句,虽然我知道tkinter中的许多文档都使用from tkinter import *方法,但我不鼓励这种做法,并建议使用import tkinter as tk(或者像您已经做过的那样,使用import tkinter,它可以完成同样的事情(。请参阅此处的相关答案


这里有一个类似的OOP方法的快速示例:

import tkinter as tk
# Here the main window can be called upon as its own instance with its own instance attributes.
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.main_button = tk.Button(self, text="Creat a sub window", command=self.open_sub_window)
self.main_button.pack()
# define the things you wish to retain under the main window as an instance attribute
self.sub_check_var = tk.BooleanVar()
self.sub_entry_var = tk.StringVar()
# when creating a new window, just reference back to the main attributes you've already created.
def open_sub_window(self):
self.sub_window = tk.Toplevel()
tk.Checkbutton(self.sub_window, text="I'm a checkbox!", variable=self.sub_check_var).pack()
lbl_frm = tk.LabelFrame(self.sub_window, text="I am an entry!")
lbl_frm.pack()
tk.Entry(lbl_frm, text=self.sub_entry_var).pack()
gui = Window()
gui.mainloop()

注意,这只是一种方法。你只需要四处走走,就可以适应你的实现,没有对错的方法。

最新更新