From 32c0d3ada52109f339c081d3408546a4af024b3c Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sun, 30 Oct 2016 18:49:52 +0200 Subject: [PATCH] Issue #27939: Fixed bugs in tkinter.ttk.LabeledScale and tkinter.Scale caused by representing the scale as float value internally in Tk. tkinter.IntVar now works if float value is set to underlying Tk variable. --- Lib/tkinter/__init__.py | 8 ++++++-- Lib/tkinter/test/test_tkinter/test_variables.py | 5 ++--- Lib/tkinter/test/test_ttk/test_extensions.py | 17 +++++++++++++---- Misc/NEWS | 4 ++++ 4 files changed, 25 insertions(+), 9 deletions(-) diff --git a/Lib/tkinter/__init__.py b/Lib/tkinter/__init__.py index 55bfb7f4146..1eaab44bfed 100644 --- a/Lib/tkinter/__init__.py +++ b/Lib/tkinter/__init__.py @@ -357,7 +357,11 @@ class IntVar(Variable): def get(self): """Return the value of the variable as an integer.""" - return self._tk.getint(self._tk.globalgetvar(self._name)) + value = self._tk.globalgetvar(self._name) + try: + return self._tk.getint(value) + except (TypeError, TclError): + return int(self._tk.getdouble(value)) class DoubleVar(Variable): """Value holder for float variables.""" @@ -2864,7 +2868,7 @@ class Scale(Widget): value = self.tk.call(self._w, 'get') try: return self.tk.getint(value) - except (ValueError, TclError): + except (ValueError, TypeError, TclError): return self.tk.getdouble(value) def set(self, value): """Set the value to VALUE.""" diff --git a/Lib/tkinter/test/test_tkinter/test_variables.py b/Lib/tkinter/test/test_tkinter/test_variables.py index 1f74453cea6..d8ba9cea747 100644 --- a/Lib/tkinter/test/test_tkinter/test_variables.py +++ b/Lib/tkinter/test/test_tkinter/test_variables.py @@ -167,15 +167,14 @@ class TestIntVar(TestBase): self.assertEqual(123, v.get()) self.root.globalsetvar("name", "345") self.assertEqual(345, v.get()) + self.root.globalsetvar("name", "876.5") + self.assertEqual(876, v.get()) def test_invalid_value(self): v = IntVar(self.root, name="name") self.root.globalsetvar("name", "value") with self.assertRaises((ValueError, TclError)): v.get() - self.root.globalsetvar("name", "345.0") - with self.assertRaises((ValueError, TclError)): - v.get() class TestDoubleVar(TestBase): diff --git a/Lib/tkinter/test/test_ttk/test_extensions.py b/Lib/tkinter/test/test_ttk/test_extensions.py index f33945cef9c..218b27fc30e 100644 --- a/Lib/tkinter/test/test_ttk/test_extensions.py +++ b/Lib/tkinter/test/test_ttk/test_extensions.py @@ -69,14 +69,12 @@ class LabeledScaleTest(AbstractTkTest, unittest.TestCase): # variable initialization/passing passed_expected = (('0', 0), (0, 0), (10, 10), - (-1, -1), (sys.maxsize + 1, sys.maxsize + 1)) + (-1, -1), (sys.maxsize + 1, sys.maxsize + 1), + (2.5, 2), ('2.5', 2)) for pair in passed_expected: x = ttk.LabeledScale(self.root, from_=pair[0]) self.assertEqual(x.value, pair[1]) x.destroy() - x = ttk.LabeledScale(self.root, from_='2.5') - self.assertRaises((ValueError, tkinter.TclError), x._variable.get) - x.destroy() x = ttk.LabeledScale(self.root, from_=None) self.assertRaises((ValueError, tkinter.TclError), x._variable.get) x.destroy() @@ -155,8 +153,10 @@ class LabeledScaleTest(AbstractTkTest, unittest.TestCase): # The following update is needed since the test doesn't use mainloop, # at the same time this shouldn't affect test outcome x.update() + self.assertEqual(x.value, newval) self.assertEqual(x.label['text'], newval if self.wantobjects else str(newval)) + self.assertEqual(float(x.scale.get()), newval) self.assertGreater(x.scale.coords()[0], curr_xcoord) self.assertEqual(x.scale.coords()[0], int(x.label.place_info()['x'])) @@ -168,10 +168,19 @@ class LabeledScaleTest(AbstractTkTest, unittest.TestCase): conv = int x.value = conv(x.scale['to']) + 1 # no changes shouldn't happen x.update() + self.assertEqual(x.value, newval) self.assertEqual(conv(x.label['text']), newval) + self.assertEqual(float(x.scale.get()), newval) self.assertEqual(x.scale.coords()[0], int(x.label.place_info()['x'])) + # non-integer value + x.value = newval = newval + 1.5 + x.update() + self.assertEqual(x.value, int(newval)) + self.assertEqual(conv(x.label['text']), int(newval)) + self.assertEqual(float(x.scale.get()), newval) + x.destroy() diff --git a/Misc/NEWS b/Misc/NEWS index cbc8c4d953f..4d84e7ed1e0 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -113,6 +113,10 @@ Core and Builtins Library ------- +- Issue #27939: Fixed bugs in tkinter.ttk.LabeledScale and tkinter.Scale caused + by representing the scale as float value internally in Tk. tkinter.IntVar + now works if float value is set to underlying Tk variable. + - Issue #28255: calendar.TextCalendar().prmonth() no longer prints a space at the start of new line after printing a month's calendar. Patch by Xiang Zhang.