Tkinter 基于单选按钮改变入口状态

Tkinter changing entry state based on radiobutton

我有四个单选按钮。在这四个按钮下面是一个 Entry 小部件。我试图使这个 Entry 小部件仅在选择最后一个单选按钮时才可用于输入。 gui 在 class 中,您可以在下面的代码中看到:

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 始终可供输入。我究竟做错了什么。如果您仍然不明白发生了什么,那么请 运行 自己查看这段代码,您将会看到。

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

唯一的问题,我明白了,你在这里面临的是因为你没有将值“正确地”传递到函数中,当你使用 (..) 时,你调用了函数,所以要摆脱它使用 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=' ')

但请确保仅执行上述解决方案之一。阅读 有关三态值的更多信息。

另请注意,您没有将任何 master window 传递给小部件,只要您只有一个 window 就可以了,当使用多个 windows,小部件的显示位置可能会令人困惑。

还有side-note,如果这是完整的代码,那么如果在__init__()上什么都没做,可以删除它的定义。

您对使用 RadioButton 到 enable/disable 条目小部件的想法是正确的。主要是您的 class 设计存在缺陷 - 它介于 OO 代码和过程代码之间...

我修复了 class 结构并使它成为 tk.Tk 的子 class,因此它完全封装了您的 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()