简体   繁体   English

如何启用和禁用框架而不是Python Tkinter中的单个小部件

[英]How to enable and disable Frame instead of individual widgets in Python Tkinter

I have an application where I have to enable all the widgets on current window after I click on a radio button. 我有一个应用程序,单击单选按钮后,必须在当前窗口中启用所有小部件。 Initially, when I start my application, I have two radio buttons in frame1 and I have to disable all other widgets (like buttons, entries) which are placed in frame2 , and whenever I click on radio_button1 it all the widgets should be enabled. 起初,当我开始我的申请, 我有两个单选按钮frame1 ,我必须禁用所有其他部件(如按钮,输入),它被放置在frame2 ,每当我点击radio_button1它所有的部件应该启用。 In this code, when I click on radio_button1 , it activates all widgets. 在此代码中,当我单击radio_button1 ,它将激活所有小部件。 Is there a better approach I can develop, so that it disables and enables the whole frame instead of enabling and disabling each individual widget? 我是否可以开发出更好的方法,以便禁用并启用整个框架,而不是启用和禁用每个单独的小部件? Below is my current code: 下面是我当前的代码:

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

What you should do is to recursively visit all the children of the frame (and the children of its children and so on if (like me) you use nested frames to organize your UI), and disable or enable each individually. 您应该做的是递归地访问框架的所有子项(及其子项等等,如果您(例如我)使用嵌套框架来组织UI),则分别禁用或启用每个子项。

The best way to do that is to subclass ttk.Frame to include the required functionality: 最好的方法是将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')

Then create your frames as instances of dFrame: 然后将您的框架创建为dFrame的实例:

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

and you can use: 您可以使用:

self.frame1.enable()

and

self.frame1.disable()

to enable / disable all widgets in the frame. 启用/禁用框架中的所有小部件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM