1import unittest 2import sys 3import tkinter 4from tkinter import ttk 5from test import support 6from test.support import requires, run_unittest 7from tkinter.test.support import AbstractTkTest 8 9requires('gui') 10 11CLASS_NAMES = [ 12 '.', 'ComboboxPopdownFrame', 'Heading', 13 'Horizontal.TProgressbar', 'Horizontal.TScale', 'Item', 'Sash', 14 'TButton', 'TCheckbutton', 'TCombobox', 'TEntry', 15 'TLabelframe', 'TLabelframe.Label', 'TMenubutton', 16 'TNotebook', 'TNotebook.Tab', 'Toolbutton', 'TProgressbar', 17 'TRadiobutton', 'Treeview', 'TScale', 'TScrollbar', 'TSpinbox', 18 'Vertical.TProgressbar', 'Vertical.TScale' 19] 20 21class StyleTest(AbstractTkTest, unittest.TestCase): 22 23 def setUp(self): 24 super().setUp() 25 self.style = ttk.Style(self.root) 26 27 28 def test_configure(self): 29 style = self.style 30 style.configure('TButton', background='yellow') 31 self.assertEqual(style.configure('TButton', 'background'), 32 'yellow') 33 self.assertIsInstance(style.configure('TButton'), dict) 34 35 36 def test_map(self): 37 style = self.style 38 39 # Single state 40 for states in ['active'], [('active',)]: 41 with self.subTest(states=states): 42 style.map('TButton', background=[(*states, 'white')]) 43 expected = [('active', 'white')] 44 self.assertEqual(style.map('TButton', 'background'), expected) 45 m = style.map('TButton') 46 self.assertIsInstance(m, dict) 47 self.assertEqual(m['background'], expected) 48 49 # Multiple states 50 for states in ['pressed', '!disabled'], ['pressed !disabled'], [('pressed', '!disabled')]: 51 with self.subTest(states=states): 52 style.map('TButton', background=[(*states, 'black')]) 53 expected = [('pressed', '!disabled', 'black')] 54 self.assertEqual(style.map('TButton', 'background'), expected) 55 m = style.map('TButton') 56 self.assertIsInstance(m, dict) 57 self.assertEqual(m['background'], expected) 58 59 # Default state 60 for states in [], [''], [()]: 61 with self.subTest(states=states): 62 style.map('TButton', background=[(*states, 'grey')]) 63 expected = [('grey',)] 64 self.assertEqual(style.map('TButton', 'background'), expected) 65 m = style.map('TButton') 66 self.assertIsInstance(m, dict) 67 self.assertEqual(m['background'], expected) 68 69 70 def test_lookup(self): 71 style = self.style 72 style.configure('TButton', background='yellow') 73 style.map('TButton', background=[('active', 'background', 'blue')]) 74 75 self.assertEqual(style.lookup('TButton', 'background'), 'yellow') 76 self.assertEqual(style.lookup('TButton', 'background', 77 ['active', 'background']), 'blue') 78 self.assertEqual(style.lookup('TButton', 'optionnotdefined', 79 default='iknewit'), 'iknewit') 80 81 82 def test_layout(self): 83 style = self.style 84 self.assertRaises(tkinter.TclError, style.layout, 'NotALayout') 85 tv_style = style.layout('Treeview') 86 87 # "erase" Treeview layout 88 style.layout('Treeview', '') 89 self.assertEqual(style.layout('Treeview'), 90 [('null', {'sticky': 'nswe'})] 91 ) 92 93 # restore layout 94 style.layout('Treeview', tv_style) 95 self.assertEqual(style.layout('Treeview'), tv_style) 96 97 # should return a list 98 self.assertIsInstance(style.layout('TButton'), list) 99 100 # correct layout, but "option" doesn't exist as option 101 self.assertRaises(tkinter.TclError, style.layout, 'Treeview', 102 [('name', {'option': 'inexistent'})]) 103 104 105 def test_theme_use(self): 106 self.assertRaises(tkinter.TclError, self.style.theme_use, 107 'nonexistingname') 108 109 curr_theme = self.style.theme_use() 110 new_theme = None 111 for theme in self.style.theme_names(): 112 if theme != curr_theme: 113 new_theme = theme 114 self.style.theme_use(theme) 115 break 116 else: 117 # just one theme available, can't go on with tests 118 return 119 120 self.assertFalse(curr_theme == new_theme) 121 self.assertFalse(new_theme != self.style.theme_use()) 122 123 self.style.theme_use(curr_theme) 124 125 126 def test_configure_custom_copy(self): 127 style = self.style 128 129 curr_theme = self.style.theme_use() 130 self.addCleanup(self.style.theme_use, curr_theme) 131 for theme in self.style.theme_names(): 132 self.style.theme_use(theme) 133 for name in CLASS_NAMES: 134 default = style.configure(name) 135 if not default: 136 continue 137 with self.subTest(theme=theme, name=name): 138 if support.verbose >= 2: 139 print('configure', theme, name, default) 140 if (theme in ('vista', 'xpnative') 141 and sys.getwindowsversion()[:2] == (6, 1)): 142 # Fails on the Windows 7 buildbot 143 continue 144 newname = f'C.{name}' 145 self.assertEqual(style.configure(newname), None) 146 style.configure(newname, **default) 147 self.assertEqual(style.configure(newname), default) 148 for key, value in default.items(): 149 self.assertEqual(style.configure(newname, key), value) 150 151 152 def test_map_custom_copy(self): 153 style = self.style 154 155 curr_theme = self.style.theme_use() 156 self.addCleanup(self.style.theme_use, curr_theme) 157 for theme in self.style.theme_names(): 158 self.style.theme_use(theme) 159 for name in CLASS_NAMES: 160 default = style.map(name) 161 if not default: 162 continue 163 with self.subTest(theme=theme, name=name): 164 if support.verbose >= 2: 165 print('map', theme, name, default) 166 if (theme in ('vista', 'xpnative') 167 and sys.getwindowsversion()[:2] == (6, 1)): 168 # Fails on the Windows 7 buildbot 169 continue 170 newname = f'C.{name}' 171 self.assertEqual(style.map(newname), {}) 172 style.map(newname, **default) 173 self.assertEqual(style.map(newname), default) 174 for key, value in default.items(): 175 self.assertEqual(style.map(newname, key), value) 176 177 178tests_gui = (StyleTest, ) 179 180if __name__ == "__main__": 181 run_unittest(*tests_gui) 182