【问题标题】:Tkinter changing entry state based on radiobuttonTkinter 基于单选按钮更改条目状态
【发布时间】:2021-02-13 17:13:54
【问题描述】:

我有四个单选按钮。这四个按钮下方是一个Entry 小部件。我试图让这个Entry 小部件只有在选择最后一个单选按钮时才可以输入。 gui 在一个类中,如下面的代码所示:

class Gui:
    def __init__(self):
        pass

    def draw(self):
        global root

        if not root:
            root  = tk.Tk()
            root.geometry('280x350')

            self.type = tk.StringVar()
            self.type_label = tk.Label(text="Game Mode")
            self.name_entry = tk.Entry()
            self.name_entry.configure(state="disabled")
            self.name_entry.update()
            self.type_entry_one = tk.Radiobutton(text="Garage", value="garage", variable=self.type, command=self.disable_entry(self.name_entry))
            self.type_entry_two = tk.Radiobutton(text="Festival", value="festival", variable=self.type, command=self.disable_entry(self.name_entry))
            self.type_entry_three = tk.Radiobutton(text="Studio", value="studio", variable=self.type, command=self.disable_entry(self.name_entry))
            self.type_entry_four = tk.Radiobutton(text="Rockslam", value="rockslam", variable=self.type, command=self.enable_entry(self.name_entry))
            
         
            self.type_label.pack()
            self.type_entry_one.pack()
            self.type_entry_two.pack()
            self.type_entry_three.pack()
            self.type_entry_four.pack()
            self.name_entry.pack()

            root.mainloop()

    def enable_entry(self, entry):
        entry.configure(state="normal")
        entry.update()

    def disable_entry(self, entry):
        entry.configure(state="disabled")
        entry.update()





if __name__ == '__main__':
    root = None
    gui = Gui()
    gui.draw()

但是,self.name_entry 始终可以输入。我究竟做错了什么。如果您仍然不明白发生了什么,请自己运行此代码,您会看到。

非常感谢您抽出宝贵时间,期待您的回复。

【问题讨论】:

标签: python python-3.x tkinter radio-button tkinter-entry


【解决方案1】:

您对使用RadioButton 启用/禁用条目小部件有正确的想法。主要是你的类设计有缺陷——它介于 OO 代码和过程代码之间......

我修复了类结构并使其成为tk.Tk 的子类,因此它完全封装了您的GUI。 name_entry 现在仅在选择 type_entry_four 单选按钮时启用,否则禁用。我已将最后一个按钮设置为在启动时选择,但您可以轻松更改它;它会导致在启动时启用该条目。
删除了通过方法传递的多余变量,draw 方法及其调用;所有小部件的创建现在都可以在GUI.__init__ 中方便地找到

import tkinter as tk


class Gui(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry('280x350')

        self.select_type = tk.StringVar()
        self.type_label = tk.Label(self, text='Game Mode')
        self.name_entry = tk.Entry(self)
        self.type_entry_one = tk.Radiobutton(self, text='Garage', value='garage', variable=self.select_type, command=self.disable_entry)
        self.type_entry_two = tk.Radiobutton(self, text='Festival', value='festival', variable=self.select_type, command=self.disable_entry)
        self.type_entry_three = tk.Radiobutton(self, text='Studio', value='studio', variable=self.select_type, command=self.disable_entry)
        self.type_entry_four = tk.Radiobutton(self, text='Rockslam', value='rockslam', variable=self.select_type, command=self.enable_entry)

        self.select_type.set('rockslam')   # select the last radiobutton; also enables name_entry
        
        self.type_label.pack()
        self.type_entry_one.pack()
        self.type_entry_two.pack()
        self.type_entry_three.pack()
        self.type_entry_four.pack()
        self.name_entry.pack()

    def enable_entry(self):
        self.name_entry.configure(state='normal')

    def disable_entry(self):
        self.name_entry.configure(state='disabled')


if __name__ == '__main__':
    
    Gui().mainloop()

【讨论】:

  • 我看到您将 self 作为 tk.Entry() 的参数。我是否也必须为所有其他条目执行此操作?另外,感谢您实际解释要做什么。这个平台上的大多数人都会告诉我要正确地学习面向对象编程,并否决我的问题。
  • 是的,非常欢迎您。小部件在树中表示,其中子小部件持有对其父级的引用。对于带有一个窗口的简单 GUI,如果省略父窗口,它仍然可以工作;在这种情况下,tkinter 默认分配root(树的);但是,我认为最好养成良好的习惯,并为所有小部件明确指定父级。
  • 好的,我明白了。我也想澄清一下我对 OOP 的了解,我觉得我有点生疏了。我将观看 1 小时的教程。还是谢谢。
  • @Lucy 这个答案肯定总结了问题!但如果您想知道这里还面临哪些其他问题,请查看我的答案。
【解决方案2】:

唯一的问题S,我明白了,你在这里面临的是因为你没有将值“正确”传递给函数,当你使用(..)时,你调用了函数,所以要摆脱那个使用lambda ,比如:

self.type_entry_one = tk.Radiobutton(text="Garage", value="garage", variable=self.type, command=lambda: self.disable_entry(self.name_entry))
self.type_entry_two = tk.Radiobutton(text="Festival", value="festival", variable=self.type, command=lambda:self.disable_entry(self.name_entry))
self.type_entry_three = tk.Radiobutton(text="Studio", value="studio", variable=self.type, command=lambda:self.disable_entry(self.name_entry))
self.type_entry_four = tk.Radiobutton(text="Rockslam", value="rockslam", variable=self.type, command=lambda:self.enable_entry(self.name_entry))

使用command=lambda:func(arg) 时,仅在选择单选按钮时才会执行。这就是使用单选按钮的意义所在,对吧?

还要注意,当初始代码运行时,整个单选按钮都被选中,我认为这可能是因为三态值,要摆脱这种情况,我知道有两种方法:

  1. self.type 的声明更改为:
self.type = tk.StringVar(value=' ')
  1. 或者,您还可以继续为每个单选按钮添加一个额外的选项,tristatevalue=' ',例如:
self.type_entry_one = tk.Radiobutton(text="Garage",..,tristatevalue=' ')

但请确保只执行上述解决方案之一。阅读here,了解更多关于三态值的信息。

另外请注意,您没有将任何master 窗口传递给小部件,只要您只有一个窗口就可以了,当使用多个窗口时,可能会混淆小部件应该出现的位置。

另外附注,如果这是完整的代码,那么如果在 __init__() 上没有做任何事情,则可以删除它的定义。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-08-01
    • 2021-03-20
    • 2013-08-04
    • 1970-01-01
    • 1970-01-01
    • 2017-12-07
    • 1970-01-01
    相关资源
    最近更新 更多