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)
时,只有在选择单选按钮时才会执行。这就是使用单选按钮的意义所在,对吧?
另请注意,当初始代码为 运行 时,整个单选按钮都被选中,我认为这可能是因为三态值,要摆脱我知道的两种方式:
- 将
self.type
的声明更改为:
self.type = tk.StringVar(value=' ')
- 或者,您还可以继续为每个单选按钮添加一个额外的选项,
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()
我有四个单选按钮。在这四个按钮下面是一个 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)
时,只有在选择单选按钮时才会执行。这就是使用单选按钮的意义所在,对吧?
另请注意,当初始代码为 运行 时,整个单选按钮都被选中,我认为这可能是因为三态值,要摆脱我知道的两种方式:
- 将
self.type
的声明更改为:
self.type = tk.StringVar(value=' ')
- 或者,您还可以继续为每个单选按钮添加一个额外的选项,
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()