簡體   English   中英

Python Tkinter-記住創建新窗口的狀態(復選框)

[英]Python Tkinter- Remember State of Created New Window (Checkboxes)

我有一個名為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的許多文檔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()

請注意,這只是一種方法。 您只需要四處摸索以適應自己的實現,就沒有正確/錯誤的方法來做事情。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM