mirror of
				https://github.com/python/cpython.git
				synced 2025-11-03 23:21:29 +00:00 
			
		
		
		
	[3.9] bpo-33289: Return RGB triplet of ints instead of floats from tkinter.colorchooser (GH-6578). (GH-24318)
(cherry picked from commit 6713e869c4)
Co-authored-by: Cheryl Sabella <cheryl.sabella@gmail.com>
			
			
This commit is contained in:
		
							parent
							
								
									ff06957710
								
							
						
					
					
						commit
						3d5434d5cb
					
				
					 5 changed files with 103 additions and 27 deletions
				
			
		| 
						 | 
					@ -1160,8 +1160,7 @@ def winfo_reqwidth(self):
 | 
				
			||||||
            self.tk.call('winfo', 'reqwidth', self._w))
 | 
					            self.tk.call('winfo', 'reqwidth', self._w))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def winfo_rgb(self, color):
 | 
					    def winfo_rgb(self, color):
 | 
				
			||||||
        """Return tuple of decimal values for red, green, blue for
 | 
					        """Return a tuple of integer RGB values in range(65536) for color in this widget."""
 | 
				
			||||||
        COLOR in this widget."""
 | 
					 | 
				
			||||||
        return self._getints(
 | 
					        return self._getints(
 | 
				
			||||||
            self.tk.call('winfo', 'rgb', self._w, color))
 | 
					            self.tk.call('winfo', 'rgb', self._w, color))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,57 +8,69 @@
 | 
				
			||||||
# fixed initialcolor handling in August 1998
 | 
					# fixed initialcolor handling in August 1998
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# options (all have default values):
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# - initialcolor: color to mark as selected when dialog is displayed
 | 
					 | 
				
			||||||
#   (given as an RGB triplet or a Tk color string)
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# - parent: which window to place the dialog on top of
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# - title: dialog title
 | 
					 | 
				
			||||||
#
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
from tkinter.commondialog import Dialog
 | 
					from tkinter.commondialog import Dialog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = ["Chooser", "askcolor"]
 | 
					__all__ = ["Chooser", "askcolor"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					 | 
				
			||||||
# color chooser class
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Chooser(Dialog):
 | 
					class Chooser(Dialog):
 | 
				
			||||||
    "Ask for a color"
 | 
					    """Create a dialog for the tk_chooseColor command.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Args:
 | 
				
			||||||
 | 
					        master: The master widget for this dialog.  If not provided,
 | 
				
			||||||
 | 
					            defaults to options['parent'] (if defined).
 | 
				
			||||||
 | 
					        options: Dictionary of options for the tk_chooseColor call.
 | 
				
			||||||
 | 
					            initialcolor: Specifies the selected color when the
 | 
				
			||||||
 | 
					                dialog is first displayed.  This can be a tk color
 | 
				
			||||||
 | 
					                string or a 3-tuple of ints in the range (0, 255)
 | 
				
			||||||
 | 
					                for an RGB triplet.
 | 
				
			||||||
 | 
					            parent: The parent window of the color dialog.  The
 | 
				
			||||||
 | 
					                color dialog is displayed on top of this.
 | 
				
			||||||
 | 
					            title: A string for the title of the dialog box.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    command = "tk_chooseColor"
 | 
					    command = "tk_chooseColor"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _fixoptions(self):
 | 
					    def _fixoptions(self):
 | 
				
			||||||
 | 
					        """Ensure initialcolor is a tk color string.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Convert initialcolor from a RGB triplet to a color string.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
            # make sure initialcolor is a tk color string
 | 
					 | 
				
			||||||
            color = self.options["initialcolor"]
 | 
					            color = self.options["initialcolor"]
 | 
				
			||||||
            if isinstance(color, tuple):
 | 
					            if isinstance(color, tuple):
 | 
				
			||||||
                # assume an RGB triplet
 | 
					                # Assume an RGB triplet.
 | 
				
			||||||
                self.options["initialcolor"] = "#%02x%02x%02x" % color
 | 
					                self.options["initialcolor"] = "#%02x%02x%02x" % color
 | 
				
			||||||
        except KeyError:
 | 
					        except KeyError:
 | 
				
			||||||
            pass
 | 
					            pass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def _fixresult(self, widget, result):
 | 
					    def _fixresult(self, widget, result):
 | 
				
			||||||
        # result can be somethings: an empty tuple, an empty string or
 | 
					        """Adjust result returned from call to tk_chooseColor.
 | 
				
			||||||
        # a Tcl_Obj, so this somewhat weird check handles that
 | 
					
 | 
				
			||||||
 | 
					        Return both an RGB tuple of ints in the range (0, 255) and the
 | 
				
			||||||
 | 
					        tk color string in the form #rrggbb.
 | 
				
			||||||
 | 
					        """
 | 
				
			||||||
 | 
					        # Result can be many things: an empty tuple, an empty string, or
 | 
				
			||||||
 | 
					        # a _tkinter.Tcl_Obj, so this somewhat weird check handles that.
 | 
				
			||||||
        if not result or not str(result):
 | 
					        if not result or not str(result):
 | 
				
			||||||
            return None, None  # canceled
 | 
					            return None, None  # canceled
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # to simplify application code, the color chooser returns
 | 
					        # To simplify application code, the color chooser returns
 | 
				
			||||||
        # an RGB tuple together with the Tk color string
 | 
					        # an RGB tuple together with the Tk color string.
 | 
				
			||||||
        r, g, b = widget.winfo_rgb(result)
 | 
					        r, g, b = widget.winfo_rgb(result)
 | 
				
			||||||
        return (r/256, g/256, b/256), str(result)
 | 
					        return (r//256, g//256, b//256), str(result)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#
 | 
					#
 | 
				
			||||||
# convenience stuff
 | 
					# convenience stuff
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def askcolor(color=None, **options):
 | 
					def askcolor(color=None, **options):
 | 
				
			||||||
    "Ask for a color"
 | 
					    """Display dialog window for selection of a color.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Convenience wrapper for the Chooser class.  Displays the color
 | 
				
			||||||
 | 
					    chooser dialog with color as the initial value.
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if color:
 | 
					    if color:
 | 
				
			||||||
        options = options.copy()
 | 
					        options = options.copy()
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										43
									
								
								Lib/tkinter/test/test_tkinter/test_colorchooser.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								Lib/tkinter/test/test_tkinter/test_colorchooser.py
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					import unittest
 | 
				
			||||||
 | 
					import tkinter
 | 
				
			||||||
 | 
					from test.support import requires, run_unittest, swap_attr
 | 
				
			||||||
 | 
					from tkinter.test.support import AbstractTkTest
 | 
				
			||||||
 | 
					from tkinter import colorchooser
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					requires('gui')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ChooserTest(AbstractTkTest, unittest.TestCase):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def setUpClass(cls):
 | 
				
			||||||
 | 
					        AbstractTkTest.setUpClass.__func__(cls)
 | 
				
			||||||
 | 
					        cls.cc = colorchooser.Chooser(initialcolor='dark blue slate')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_fixoptions(self):
 | 
				
			||||||
 | 
					        cc = self.cc
 | 
				
			||||||
 | 
					        cc._fixoptions()
 | 
				
			||||||
 | 
					        self.assertEqual(cc.options['initialcolor'], 'dark blue slate')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cc.options['initialcolor'] = '#D2D269691E1E'
 | 
				
			||||||
 | 
					        cc._fixoptions()
 | 
				
			||||||
 | 
					        self.assertEqual(cc.options['initialcolor'], '#D2D269691E1E')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        cc.options['initialcolor'] = (210, 105, 30)
 | 
				
			||||||
 | 
					        cc._fixoptions()
 | 
				
			||||||
 | 
					        self.assertEqual(cc.options['initialcolor'], '#d2691e')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_fixresult(self):
 | 
				
			||||||
 | 
					        cc = self.cc
 | 
				
			||||||
 | 
					        self.assertEqual(cc._fixresult(self.root, ()), (None, None))
 | 
				
			||||||
 | 
					        self.assertEqual(cc._fixresult(self.root, ''), (None, None))
 | 
				
			||||||
 | 
					        self.assertEqual(cc._fixresult(self.root, 'chocolate'),
 | 
				
			||||||
 | 
					                         ((210, 105, 30), 'chocolate'))
 | 
				
			||||||
 | 
					        self.assertEqual(cc._fixresult(self.root, '#4a3c8c'),
 | 
				
			||||||
 | 
					                         ((74, 60, 140), '#4a3c8c'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					tests_gui = (ChooserTest,)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == "__main__":
 | 
				
			||||||
 | 
					    run_unittest(*tests_gui)
 | 
				
			||||||
| 
						 | 
					@ -192,6 +192,26 @@ def test_clipboard_astral(self):
 | 
				
			||||||
        with self.assertRaises(tkinter.TclError):
 | 
					        with self.assertRaises(tkinter.TclError):
 | 
				
			||||||
            root.clipboard_get()
 | 
					            root.clipboard_get()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def test_winfo_rgb(self):
 | 
				
			||||||
 | 
					        root = self.root
 | 
				
			||||||
 | 
					        rgb = root.winfo_rgb
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # Color name.
 | 
				
			||||||
 | 
					        self.assertEqual(rgb('red'), (65535, 0, 0))
 | 
				
			||||||
 | 
					        self.assertEqual(rgb('dark slate blue'), (18504, 15677, 35723))
 | 
				
			||||||
 | 
					        # #RGB - extends each 4-bit hex value to be 16-bit.
 | 
				
			||||||
 | 
					        self.assertEqual(rgb('#F0F'), (0xFFFF, 0x0000, 0xFFFF))
 | 
				
			||||||
 | 
					        # #RRGGBB - extends each 8-bit hex value to be 16-bit.
 | 
				
			||||||
 | 
					        self.assertEqual(rgb('#4a3c8c'), (0x4a4a, 0x3c3c, 0x8c8c))
 | 
				
			||||||
 | 
					        # #RRRRGGGGBBBB
 | 
				
			||||||
 | 
					        self.assertEqual(rgb('#dede14143939'), (0xdede, 0x1414, 0x3939))
 | 
				
			||||||
 | 
					        # Invalid string.
 | 
				
			||||||
 | 
					        with self.assertRaises(tkinter.TclError):
 | 
				
			||||||
 | 
					            rgb('#123456789a')
 | 
				
			||||||
 | 
					        # RGB triplet is invalid input.
 | 
				
			||||||
 | 
					        with self.assertRaises(tkinter.TclError):
 | 
				
			||||||
 | 
					            rgb((111, 78, 55))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def test_event_repr_defaults(self):
 | 
					    def test_event_repr_defaults(self):
 | 
				
			||||||
        e = tkinter.Event()
 | 
					        e = tkinter.Event()
 | 
				
			||||||
        e.serial = 12345
 | 
					        e.serial = 12345
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,2 @@
 | 
				
			||||||
 | 
					Correct call to :mod:`tkinter.colorchooser` to return RGB triplet of ints
 | 
				
			||||||
 | 
					instead of floats.  Patch by Cheryl Sabella.
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue