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.
diff --git a/Lib/test/test_tkinter/test_widgets.py b/Lib/test/test_tkinter/test_widgets.py
index 1cddbe1..6cde1cc 100644
--- a/Lib/test/test_tkinter/test_widgets.py
+++ b/Lib/test/test_tkinter/test_widgets.py
@@ -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):
diff --git a/Lib/test/test_ttk/test_widgets.py b/Lib/test/test_ttk/test_widgets.py
index eb0cc93..6f47ccb 100644
--- a/Lib/test/test_ttk/test_widgets.py
+++ b/Lib/test/test_ttk/test_widgets.py
@@ -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):
diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py
index 2963202..3564469 100644
--- a/Lib/tkinter/__init__.py
+++ b/Lib/tkinter/__init__.py
@@ -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')
diff --git a/Lib/tkinter/dialog.py b/Lib/tkinter/dialog.py
index 8ae2140..36ae6c2 100644
--- a/Lib/tkinter/dialog.py
+++ b/Lib/tkinter/dialog.py
@@ -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,
diff --git a/Lib/tkinter/tix.py b/Lib/tkinter/tix.py
index 44ecae1..ce21826 100644
--- a/Lib/tkinter/tix.py
+++ b/Lib/tkinter/tix.py
@@ -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
diff --git a/Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst b/Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst
new file mode 100644
index 0000000..d8a0e69
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2022-09-25-20-42-33.gh-issue-73588.uVtjEA.rst
@@ -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.