gh-73588: Fix generation of the default name of tkinter.Checkbutton. (GH-97547)

Previously, checkbuttons in different parent widgets could have the same
short name and share the same state if arguments "name" and "variable" are
not specified. Now they are globally unique.
This commit is contained in:
Serhiy Storchaka 2022-09-27 14:05:05 +03:00 committed by GitHub
parent 68c46ae68b
commit adbed2d542
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 58 additions and 3 deletions

View file

@ -212,6 +212,32 @@ def test_configure_onvalue(self):
widget = self.create()
self.checkParams(widget, 'onvalue', 1, 2.3, '', 'any string')
def test_unique_variables(self):
frames = []
buttons = []
for i in range(2):
f = tkinter.Frame(self.root)
f.pack()
frames.append(f)
for j in 'AB':
b = tkinter.Checkbutton(f, text=j)
b.pack()
buttons.append(b)
variables = [str(b['variable']) for b in buttons]
self.assertEqual(len(set(variables)), 4, variables)
def test_same_name(self):
f1 = tkinter.Frame(self.root)
f2 = tkinter.Frame(self.root)
b1 = tkinter.Checkbutton(f1, name='test', text='Test1')
b2 = tkinter.Checkbutton(f2, name='test', text='Test2')
v = tkinter.IntVar(self.root, name='test')
b1.select()
self.assertEqual(v.get(), 1)
b2.deselect()
self.assertEqual(v.get(), 0)
@add_standard_options(StandardOptionsTests)
class RadiobuttonTest(AbstractLabelTest, unittest.TestCase):

View file

@ -275,6 +275,21 @@ def cb_test():
self.assertEqual(cbtn['offvalue'],
cbtn.tk.globalgetvar(cbtn['variable']))
def test_unique_variables(self):
frames = []
buttons = []
for i in range(2):
f = ttk.Frame(self.root)
f.pack()
frames.append(f)
for j in 'AB':
b = ttk.Checkbutton(f, text=j)
b.pack()
buttons.append(b)
variables = [str(b['variable']) for b in buttons]
print(variables)
self.assertEqual(len(set(variables)), 4, variables)
@add_standard_options(IntegerSizeTests, StandardTtkOptionsTests)
class EntryTest(AbstractWidgetTest, unittest.TestCase):

View file

@ -2619,7 +2619,7 @@ def __init__(self, master, widgetName, cnf={}, kw={}, extra=()):
if kw:
cnf = _cnfmerge((cnf, kw))
self.widgetName = widgetName
BaseWidget._setup(self, master, cnf)
self._setup(master, cnf)
if self._tclCommands is None:
self._tclCommands = []
classes = [(k, v) for k, v in cnf.items() if isinstance(k, type)]
@ -3038,6 +3038,8 @@ def type(self, tagOrId):
return self.tk.call(self._w, 'type', tagOrId) or None
_checkbutton_count = 0
class Checkbutton(Widget):
"""Checkbutton widget which is either in on- or off-state."""
@ -3053,6 +3055,14 @@ def __init__(self, master=None, cnf={}, **kw):
underline, variable, width, wraplength."""
Widget.__init__(self, master, 'checkbutton', cnf, kw)
def _setup(self, master, cnf):
if not cnf.get('name'):
global _checkbutton_count
name = self.__class__.__name__.lower()
_checkbutton_count += 1
cnf['name'] = f'!{name}{_checkbutton_count}'
super()._setup(master, cnf)
def deselect(self):
"""Put the button in off-state."""
self.tk.call(self._w, 'deselect')

View file

@ -11,7 +11,7 @@ class Dialog(Widget):
def __init__(self, master=None, cnf={}, **kw):
cnf = _cnfmerge((cnf, kw))
self.widgetName = '__dialog__'
Widget._setup(self, master, cnf)
self._setup(master, cnf)
self.num = self.tk.getint(
self.tk.call(
'tk_dialog', self._w,

View file

@ -310,7 +310,7 @@ def __init__ (self, master=None, widgetName=None,
del cnf[k]
self.widgetName = widgetName
Widget._setup(self, master, cnf)
self._setup(master, cnf)
# If widgetName is None, this is a dummy creation call where the
# corresponding Tk widget has already been created by Tix

View file

@ -0,0 +1,4 @@
Fix generation of the default name of :class:`tkinter.Checkbutton`.
Previously, checkbuttons in different parent widgets could have the same
short name and share the same state if arguments "name" and "variable" are
not specified. Now they are globally unique.