为什么使用 StringVar 而不是 IntVar 时 Tkinter 的单选按钮都开始选中?
问题描述
这里是一些示例代码,它创建了 4 个 Radiobutton
,其中 2 个使用 int
,2 个使用 str
:
Here is some example code that creates 4 Radiobutton
s, 2 using int
and 2 using str
:
from tkinter import *
class test:
def __init__(self):
wind = Tk()
frame1 = Frame(wind)
frame1.pack()
self.v1 = IntVar()
self.v2 = StringVar()
int1 = Radiobutton(frame1, text = 'int1', variable = self.v1, value = 1,
command = self.ipress)
int2 = Radiobutton(frame1, text = 'int2', variable = self.v1, value = 2,
command = self.ipress)
str1 = Radiobutton(frame1, text = 'str1', variable = self.v2, value = '1',
command = self.spress)
str2 = Radiobutton(frame1, text = 'str2', variable = self.v2, value = '2',
command = self.spress)
int1.grid(row = 1, column = 1)
int2.grid(row = 1, column = 2)
str1.grid(row = 2, column = 1)
str2.grid(row = 2, column = 2)
str1.deselect() #this didn't fix it
str2.deselect()
def ipress(self):
print('int'+str(self.v1.get()))
def spress(self):
print('str'+self.v2.get())
test()
运行后,我有一个如下所示的框:
After running this I have a box that look like this:
出于某种原因,str
开始被选中,而 int
则没有.是否有一个原因?有什么解决办法吗?我知道我可以通过使用数值然后将它们转换为字符串来解决它,但我想先了解为什么会发生这种情况.
For some reason the str
ones start selected while the int
ones do not. Is there a reason for this? Is there any fix for it? I know I could work around it by just using number values and then converting them to strings but I'd like to understand why this is happening first.
如果这很重要,我正在使用 Windows 10.
I am using Windows 10 if that matters.
澄清一下,这些按钮在被点击后仍然可以正常工作.
for clarification, the buttons still work properly after they have been clicked on.
解决方案
在第二组单选按钮的情况下,它们以三态模式"呈现.
In the case of the second set of radiobuttons, they are being rendered in "tri-state mode".
根据官方文档1:
如果变量的值与 tristateValue 匹配,则单选按钮是使用三态模式绘制的.该模式用于表示混合值或多个值.
If the variable's value matches the tristateValue, then the radiobutton is drawn using the tri-state mode. This mode is used to indicate mixed or multiple values.
说明
tristatevalue
的默认值为空字符串,StringVar
的默认值为空字符串.对于您的第二组单选按钮,变量值和 tristatevalue
都是相同的,因此您看到的是三态模式".
Explanation
The default for tristatevalue
is the empty string, and the default value for a StringVar
is the empty string. For your second set of radiobuttons both the variable value and the tristatevalue
are the same so you are seeing the "tri-state mode".
在 IntVar
的情况下,变量的默认值为零.tristatevalue
仍然是空字符串.这两个是不同的,所以小部件不会出现在三态模式"中.
In the case of the IntVar
, the default value of the variable is zero. The tristatevalue
is still the empty string. Those two are different so the widget does not appear in "tri-state mode".
为了证明这一点,请将第一组单选按钮的 tristatevalue
设置为零,使其与关联变量的默认值匹配,您将看到它们的外观发生变化以匹配第二组.
To prove this, set tristatevalue
to zero for the first set of radiobuttons so that it matches the default value of the associated variable and you will see that their appearance changes to match the second set.
int1 = Radiobutton(..., tristatevalue=0)
int2 = Radiobutton(..., tristatevalue=0)
同样,您可以将第二组的 tristatevalue
设置为默认值以外的其他值,以便它们看起来像第一组:
Likewise, you could set the tristatevalue
of the second set to something other than the default value so that they will look like the first set:
str1 = Radiobutton(..., tristatevalue="x")
str2 = Radiobutton(..., tristatevalue="x")
解决方案
单选按钮的最佳做法是始终确保默认值对应于单选按钮值之一,除非您确实需要三态模式".
Solution
The best practice with radiobuttons is to always make sure the default value corresponds to one of the radiobutton values, unless you truly do want "tri-state mode".
在您的情况下,您应该将变量初始化为单选按钮之一的值:
In your case, you should initialize the variables to the value of one of the radiobuttons:
self.v1 = IntVar(value=1)
self.v2 = StringVar(value="1")
... 或者在你创建它们之后,通过 set
:
... or after you create them, via set
:
self.v1.set(1)
self.v2.set("1")
<小时>
1 链接指向 tcl/tk 手册页.Tkinter 只是 tcl/tk 的一个薄包装,这个文档是小部件行为方式的明确答案.
1 the link goes to the tcl/tk man pages. Tkinter is just a thin wrapper around tcl/tk, and this documentation is the definitive answer to how the widgets behave.
相关文章