Python Tkinter - запомнить состояние созданного нового окна (флажки) - PullRequest
0 голосов
/ 08 ноября 2018

У меня есть кнопка с именем 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 Ответ

0 голосов
/ 08 ноября 2018

С вашей текущей структурой самое простое исправление будет:

  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()

Возможно, вы захотите добавить тот же самый метод protocol в master, чтобы при закрытии уничтожить оба объекта master и new_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, что выполняет то же самое). Смотрите соответствующий ответ здесь


Вот краткий пример подхода ООП в том же духе:

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()

Обратите внимание, что это всего лишь один из способов сделать это. Вам просто нужно чувствовать себя комфортно в своей реализации, нет правильного / неправильного способа сделать что-либо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...