Как включить и отключить Frame вместо отдельных виджетов в Python Tkinter

У меня есть приложение, в котором я должен включить все виджеты в текущем окне после того, как я нажму на переключатель. Первоначально, когда я запускаю свое приложение, у меня есть две кнопки frame1 и я должен отключить все другие виджеты (например, кнопки, записи), которые находятся в frame2 и всякий раз, когда я нажимаю на radio_button1 это все виджеты должны быть включены. В этом коде, когда я нажимаю на radio_button1, он активирует все виджеты. Есть ли лучший подход, который я могу разработать, чтобы он отключал и включал весь кадр вместо того, чтобы включать и отключать каждый отдельный виджет? Ниже мой текущий код:

from tkinter import *
from tkinter import simpledialog

class Gui:
    def __init__(self, parent, **kw):
        self.parent = parent
        self.top = Toplevel(self.parent)
        self.frame1= Frame(self.top,width= 450,height =550)
        self.frame1.grid(row=0)
        self.frame2 = Frame(self.top, width=450, height=550)
        self.frame2.grid(row=1)
        self.radio1=Radiobutton(self.frame1,text='radio_button1',value=1,command=self.enable_window)
        self.radio2=Radiobutton(self.frame1,text='radio_button2',value=2)


        self.label1 = Label(self.frame2, text='Label1:', width=15, background='white', justify=CENTER,
                                  font='-weight bold')
        self.label2 = Label(self.frame2, text='Lable2:', width=15, background='white', justify=CENTER,
                               font='-weight bold')
        self.b=Button(self.frame2,text='save',state=DISABLED)
        self.c = Button(self.frame2, text='cancel',state=DISABLED)
        self.radio1.grid(row=0,column=0,sticky='W')
        self.radio2.grid(row=0,column=1,padx=50,sticky='W')
        self.label1.grid(padx=10, pady=5, row=0, column=0, sticky='E')
        self.label2.grid(padx=10, pady=5, row=1, column=0, sticky='E')
        self.b.grid(row=3,column=0)
        self.c.grid(row=3, column=1)
        self.entry1_Var = StringVar()
        self.entry2_Var = StringVar()
        self.entry1 = Entry(self.frame2, width=15, background='white', textvariable=self.entry1_Var,state='disable',
                                   font='-weight bold')
        self.entry2 = Entry(self.frame2, width=15, background='white', textvariable=self.entry2_Var,state='disable',
                                font='-weight bold')

        self.entry1.grid(padx=10, pady=5, row=0, column=1, sticky='W')
        self.entry2.grid(padx=10, pady=5, row=1, column=1, sticky='W')


       self.entry_focus_flag = False
       self.top.grab_set()
    def enable_window(self):
        self.entry1['state'] = 'normal'
        self.entry2['state'] = 'normal'
        self.b['state'] = NORMAL
        self.b['state'] = NORMAL

class main_window:
    def __init__(self,root):
        self.root=root
        button1=Button(self.root,text='Start application',command= lambda p=self.root:self.callback(p))
        button1.pack()
    def callback(self,p):
        Gui(p)

root =Tk()
app = main_window(root)
root.mainloop()

1 ответ

Что вы должны сделать, это рекурсивно посетить все дочерние элементы фрейма (и дочерние элементы его дочерних элементов и т. Д., Если (как и я) вы используете вложенные фреймы для организации своего пользовательского интерфейса), а также отключить или включить каждый из них по отдельности.

Лучший способ сделать это - создать подкласс ttk.Frame для включения необходимой функциональности:

class dFrame(ttk.Frame):

    def enable(self, state='!disabled'):

        def cstate(widget):
            # Is this widget a container?
            if widget.winfo_children:
                # It's a container, so iterate through its children
                for w in widget.winfo_children():
                    # change its state
                    w.state((state,))
                    # and then recurse to process ITS children
                    cstate(w)

            cstate(self)


    def disable(self):
        self.enable('disabled')

Затем создайте свои кадры как экземпляры dFrame:

self.frame1 = dFrame(self.top,width= 450,height =550)

и вы можете использовать:

self.frame1.enable()

а также

self.frame1.disable()

включить / отключить все виджеты в кадре.

Другие вопросы по тегам