test_geometry_managers.py 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906
  1. import unittest
  2. import re
  3. import tkinter
  4. from tkinter import TclError
  5. from test.support import requires
  6. from tkinter.test.support import pixels_conv, tcl_version, requires_tcl
  7. from tkinter.test.widget_tests import AbstractWidgetTest
  8. requires('gui')
  9. class PackTest(AbstractWidgetTest, unittest.TestCase):
  10. test_keys = None
  11. def create2(self):
  12. pack = tkinter.Toplevel(self.root, name='pack')
  13. pack.wm_geometry('300x200+0+0')
  14. pack.wm_minsize(1, 1)
  15. a = tkinter.Frame(pack, name='a', width=20, height=40, bg='red')
  16. b = tkinter.Frame(pack, name='b', width=50, height=30, bg='blue')
  17. c = tkinter.Frame(pack, name='c', width=80, height=80, bg='green')
  18. d = tkinter.Frame(pack, name='d', width=40, height=30, bg='yellow')
  19. return pack, a, b, c, d
  20. def test_pack_configure_after(self):
  21. pack, a, b, c, d = self.create2()
  22. with self.assertRaisesRegex(TclError, 'window "%s" isn\'t packed' % b):
  23. a.pack_configure(after=b)
  24. with self.assertRaisesRegex(TclError, 'bad window path name ".foo"'):
  25. a.pack_configure(after='.foo')
  26. a.pack_configure(side='top')
  27. b.pack_configure(side='top')
  28. c.pack_configure(side='top')
  29. d.pack_configure(side='top')
  30. self.assertEqual(pack.pack_slaves(), [a, b, c, d])
  31. a.pack_configure(after=b)
  32. self.assertEqual(pack.pack_slaves(), [b, a, c, d])
  33. a.pack_configure(after=a)
  34. self.assertEqual(pack.pack_slaves(), [b, a, c, d])
  35. def test_pack_configure_anchor(self):
  36. pack, a, b, c, d = self.create2()
  37. def check(anchor, geom):
  38. a.pack_configure(side='top', ipadx=5, padx=10, ipady=15, pady=20,
  39. expand=True, anchor=anchor)
  40. self.root.update()
  41. self.assertEqual(a.winfo_geometry(), geom)
  42. check('n', '30x70+135+20')
  43. check('ne', '30x70+260+20')
  44. check('e', '30x70+260+65')
  45. check('se', '30x70+260+110')
  46. check('s', '30x70+135+110')
  47. check('sw', '30x70+10+110')
  48. check('w', '30x70+10+65')
  49. check('nw', '30x70+10+20')
  50. check('center', '30x70+135+65')
  51. def test_pack_configure_before(self):
  52. pack, a, b, c, d = self.create2()
  53. with self.assertRaisesRegex(TclError, 'window "%s" isn\'t packed' % b):
  54. a.pack_configure(before=b)
  55. with self.assertRaisesRegex(TclError, 'bad window path name ".foo"'):
  56. a.pack_configure(before='.foo')
  57. a.pack_configure(side='top')
  58. b.pack_configure(side='top')
  59. c.pack_configure(side='top')
  60. d.pack_configure(side='top')
  61. self.assertEqual(pack.pack_slaves(), [a, b, c, d])
  62. a.pack_configure(before=d)
  63. self.assertEqual(pack.pack_slaves(), [b, c, a, d])
  64. a.pack_configure(before=a)
  65. self.assertEqual(pack.pack_slaves(), [b, c, a, d])
  66. def test_pack_configure_expand(self):
  67. pack, a, b, c, d = self.create2()
  68. def check(*geoms):
  69. self.root.update()
  70. self.assertEqual(a.winfo_geometry(), geoms[0])
  71. self.assertEqual(b.winfo_geometry(), geoms[1])
  72. self.assertEqual(c.winfo_geometry(), geoms[2])
  73. self.assertEqual(d.winfo_geometry(), geoms[3])
  74. a.pack_configure(side='left')
  75. b.pack_configure(side='top')
  76. c.pack_configure(side='right')
  77. d.pack_configure(side='bottom')
  78. check('20x40+0+80', '50x30+135+0', '80x80+220+75', '40x30+100+170')
  79. a.pack_configure(side='left', expand='yes')
  80. b.pack_configure(side='top', expand='on')
  81. c.pack_configure(side='right', expand=True)
  82. d.pack_configure(side='bottom', expand=1)
  83. check('20x40+40+80', '50x30+175+35', '80x80+180+110', '40x30+100+135')
  84. a.pack_configure(side='left', expand='yes', fill='both')
  85. b.pack_configure(side='top', expand='on', fill='both')
  86. c.pack_configure(side='right', expand=True, fill='both')
  87. d.pack_configure(side='bottom', expand=1, fill='both')
  88. check('100x200+0+0', '200x100+100+0', '160x100+140+100', '40x100+100+100')
  89. def test_pack_configure_in(self):
  90. pack, a, b, c, d = self.create2()
  91. a.pack_configure(side='top')
  92. b.pack_configure(side='top')
  93. c.pack_configure(side='top')
  94. d.pack_configure(side='top')
  95. a.pack_configure(in_=pack)
  96. self.assertEqual(pack.pack_slaves(), [b, c, d, a])
  97. a.pack_configure(in_=c)
  98. self.assertEqual(pack.pack_slaves(), [b, c, d])
  99. self.assertEqual(c.pack_slaves(), [a])
  100. with self.assertRaisesRegex(TclError,
  101. 'can\'t pack %s inside itself' % (a,)):
  102. a.pack_configure(in_=a)
  103. with self.assertRaisesRegex(TclError, 'bad window path name ".foo"'):
  104. a.pack_configure(in_='.foo')
  105. def test_pack_configure_padx_ipadx_fill(self):
  106. pack, a, b, c, d = self.create2()
  107. def check(geom1, geom2, **kwargs):
  108. a.pack_forget()
  109. b.pack_forget()
  110. a.pack_configure(**kwargs)
  111. b.pack_configure(expand=True, fill='both')
  112. self.root.update()
  113. self.assertEqual(a.winfo_geometry(), geom1)
  114. self.assertEqual(b.winfo_geometry(), geom2)
  115. check('20x40+260+80', '240x200+0+0', side='right', padx=20)
  116. check('20x40+250+80', '240x200+0+0', side='right', padx=(10, 30))
  117. check('60x40+240+80', '240x200+0+0', side='right', ipadx=20)
  118. check('30x40+260+80', '250x200+0+0', side='right', ipadx=5, padx=10)
  119. check('20x40+260+80', '240x200+0+0', side='right', padx=20, fill='x')
  120. check('20x40+249+80', '240x200+0+0',
  121. side='right', padx=(9, 31), fill='x')
  122. check('60x40+240+80', '240x200+0+0', side='right', ipadx=20, fill='x')
  123. check('30x40+260+80', '250x200+0+0',
  124. side='right', ipadx=5, padx=10, fill='x')
  125. check('30x40+255+80', '250x200+0+0',
  126. side='right', ipadx=5, padx=(5, 15), fill='x')
  127. check('20x40+140+0', '300x160+0+40', side='top', padx=20)
  128. check('20x40+120+0', '300x160+0+40', side='top', padx=(0, 40))
  129. check('60x40+120+0', '300x160+0+40', side='top', ipadx=20)
  130. check('30x40+135+0', '300x160+0+40', side='top', ipadx=5, padx=10)
  131. check('30x40+130+0', '300x160+0+40', side='top', ipadx=5, padx=(5, 15))
  132. check('260x40+20+0', '300x160+0+40', side='top', padx=20, fill='x')
  133. check('260x40+25+0', '300x160+0+40',
  134. side='top', padx=(25, 15), fill='x')
  135. check('300x40+0+0', '300x160+0+40', side='top', ipadx=20, fill='x')
  136. check('280x40+10+0', '300x160+0+40',
  137. side='top', ipadx=5, padx=10, fill='x')
  138. check('280x40+5+0', '300x160+0+40',
  139. side='top', ipadx=5, padx=(5, 15), fill='x')
  140. a.pack_configure(padx='1c')
  141. self.assertEqual(a.pack_info()['padx'],
  142. self._str(pack.winfo_pixels('1c')))
  143. a.pack_configure(ipadx='1c')
  144. self.assertEqual(a.pack_info()['ipadx'],
  145. self._str(pack.winfo_pixels('1c')))
  146. def test_pack_configure_pady_ipady_fill(self):
  147. pack, a, b, c, d = self.create2()
  148. def check(geom1, geom2, **kwargs):
  149. a.pack_forget()
  150. b.pack_forget()
  151. a.pack_configure(**kwargs)
  152. b.pack_configure(expand=True, fill='both')
  153. self.root.update()
  154. self.assertEqual(a.winfo_geometry(), geom1)
  155. self.assertEqual(b.winfo_geometry(), geom2)
  156. check('20x40+280+80', '280x200+0+0', side='right', pady=20)
  157. check('20x40+280+70', '280x200+0+0', side='right', pady=(10, 30))
  158. check('20x80+280+60', '280x200+0+0', side='right', ipady=20)
  159. check('20x50+280+75', '280x200+0+0', side='right', ipady=5, pady=10)
  160. check('20x40+280+80', '280x200+0+0', side='right', pady=20, fill='x')
  161. check('20x40+280+69', '280x200+0+0',
  162. side='right', pady=(9, 31), fill='x')
  163. check('20x80+280+60', '280x200+0+0', side='right', ipady=20, fill='x')
  164. check('20x50+280+75', '280x200+0+0',
  165. side='right', ipady=5, pady=10, fill='x')
  166. check('20x50+280+70', '280x200+0+0',
  167. side='right', ipady=5, pady=(5, 15), fill='x')
  168. check('20x40+140+20', '300x120+0+80', side='top', pady=20)
  169. check('20x40+140+0', '300x120+0+80', side='top', pady=(0, 40))
  170. check('20x80+140+0', '300x120+0+80', side='top', ipady=20)
  171. check('20x50+140+10', '300x130+0+70', side='top', ipady=5, pady=10)
  172. check('20x50+140+5', '300x130+0+70', side='top', ipady=5, pady=(5, 15))
  173. check('300x40+0+20', '300x120+0+80', side='top', pady=20, fill='x')
  174. check('300x40+0+25', '300x120+0+80',
  175. side='top', pady=(25, 15), fill='x')
  176. check('300x80+0+0', '300x120+0+80', side='top', ipady=20, fill='x')
  177. check('300x50+0+10', '300x130+0+70',
  178. side='top', ipady=5, pady=10, fill='x')
  179. check('300x50+0+5', '300x130+0+70',
  180. side='top', ipady=5, pady=(5, 15), fill='x')
  181. a.pack_configure(pady='1c')
  182. self.assertEqual(a.pack_info()['pady'],
  183. self._str(pack.winfo_pixels('1c')))
  184. a.pack_configure(ipady='1c')
  185. self.assertEqual(a.pack_info()['ipady'],
  186. self._str(pack.winfo_pixels('1c')))
  187. def test_pack_configure_side(self):
  188. pack, a, b, c, d = self.create2()
  189. def check(side, geom1, geom2):
  190. a.pack_configure(side=side)
  191. self.assertEqual(a.pack_info()['side'], side)
  192. b.pack_configure(expand=True, fill='both')
  193. self.root.update()
  194. self.assertEqual(a.winfo_geometry(), geom1)
  195. self.assertEqual(b.winfo_geometry(), geom2)
  196. check('top', '20x40+140+0', '300x160+0+40')
  197. check('bottom', '20x40+140+160', '300x160+0+0')
  198. check('left', '20x40+0+80', '280x200+20+0')
  199. check('right', '20x40+280+80', '280x200+0+0')
  200. def test_pack_forget(self):
  201. pack, a, b, c, d = self.create2()
  202. a.pack_configure()
  203. b.pack_configure()
  204. c.pack_configure()
  205. self.assertEqual(pack.pack_slaves(), [a, b, c])
  206. b.pack_forget()
  207. self.assertEqual(pack.pack_slaves(), [a, c])
  208. b.pack_forget()
  209. self.assertEqual(pack.pack_slaves(), [a, c])
  210. d.pack_forget()
  211. def test_pack_info(self):
  212. pack, a, b, c, d = self.create2()
  213. with self.assertRaisesRegex(TclError, 'window "%s" isn\'t packed' % a):
  214. a.pack_info()
  215. a.pack_configure()
  216. b.pack_configure(side='right', in_=a, anchor='s', expand=True, fill='x',
  217. ipadx=5, padx=10, ipady=2, pady=(5, 15))
  218. info = a.pack_info()
  219. self.assertIsInstance(info, dict)
  220. self.assertEqual(info['anchor'], 'center')
  221. self.assertEqual(info['expand'], self._str(0))
  222. self.assertEqual(info['fill'], 'none')
  223. self.assertEqual(info['in'], pack)
  224. self.assertEqual(info['ipadx'], self._str(0))
  225. self.assertEqual(info['ipady'], self._str(0))
  226. self.assertEqual(info['padx'], self._str(0))
  227. self.assertEqual(info['pady'], self._str(0))
  228. self.assertEqual(info['side'], 'top')
  229. info = b.pack_info()
  230. self.assertIsInstance(info, dict)
  231. self.assertEqual(info['anchor'], 's')
  232. self.assertEqual(info['expand'], self._str(1))
  233. self.assertEqual(info['fill'], 'x')
  234. self.assertEqual(info['in'], a)
  235. self.assertEqual(info['ipadx'], self._str(5))
  236. self.assertEqual(info['ipady'], self._str(2))
  237. self.assertEqual(info['padx'], self._str(10))
  238. self.assertEqual(info['pady'], self._str((5, 15)))
  239. self.assertEqual(info['side'], 'right')
  240. def test_pack_propagate(self):
  241. pack, a, b, c, d = self.create2()
  242. pack.configure(width=300, height=200)
  243. a.pack_configure()
  244. pack.pack_propagate(False)
  245. self.root.update()
  246. self.assertEqual(pack.winfo_reqwidth(), 300)
  247. self.assertEqual(pack.winfo_reqheight(), 200)
  248. pack.pack_propagate(True)
  249. self.root.update()
  250. self.assertEqual(pack.winfo_reqwidth(), 20)
  251. self.assertEqual(pack.winfo_reqheight(), 40)
  252. def test_pack_slaves(self):
  253. pack, a, b, c, d = self.create2()
  254. self.assertEqual(pack.pack_slaves(), [])
  255. a.pack_configure()
  256. self.assertEqual(pack.pack_slaves(), [a])
  257. b.pack_configure()
  258. self.assertEqual(pack.pack_slaves(), [a, b])
  259. class PlaceTest(AbstractWidgetTest, unittest.TestCase):
  260. test_keys = None
  261. def create2(self):
  262. t = tkinter.Toplevel(self.root, width=300, height=200, bd=0)
  263. t.wm_geometry('300x200+0+0')
  264. f = tkinter.Frame(t, width=154, height=84, bd=2, relief='raised')
  265. f.place_configure(x=48, y=38)
  266. f2 = tkinter.Frame(t, width=30, height=60, bd=2, relief='raised')
  267. self.root.update()
  268. return t, f, f2
  269. def test_place_configure_in(self):
  270. t, f, f2 = self.create2()
  271. self.assertEqual(f2.winfo_manager(), '')
  272. with self.assertRaisesRegex(TclError, "can't place %s relative to "
  273. "itself" % re.escape(str(f2))):
  274. f2.place_configure(in_=f2)
  275. if tcl_version >= (8, 5):
  276. self.assertEqual(f2.winfo_manager(), '')
  277. with self.assertRaisesRegex(TclError, 'bad window path name'):
  278. f2.place_configure(in_='spam')
  279. f2.place_configure(in_=f)
  280. self.assertEqual(f2.winfo_manager(), 'place')
  281. def test_place_configure_x(self):
  282. t, f, f2 = self.create2()
  283. f2.place_configure(in_=f)
  284. self.assertEqual(f2.place_info()['x'], '0')
  285. self.root.update()
  286. self.assertEqual(f2.winfo_x(), 50)
  287. f2.place_configure(x=100)
  288. self.assertEqual(f2.place_info()['x'], '100')
  289. self.root.update()
  290. self.assertEqual(f2.winfo_x(), 150)
  291. f2.place_configure(x=-10, relx=1)
  292. self.assertEqual(f2.place_info()['x'], '-10')
  293. self.root.update()
  294. self.assertEqual(f2.winfo_x(), 190)
  295. with self.assertRaisesRegex(TclError, 'bad screen distance "spam"'):
  296. f2.place_configure(in_=f, x='spam')
  297. def test_place_configure_y(self):
  298. t, f, f2 = self.create2()
  299. f2.place_configure(in_=f)
  300. self.assertEqual(f2.place_info()['y'], '0')
  301. self.root.update()
  302. self.assertEqual(f2.winfo_y(), 40)
  303. f2.place_configure(y=50)
  304. self.assertEqual(f2.place_info()['y'], '50')
  305. self.root.update()
  306. self.assertEqual(f2.winfo_y(), 90)
  307. f2.place_configure(y=-10, rely=1)
  308. self.assertEqual(f2.place_info()['y'], '-10')
  309. self.root.update()
  310. self.assertEqual(f2.winfo_y(), 110)
  311. with self.assertRaisesRegex(TclError, 'bad screen distance "spam"'):
  312. f2.place_configure(in_=f, y='spam')
  313. def test_place_configure_relx(self):
  314. t, f, f2 = self.create2()
  315. f2.place_configure(in_=f)
  316. self.assertEqual(f2.place_info()['relx'], '0')
  317. self.root.update()
  318. self.assertEqual(f2.winfo_x(), 50)
  319. f2.place_configure(relx=0.5)
  320. self.assertEqual(f2.place_info()['relx'], '0.5')
  321. self.root.update()
  322. self.assertEqual(f2.winfo_x(), 125)
  323. f2.place_configure(relx=1)
  324. self.assertEqual(f2.place_info()['relx'], '1')
  325. self.root.update()
  326. self.assertEqual(f2.winfo_x(), 200)
  327. with self.assertRaisesRegex(TclError, 'expected floating-point number '
  328. 'but got "spam"'):
  329. f2.place_configure(in_=f, relx='spam')
  330. def test_place_configure_rely(self):
  331. t, f, f2 = self.create2()
  332. f2.place_configure(in_=f)
  333. self.assertEqual(f2.place_info()['rely'], '0')
  334. self.root.update()
  335. self.assertEqual(f2.winfo_y(), 40)
  336. f2.place_configure(rely=0.5)
  337. self.assertEqual(f2.place_info()['rely'], '0.5')
  338. self.root.update()
  339. self.assertEqual(f2.winfo_y(), 80)
  340. f2.place_configure(rely=1)
  341. self.assertEqual(f2.place_info()['rely'], '1')
  342. self.root.update()
  343. self.assertEqual(f2.winfo_y(), 120)
  344. with self.assertRaisesRegex(TclError, 'expected floating-point number '
  345. 'but got "spam"'):
  346. f2.place_configure(in_=f, rely='spam')
  347. def test_place_configure_anchor(self):
  348. f = tkinter.Frame(self.root)
  349. with self.assertRaisesRegex(TclError, 'bad anchor "j"'):
  350. f.place_configure(anchor='j')
  351. with self.assertRaisesRegex(TclError, 'ambiguous anchor ""'):
  352. f.place_configure(anchor='')
  353. for value in 'n', 'ne', 'e', 'se', 's', 'sw', 'w', 'nw', 'center':
  354. f.place_configure(anchor=value)
  355. self.assertEqual(f.place_info()['anchor'], value)
  356. def test_place_configure_width(self):
  357. t, f, f2 = self.create2()
  358. f2.place_configure(in_=f, width=120)
  359. self.root.update()
  360. self.assertEqual(f2.winfo_width(), 120)
  361. f2.place_configure(width='')
  362. self.root.update()
  363. self.assertEqual(f2.winfo_width(), 30)
  364. with self.assertRaisesRegex(TclError, 'bad screen distance "abcd"'):
  365. f2.place_configure(width='abcd')
  366. def test_place_configure_height(self):
  367. t, f, f2 = self.create2()
  368. f2.place_configure(in_=f, height=120)
  369. self.root.update()
  370. self.assertEqual(f2.winfo_height(), 120)
  371. f2.place_configure(height='')
  372. self.root.update()
  373. self.assertEqual(f2.winfo_height(), 60)
  374. with self.assertRaisesRegex(TclError, 'bad screen distance "abcd"'):
  375. f2.place_configure(height='abcd')
  376. def test_place_configure_relwidth(self):
  377. t, f, f2 = self.create2()
  378. f2.place_configure(in_=f, relwidth=0.5)
  379. self.root.update()
  380. self.assertEqual(f2.winfo_width(), 75)
  381. f2.place_configure(relwidth='')
  382. self.root.update()
  383. self.assertEqual(f2.winfo_width(), 30)
  384. with self.assertRaisesRegex(TclError, 'expected floating-point number '
  385. 'but got "abcd"'):
  386. f2.place_configure(relwidth='abcd')
  387. def test_place_configure_relheight(self):
  388. t, f, f2 = self.create2()
  389. f2.place_configure(in_=f, relheight=0.5)
  390. self.root.update()
  391. self.assertEqual(f2.winfo_height(), 40)
  392. f2.place_configure(relheight='')
  393. self.root.update()
  394. self.assertEqual(f2.winfo_height(), 60)
  395. with self.assertRaisesRegex(TclError, 'expected floating-point number '
  396. 'but got "abcd"'):
  397. f2.place_configure(relheight='abcd')
  398. def test_place_configure_bordermode(self):
  399. f = tkinter.Frame(self.root)
  400. with self.assertRaisesRegex(TclError, 'bad bordermode "j"'):
  401. f.place_configure(bordermode='j')
  402. with self.assertRaisesRegex(TclError, 'ambiguous bordermode ""'):
  403. f.place_configure(bordermode='')
  404. for value in 'inside', 'outside', 'ignore':
  405. f.place_configure(bordermode=value)
  406. self.assertEqual(f.place_info()['bordermode'], value)
  407. def test_place_forget(self):
  408. foo = tkinter.Frame(self.root)
  409. foo.place_configure(width=50, height=50)
  410. self.root.update()
  411. foo.place_forget()
  412. self.root.update()
  413. self.assertFalse(foo.winfo_ismapped())
  414. with self.assertRaises(TypeError):
  415. foo.place_forget(0)
  416. def test_place_info(self):
  417. t, f, f2 = self.create2()
  418. f2.place_configure(in_=f, x=1, y=2, width=3, height=4,
  419. relx=0.1, rely=0.2, relwidth=0.3, relheight=0.4,
  420. anchor='se', bordermode='outside')
  421. info = f2.place_info()
  422. self.assertIsInstance(info, dict)
  423. self.assertEqual(info['x'], '1')
  424. self.assertEqual(info['y'], '2')
  425. self.assertEqual(info['width'], '3')
  426. self.assertEqual(info['height'], '4')
  427. self.assertEqual(info['relx'], '0.1')
  428. self.assertEqual(info['rely'], '0.2')
  429. self.assertEqual(info['relwidth'], '0.3')
  430. self.assertEqual(info['relheight'], '0.4')
  431. self.assertEqual(info['anchor'], 'se')
  432. self.assertEqual(info['bordermode'], 'outside')
  433. self.assertEqual(info['x'], '1')
  434. self.assertEqual(info['x'], '1')
  435. with self.assertRaises(TypeError):
  436. f2.place_info(0)
  437. def test_place_slaves(self):
  438. foo = tkinter.Frame(self.root)
  439. bar = tkinter.Frame(self.root)
  440. self.assertEqual(foo.place_slaves(), [])
  441. bar.place_configure(in_=foo)
  442. self.assertEqual(foo.place_slaves(), [bar])
  443. with self.assertRaises(TypeError):
  444. foo.place_slaves(0)
  445. class GridTest(AbstractWidgetTest, unittest.TestCase):
  446. test_keys = None
  447. def tearDown(self):
  448. cols, rows = self.root.grid_size()
  449. for i in range(cols + 1):
  450. self.root.grid_columnconfigure(i, weight=0, minsize=0, pad=0, uniform='')
  451. for i in range(rows + 1):
  452. self.root.grid_rowconfigure(i, weight=0, minsize=0, pad=0, uniform='')
  453. self.root.grid_propagate(1)
  454. if tcl_version >= (8, 5):
  455. self.root.grid_anchor('nw')
  456. super().tearDown()
  457. def test_grid_configure(self):
  458. b = tkinter.Button(self.root)
  459. self.assertEqual(b.grid_info(), {})
  460. b.grid_configure()
  461. self.assertEqual(b.grid_info()['in'], self.root)
  462. self.assertEqual(b.grid_info()['column'], self._str(0))
  463. self.assertEqual(b.grid_info()['row'], self._str(0))
  464. b.grid_configure({'column': 1}, row=2)
  465. self.assertEqual(b.grid_info()['column'], self._str(1))
  466. self.assertEqual(b.grid_info()['row'], self._str(2))
  467. def test_grid_configure_column(self):
  468. b = tkinter.Button(self.root)
  469. with self.assertRaisesRegex(TclError, 'bad column value "-1": '
  470. 'must be a non-negative integer'):
  471. b.grid_configure(column=-1)
  472. b.grid_configure(column=2)
  473. self.assertEqual(b.grid_info()['column'], self._str(2))
  474. def test_grid_configure_columnspan(self):
  475. b = tkinter.Button(self.root)
  476. with self.assertRaisesRegex(TclError, 'bad columnspan value "0": '
  477. 'must be a positive integer'):
  478. b.grid_configure(columnspan=0)
  479. b.grid_configure(columnspan=2)
  480. self.assertEqual(b.grid_info()['columnspan'], self._str(2))
  481. def test_grid_configure_in(self):
  482. f = tkinter.Frame(self.root)
  483. b = tkinter.Button(self.root)
  484. self.assertEqual(b.grid_info(), {})
  485. b.grid_configure()
  486. self.assertEqual(b.grid_info()['in'], self.root)
  487. b.grid_configure(in_=f)
  488. self.assertEqual(b.grid_info()['in'], f)
  489. b.grid_configure({'in': self.root})
  490. self.assertEqual(b.grid_info()['in'], self.root)
  491. def test_grid_configure_ipadx(self):
  492. b = tkinter.Button(self.root)
  493. with self.assertRaisesRegex(TclError, 'bad ipadx value "-1": '
  494. 'must be positive screen distance'):
  495. b.grid_configure(ipadx=-1)
  496. b.grid_configure(ipadx=1)
  497. self.assertEqual(b.grid_info()['ipadx'], self._str(1))
  498. b.grid_configure(ipadx='.5c')
  499. self.assertEqual(b.grid_info()['ipadx'],
  500. self._str(round(pixels_conv('.5c') * self.scaling)))
  501. def test_grid_configure_ipady(self):
  502. b = tkinter.Button(self.root)
  503. with self.assertRaisesRegex(TclError, 'bad ipady value "-1": '
  504. 'must be positive screen distance'):
  505. b.grid_configure(ipady=-1)
  506. b.grid_configure(ipady=1)
  507. self.assertEqual(b.grid_info()['ipady'], self._str(1))
  508. b.grid_configure(ipady='.5c')
  509. self.assertEqual(b.grid_info()['ipady'],
  510. self._str(round(pixels_conv('.5c') * self.scaling)))
  511. def test_grid_configure_padx(self):
  512. b = tkinter.Button(self.root)
  513. with self.assertRaisesRegex(TclError, 'bad pad value "-1": '
  514. 'must be positive screen distance'):
  515. b.grid_configure(padx=-1)
  516. b.grid_configure(padx=1)
  517. self.assertEqual(b.grid_info()['padx'], self._str(1))
  518. b.grid_configure(padx=(10, 5))
  519. self.assertEqual(b.grid_info()['padx'], self._str((10, 5)))
  520. b.grid_configure(padx='.5c')
  521. self.assertEqual(b.grid_info()['padx'],
  522. self._str(round(pixels_conv('.5c') * self.scaling)))
  523. def test_grid_configure_pady(self):
  524. b = tkinter.Button(self.root)
  525. with self.assertRaisesRegex(TclError, 'bad pad value "-1": '
  526. 'must be positive screen distance'):
  527. b.grid_configure(pady=-1)
  528. b.grid_configure(pady=1)
  529. self.assertEqual(b.grid_info()['pady'], self._str(1))
  530. b.grid_configure(pady=(10, 5))
  531. self.assertEqual(b.grid_info()['pady'], self._str((10, 5)))
  532. b.grid_configure(pady='.5c')
  533. self.assertEqual(b.grid_info()['pady'],
  534. self._str(round(pixels_conv('.5c') * self.scaling)))
  535. def test_grid_configure_row(self):
  536. b = tkinter.Button(self.root)
  537. with self.assertRaisesRegex(TclError, 'bad (row|grid) value "-1": '
  538. 'must be a non-negative integer'):
  539. b.grid_configure(row=-1)
  540. b.grid_configure(row=2)
  541. self.assertEqual(b.grid_info()['row'], self._str(2))
  542. def test_grid_configure_rownspan(self):
  543. b = tkinter.Button(self.root)
  544. with self.assertRaisesRegex(TclError, 'bad rowspan value "0": '
  545. 'must be a positive integer'):
  546. b.grid_configure(rowspan=0)
  547. b.grid_configure(rowspan=2)
  548. self.assertEqual(b.grid_info()['rowspan'], self._str(2))
  549. def test_grid_configure_sticky(self):
  550. f = tkinter.Frame(self.root, bg='red')
  551. with self.assertRaisesRegex(TclError, 'bad stickyness value "glue"'):
  552. f.grid_configure(sticky='glue')
  553. f.grid_configure(sticky='ne')
  554. self.assertEqual(f.grid_info()['sticky'], 'ne')
  555. f.grid_configure(sticky='n,s,e,w')
  556. self.assertEqual(f.grid_info()['sticky'], 'nesw')
  557. def test_grid_columnconfigure(self):
  558. with self.assertRaises(TypeError):
  559. self.root.grid_columnconfigure()
  560. self.assertEqual(self.root.grid_columnconfigure(0),
  561. {'minsize': 0, 'pad': 0, 'uniform': None, 'weight': 0})
  562. with self.assertRaisesRegex(TclError, 'bad option "-foo"'):
  563. self.root.grid_columnconfigure(0, 'foo')
  564. self.root.grid_columnconfigure((0, 3), weight=2)
  565. with self.assertRaisesRegex(TclError,
  566. 'must specify a single element on retrieval'):
  567. self.root.grid_columnconfigure((0, 3))
  568. b = tkinter.Button(self.root)
  569. b.grid_configure(column=0, row=0)
  570. if tcl_version >= (8, 5):
  571. self.root.grid_columnconfigure('all', weight=3)
  572. with self.assertRaisesRegex(TclError, 'expected integer but got "all"'):
  573. self.root.grid_columnconfigure('all')
  574. self.assertEqual(self.root.grid_columnconfigure(0, 'weight'), 3)
  575. self.assertEqual(self.root.grid_columnconfigure(3, 'weight'), 2)
  576. self.assertEqual(self.root.grid_columnconfigure(265, 'weight'), 0)
  577. if tcl_version >= (8, 5):
  578. self.root.grid_columnconfigure(b, weight=4)
  579. self.assertEqual(self.root.grid_columnconfigure(0, 'weight'), 4)
  580. def test_grid_columnconfigure_minsize(self):
  581. with self.assertRaisesRegex(TclError, 'bad screen distance "foo"'):
  582. self.root.grid_columnconfigure(0, minsize='foo')
  583. self.root.grid_columnconfigure(0, minsize=10)
  584. self.assertEqual(self.root.grid_columnconfigure(0, 'minsize'), 10)
  585. self.assertEqual(self.root.grid_columnconfigure(0)['minsize'], 10)
  586. def test_grid_columnconfigure_weight(self):
  587. with self.assertRaisesRegex(TclError, 'expected integer but got "bad"'):
  588. self.root.grid_columnconfigure(0, weight='bad')
  589. with self.assertRaisesRegex(TclError, 'invalid arg "-weight": '
  590. 'should be non-negative'):
  591. self.root.grid_columnconfigure(0, weight=-3)
  592. self.root.grid_columnconfigure(0, weight=3)
  593. self.assertEqual(self.root.grid_columnconfigure(0, 'weight'), 3)
  594. self.assertEqual(self.root.grid_columnconfigure(0)['weight'], 3)
  595. def test_grid_columnconfigure_pad(self):
  596. with self.assertRaisesRegex(TclError, 'bad screen distance "foo"'):
  597. self.root.grid_columnconfigure(0, pad='foo')
  598. with self.assertRaisesRegex(TclError, 'invalid arg "-pad": '
  599. 'should be non-negative'):
  600. self.root.grid_columnconfigure(0, pad=-3)
  601. self.root.grid_columnconfigure(0, pad=3)
  602. self.assertEqual(self.root.grid_columnconfigure(0, 'pad'), 3)
  603. self.assertEqual(self.root.grid_columnconfigure(0)['pad'], 3)
  604. def test_grid_columnconfigure_uniform(self):
  605. self.root.grid_columnconfigure(0, uniform='foo')
  606. self.assertEqual(self.root.grid_columnconfigure(0, 'uniform'), 'foo')
  607. self.assertEqual(self.root.grid_columnconfigure(0)['uniform'], 'foo')
  608. def test_grid_rowconfigure(self):
  609. with self.assertRaises(TypeError):
  610. self.root.grid_rowconfigure()
  611. self.assertEqual(self.root.grid_rowconfigure(0),
  612. {'minsize': 0, 'pad': 0, 'uniform': None, 'weight': 0})
  613. with self.assertRaisesRegex(TclError, 'bad option "-foo"'):
  614. self.root.grid_rowconfigure(0, 'foo')
  615. self.root.grid_rowconfigure((0, 3), weight=2)
  616. with self.assertRaisesRegex(TclError,
  617. 'must specify a single element on retrieval'):
  618. self.root.grid_rowconfigure((0, 3))
  619. b = tkinter.Button(self.root)
  620. b.grid_configure(column=0, row=0)
  621. if tcl_version >= (8, 5):
  622. self.root.grid_rowconfigure('all', weight=3)
  623. with self.assertRaisesRegex(TclError, 'expected integer but got "all"'):
  624. self.root.grid_rowconfigure('all')
  625. self.assertEqual(self.root.grid_rowconfigure(0, 'weight'), 3)
  626. self.assertEqual(self.root.grid_rowconfigure(3, 'weight'), 2)
  627. self.assertEqual(self.root.grid_rowconfigure(265, 'weight'), 0)
  628. if tcl_version >= (8, 5):
  629. self.root.grid_rowconfigure(b, weight=4)
  630. self.assertEqual(self.root.grid_rowconfigure(0, 'weight'), 4)
  631. def test_grid_rowconfigure_minsize(self):
  632. with self.assertRaisesRegex(TclError, 'bad screen distance "foo"'):
  633. self.root.grid_rowconfigure(0, minsize='foo')
  634. self.root.grid_rowconfigure(0, minsize=10)
  635. self.assertEqual(self.root.grid_rowconfigure(0, 'minsize'), 10)
  636. self.assertEqual(self.root.grid_rowconfigure(0)['minsize'], 10)
  637. def test_grid_rowconfigure_weight(self):
  638. with self.assertRaisesRegex(TclError, 'expected integer but got "bad"'):
  639. self.root.grid_rowconfigure(0, weight='bad')
  640. with self.assertRaisesRegex(TclError, 'invalid arg "-weight": '
  641. 'should be non-negative'):
  642. self.root.grid_rowconfigure(0, weight=-3)
  643. self.root.grid_rowconfigure(0, weight=3)
  644. self.assertEqual(self.root.grid_rowconfigure(0, 'weight'), 3)
  645. self.assertEqual(self.root.grid_rowconfigure(0)['weight'], 3)
  646. def test_grid_rowconfigure_pad(self):
  647. with self.assertRaisesRegex(TclError, 'bad screen distance "foo"'):
  648. self.root.grid_rowconfigure(0, pad='foo')
  649. with self.assertRaisesRegex(TclError, 'invalid arg "-pad": '
  650. 'should be non-negative'):
  651. self.root.grid_rowconfigure(0, pad=-3)
  652. self.root.grid_rowconfigure(0, pad=3)
  653. self.assertEqual(self.root.grid_rowconfigure(0, 'pad'), 3)
  654. self.assertEqual(self.root.grid_rowconfigure(0)['pad'], 3)
  655. def test_grid_rowconfigure_uniform(self):
  656. self.root.grid_rowconfigure(0, uniform='foo')
  657. self.assertEqual(self.root.grid_rowconfigure(0, 'uniform'), 'foo')
  658. self.assertEqual(self.root.grid_rowconfigure(0)['uniform'], 'foo')
  659. def test_grid_forget(self):
  660. b = tkinter.Button(self.root)
  661. c = tkinter.Button(self.root)
  662. b.grid_configure(row=2, column=2, rowspan=2, columnspan=2,
  663. padx=3, pady=4, sticky='ns')
  664. self.assertEqual(self.root.grid_slaves(), [b])
  665. b.grid_forget()
  666. c.grid_forget()
  667. self.assertEqual(self.root.grid_slaves(), [])
  668. self.assertEqual(b.grid_info(), {})
  669. b.grid_configure(row=0, column=0)
  670. info = b.grid_info()
  671. self.assertEqual(info['row'], self._str(0))
  672. self.assertEqual(info['column'], self._str(0))
  673. self.assertEqual(info['rowspan'], self._str(1))
  674. self.assertEqual(info['columnspan'], self._str(1))
  675. self.assertEqual(info['padx'], self._str(0))
  676. self.assertEqual(info['pady'], self._str(0))
  677. self.assertEqual(info['sticky'], '')
  678. def test_grid_remove(self):
  679. b = tkinter.Button(self.root)
  680. c = tkinter.Button(self.root)
  681. b.grid_configure(row=2, column=2, rowspan=2, columnspan=2,
  682. padx=3, pady=4, sticky='ns')
  683. self.assertEqual(self.root.grid_slaves(), [b])
  684. b.grid_remove()
  685. c.grid_remove()
  686. self.assertEqual(self.root.grid_slaves(), [])
  687. self.assertEqual(b.grid_info(), {})
  688. b.grid_configure(row=0, column=0)
  689. info = b.grid_info()
  690. self.assertEqual(info['row'], self._str(0))
  691. self.assertEqual(info['column'], self._str(0))
  692. self.assertEqual(info['rowspan'], self._str(2))
  693. self.assertEqual(info['columnspan'], self._str(2))
  694. self.assertEqual(info['padx'], self._str(3))
  695. self.assertEqual(info['pady'], self._str(4))
  696. self.assertEqual(info['sticky'], 'ns')
  697. def test_grid_info(self):
  698. b = tkinter.Button(self.root)
  699. self.assertEqual(b.grid_info(), {})
  700. b.grid_configure(row=2, column=2, rowspan=2, columnspan=2,
  701. padx=3, pady=4, sticky='ns')
  702. info = b.grid_info()
  703. self.assertIsInstance(info, dict)
  704. self.assertEqual(info['in'], self.root)
  705. self.assertEqual(info['row'], self._str(2))
  706. self.assertEqual(info['column'], self._str(2))
  707. self.assertEqual(info['rowspan'], self._str(2))
  708. self.assertEqual(info['columnspan'], self._str(2))
  709. self.assertEqual(info['padx'], self._str(3))
  710. self.assertEqual(info['pady'], self._str(4))
  711. self.assertEqual(info['sticky'], 'ns')
  712. @requires_tcl(8, 5)
  713. def test_grid_anchor(self):
  714. with self.assertRaisesRegex(TclError, 'bad anchor "x"'):
  715. self.root.grid_anchor('x')
  716. with self.assertRaisesRegex(TclError, 'ambiguous anchor ""'):
  717. self.root.grid_anchor('')
  718. with self.assertRaises(TypeError):
  719. self.root.grid_anchor('se', 'nw')
  720. self.root.grid_anchor('se')
  721. self.assertEqual(self.root.tk.call('grid', 'anchor', self.root), 'se')
  722. def test_grid_bbox(self):
  723. self.assertEqual(self.root.grid_bbox(), (0, 0, 0, 0))
  724. self.assertEqual(self.root.grid_bbox(0, 0), (0, 0, 0, 0))
  725. self.assertEqual(self.root.grid_bbox(0, 0, 1, 1), (0, 0, 0, 0))
  726. with self.assertRaisesRegex(TclError, 'expected integer but got "x"'):
  727. self.root.grid_bbox('x', 0)
  728. with self.assertRaisesRegex(TclError, 'expected integer but got "x"'):
  729. self.root.grid_bbox(0, 'x')
  730. with self.assertRaisesRegex(TclError, 'expected integer but got "x"'):
  731. self.root.grid_bbox(0, 0, 'x', 0)
  732. with self.assertRaisesRegex(TclError, 'expected integer but got "x"'):
  733. self.root.grid_bbox(0, 0, 0, 'x')
  734. with self.assertRaises(TypeError):
  735. self.root.grid_bbox(0, 0, 0, 0, 0)
  736. t = self.root
  737. # de-maximize
  738. t.wm_geometry('1x1+0+0')
  739. t.wm_geometry('')
  740. f1 = tkinter.Frame(t, width=75, height=75, bg='red')
  741. f2 = tkinter.Frame(t, width=90, height=90, bg='blue')
  742. f1.grid_configure(row=0, column=0)
  743. f2.grid_configure(row=1, column=1)
  744. self.root.update()
  745. self.assertEqual(t.grid_bbox(), (0, 0, 165, 165))
  746. self.assertEqual(t.grid_bbox(0, 0), (0, 0, 75, 75))
  747. self.assertEqual(t.grid_bbox(0, 0, 1, 1), (0, 0, 165, 165))
  748. self.assertEqual(t.grid_bbox(1, 1), (75, 75, 90, 90))
  749. self.assertEqual(t.grid_bbox(10, 10, 0, 0), (0, 0, 165, 165))
  750. self.assertEqual(t.grid_bbox(-2, -2, -1, -1), (0, 0, 0, 0))
  751. self.assertEqual(t.grid_bbox(10, 10, 12, 12), (165, 165, 0, 0))
  752. def test_grid_location(self):
  753. with self.assertRaises(TypeError):
  754. self.root.grid_location()
  755. with self.assertRaises(TypeError):
  756. self.root.grid_location(0)
  757. with self.assertRaises(TypeError):
  758. self.root.grid_location(0, 0, 0)
  759. with self.assertRaisesRegex(TclError, 'bad screen distance "x"'):
  760. self.root.grid_location('x', 'y')
  761. with self.assertRaisesRegex(TclError, 'bad screen distance "y"'):
  762. self.root.grid_location('1c', 'y')
  763. t = self.root
  764. # de-maximize
  765. t.wm_geometry('1x1+0+0')
  766. t.wm_geometry('')
  767. f = tkinter.Frame(t, width=200, height=100,
  768. highlightthickness=0, bg='red')
  769. self.assertEqual(f.grid_location(10, 10), (-1, -1))
  770. f.grid_configure()
  771. self.root.update()
  772. self.assertEqual(t.grid_location(-10, -10), (-1, -1))
  773. self.assertEqual(t.grid_location(-10, 0), (-1, 0))
  774. self.assertEqual(t.grid_location(-1, 0), (-1, 0))
  775. self.assertEqual(t.grid_location(0, -10), (0, -1))
  776. self.assertEqual(t.grid_location(0, -1), (0, -1))
  777. self.assertEqual(t.grid_location(0, 0), (0, 0))
  778. self.assertEqual(t.grid_location(200, 0), (0, 0))
  779. self.assertEqual(t.grid_location(201, 0), (1, 0))
  780. self.assertEqual(t.grid_location(0, 100), (0, 0))
  781. self.assertEqual(t.grid_location(0, 101), (0, 1))
  782. self.assertEqual(t.grid_location(201, 101), (1, 1))
  783. def test_grid_propagate(self):
  784. self.assertEqual(self.root.grid_propagate(), True)
  785. with self.assertRaises(TypeError):
  786. self.root.grid_propagate(False, False)
  787. self.root.grid_propagate(False)
  788. self.assertFalse(self.root.grid_propagate())
  789. f = tkinter.Frame(self.root, width=100, height=100, bg='red')
  790. f.grid_configure(row=0, column=0)
  791. self.root.update()
  792. self.assertEqual(f.winfo_width(), 100)
  793. self.assertEqual(f.winfo_height(), 100)
  794. f.grid_propagate(False)
  795. g = tkinter.Frame(self.root, width=75, height=85, bg='green')
  796. g.grid_configure(in_=f, row=0, column=0)
  797. self.root.update()
  798. self.assertEqual(f.winfo_width(), 100)
  799. self.assertEqual(f.winfo_height(), 100)
  800. f.grid_propagate(True)
  801. self.root.update()
  802. self.assertEqual(f.winfo_width(), 75)
  803. self.assertEqual(f.winfo_height(), 85)
  804. def test_grid_size(self):
  805. with self.assertRaises(TypeError):
  806. self.root.grid_size(0)
  807. self.assertEqual(self.root.grid_size(), (0, 0))
  808. f = tkinter.Scale(self.root)
  809. f.grid_configure(row=0, column=0)
  810. self.assertEqual(self.root.grid_size(), (1, 1))
  811. f.grid_configure(row=4, column=5)
  812. self.assertEqual(self.root.grid_size(), (6, 5))
  813. def test_grid_slaves(self):
  814. self.assertEqual(self.root.grid_slaves(), [])
  815. a = tkinter.Label(self.root)
  816. a.grid_configure(row=0, column=1)
  817. b = tkinter.Label(self.root)
  818. b.grid_configure(row=1, column=0)
  819. c = tkinter.Label(self.root)
  820. c.grid_configure(row=1, column=1)
  821. d = tkinter.Label(self.root)
  822. d.grid_configure(row=1, column=1)
  823. self.assertEqual(self.root.grid_slaves(), [d, c, b, a])
  824. self.assertEqual(self.root.grid_slaves(row=0), [a])
  825. self.assertEqual(self.root.grid_slaves(row=1), [d, c, b])
  826. self.assertEqual(self.root.grid_slaves(column=0), [b])
  827. self.assertEqual(self.root.grid_slaves(column=1), [d, c, a])
  828. self.assertEqual(self.root.grid_slaves(row=1, column=1), [d, c])
  829. tests_gui = (
  830. PackTest, PlaceTest, GridTest,
  831. )
  832. if __name__ == '__main__':
  833. unittest.main()