1#!/usr/bin/env python 2 3# This is a rough collection of tests that can not be automated. 4# To add a new test, create a function with name ending in '_test'. 5 6import os 7import string 8import time 9import sys 10import Test 11import Tkinter 12import Pmw 13 14# ---------------------------------------------------------------------- 15 16def scrolledframeflashing_test(): 17 # Script which demonstrates continuous flashing of dynamic scrollbars 18 # in Pmw.ScrolledFrame. 19 # 20 # When this script is run, the two scrollbars will be continuously 21 # mapped and unmapped and the window will continuously change size. 22 23 frame = Tkinter.Frame(root) 24 frame.pack(fill = 'both', expand = 1) 25 26 sf = Pmw.ScrolledFrame(frame, borderframe = 0) 27 sf.pack(fill = 'both', expand = 1) 28 29 inner = Tkinter.Frame(sf.interior(), 30 width = 401, 31 height = 300, 32 borderwidth = 0, 33 highlightthickness = 0, 34 ) 35 inner.pack(fill = 'both', expand = 1) 36 37# ---------------------------------------------------------------------- 38 39def scrolledlistboxflashing_test(): 40 # Script which demonstrates continuous flashing of dynamic scrollbars 41 # in Pmw.ScrolledListBox. 42 # 43 # When this script is run, the two scrollbars will be continuously 44 # mapped and unmapped and the window will continuously change size. 45 46 frame = Tkinter.Frame(root) 47 frame.pack(fill = 'both', expand = 1) 48 49 sf = Pmw.ScrolledListBox(frame, 50 listbox_width = 20, 51 listbox_height = 10 52 ) 53 sf.pack(fill = 'both', expand = 1) 54 for i in range(11): 55 sf.insert('end', '2' * 20) 56 57# ---------------------------------------------------------------------- 58 59def scrolledlistboxflashing2_test(): 60 # Another script which demonstrates continuous flashing of dynamic 61 # scrollbars in Pmw.ScrolledListBox under Pmw.0.8. 62 # 63 # When this script is run, the two scrollbars will be continuously 64 # mapped and unmapped and the window will continuously change size. 65 # 66 # (This did not display error when tried with Pmw.0.8, 99/8/3) 67 68 def insert(): 69 sectionList = ['1', '2', '3', '4', '5', '6', '7', '8', '9', 70 '123456789012345678901'] 71 for counter in sectionList: 72 slb.insert('end', counter) 73 74 def clear(): 75 slb.delete(0, 'end') 76 77 global slb 78 slb = Pmw.ScrolledListBox(root) 79 slb.pack() 80 81 root.after(2000,insert) 82 root.after(3000,clear) 83 root.after(4000,insert) 84 85 root.geometry('400x400') 86 87# ---------------------------------------------------------------------- 88 89def scrolledtextflashing_test(): 90 # Script which demonstrates continuous flashing of dynamic scrollbars 91 # in Pmw.ScrolledText. 92 # 93 # When this script is run, the two scrollbars will be continuously 94 # mapped and unmapped and the window will continuously change size. 95 96 frame = Tkinter.Frame(root) 97 frame.pack(fill = 'both', expand = 1) 98 99 sf = Pmw.ScrolledText(frame, 100 text_width = 20, 101 text_height = 10, 102 text_wrap = 'none', 103 borderframe = 0 104 ) 105 sf.pack(fill = 'both', expand = 1) 106 for i in range(11): 107 sf.insert('end', '2' * 20) 108 if i != 10: 109 sf.insert('end', '\n') 110 111# ---------------------------------------------------------------------- 112 113def scrolledcanvasflashing_test(): 114 # Script which demonstrates continuous flashing of dynamic scrollbars 115 # in Pmw.ScrolledCanvas. 116 # 117 # When this script is run, the two scrollbars will be continuously 118 # mapped and unmapped and the window will continuously change size. 119 120 frame = Tkinter.Frame(root) 121 frame.pack(fill = 'both', expand = 1) 122 123 sf = Pmw.ScrolledCanvas(frame, 124 canvas_scrollregion = (0, 0, 301, 200), 125 canvas_width=300, 126 canvas_height=200, 127 borderframe = 0 128 ) 129 sf.pack(fill = 'both', expand = 1) 130 131# ---------------------------------------------------------------------- 132 133def scrolledframeflashing2_test(): 134 # The two scrollbars will be continuously mapped and unmapped, but 135 # the toplevel window will remain the same size. 136 137 root.geometry('550x500') 138 139 frame = Tkinter.Frame() 140 frame.pack() 141 142 sf = Pmw.ScrolledFrame(frame, borderframe = 0) 143 sf.pack(fill = 'both') 144 145 inner = Tkinter.Frame(sf.interior(), 146 width = 401, 147 height = 300, 148 borderwidth = 0, 149 highlightthickness = 0, 150 ) 151 inner.pack() 152 153# ---------------------------------------------------------------------- 154 155def reinitialise_test(): 156 global text 157 text = """ 158 Demonstrates bug in Pmw.0.8.1 and earlier. 159 Click on this button, click on OK in the dialog, then Exit below. 160 When this window appears again, clicking on this button gives 161 an error: 162 TclError: can't invoke "wm" command: application has been destroyed 163 """ 164 class test: 165 def __init__(self): 166 root = Tkinter.Tk() 167 Pmw.initialise(root) 168 self.messagedialog = Pmw.MessageDialog(message_text = 'Testing') 169 self.messagedialog.withdraw() 170 button = Tkinter.Button( 171 text = text, command = self.messagedialog.activate) 172 button.pack(pady = 20) 173 exit = Tkinter.Button(text = 'Exit', command = root.destroy) 174 exit.pack(pady = 20) 175 root.mainloop() 176 177 test() 178 test() 179 180# ---------------------------------------------------------------------- 181 182def componentgroup_test(): 183 def addbutton(bb): 184 bb.configure(Button_background = 'yellow') 185 bb.add('Apples') 186 bb.after(3000, lambda bb = bb: 187 bb.configure(Button_background = 'green')) 188 189 bb = Pmw.ButtonBox(Button_background = 'red') 190 bb.add('Bananas') 191 bb.pack() 192 193 mb = Pmw.MenuBar(Button_background = 'red') 194 mb.configure(Button_background = 'yellow') 195 mb.pack() 196 197 pw = Pmw.PanedWidget(Frame_background = 'red') 198 pw.configure(Frame_background = 'yellow') 199 pw.pack() 200 201 rs = Pmw.RadioSelect(Button_background = 'red') 202 rs.configure(Button_background = 'yellow') 203 rs.pack() 204 205 bb.after(3000, lambda bb = bb, addbutton = addbutton: addbutton(bb)) 206 207# ---------------------------------------------------------------------- 208 209def balloon_test(): 210 211 # TODO 212 213 # Test that the balloon does not reappear if the mouse button is 214 # pressed down inside a widget and then, while the mouse button is 215 # being held down, the mouse is moved outside of the widget and 216 # then moved back over the widget. 217 218 # Test that when a widget is destroyed while a balloon is being 219 # displayed for it then the balloon is withdrawn. 220 221 # Test that when a widget is destroyed while a balloon is being 222 # displayed for another widget then the balloon is not withdrawn. 223 224 # Test that there is no eror when a widget is destroyed during the 225 # initwait period (between when the mouse enters the widget and 226 # when the initwait timer goes off). 227 228 # Test that if unbind() is called on a widget that triggered the 229 # balloon to be displayed then the balloon is withdrawn. Also 230 # test that if another widget triggered the balloon then the 231 # balloon is not withdrawn. 232 233 # Test that if tagunbind() is called on a canvas or text item that 234 # triggered the balloon to be displayed then the balloon is 235 # withdrawn. Also test that if another widget or item triggered 236 # the balloon then the balloon is not withdrawn. 237 238 pass 239 240# ---------------------------------------------------------------------- 241 242# A class which prints out a message when an instance is deleted. 243class MyToplevel(Tkinter.Toplevel): 244 245 def __init__(self): 246 Tkinter.Toplevel.__init__(self) 247 248 def __del__(self): 249 print 'Window deleted' 250 251def _runMemoryLeakTest(): 252 global top 253 top = MyToplevel() 254 Pmw.MegaToplevel(top) 255 Pmw.AboutDialog(top) 256 Pmw.ComboBoxDialog(top) 257 Pmw.CounterDialog(top) 258 Pmw.Dialog(top) 259 Pmw.MessageDialog(top) 260 Pmw.PromptDialog(top) 261 Pmw.SelectionDialog(top) 262 Pmw.TextDialog(top) 263 264 Pmw.ButtonBox(top).pack() 265 Pmw.ComboBox(top).pack() 266 Pmw.Counter(top).pack() 267 Pmw.EntryField(top).pack() 268 Pmw.Group(top).pack() 269 Pmw.LabeledWidget(top).pack() 270 Pmw.MenuBar(top).pack() 271 Pmw.MessageBar(top).pack() 272 Pmw.NoteBook(top).pack() 273 Pmw.OptionMenu(top).pack() 274 Pmw.PanedWidget(top).pack() 275 Pmw.RadioSelect(top).pack() 276 Pmw.ScrolledCanvas(top).pack() 277 Pmw.ScrolledField(top).pack() 278 Pmw.ScrolledFrame(top).pack() 279 Pmw.ScrolledListBox(top).pack() 280 Pmw.ScrolledText(top).pack() 281 Pmw.TimeCounter(top).pack() 282 283def _killMemoryLeakTest(): 284 global top 285 top.destroy() 286 del top 287 288memoryLeakMessage = """ 289Click on the "Run test" button to create instances of 290all Pmw megawidgets. Then click on the "Destroy" button. 291The message "Window deleted" should be printed to 292standard output. 293""" 294def memoryleak_test(): 295 label = Tkinter.Label(text = memoryLeakMessage) 296 label.pack() 297 run = Tkinter.Button(text = 'Run test', command = _runMemoryLeakTest) 298 run.pack() 299 kill = Tkinter.Button(text = 'Destroy', command = _killMemoryLeakTest) 300 kill.pack() 301 302# ---------------------------------------------------------------------- 303 304def memoryleak2_test(): 305 306 print 'This test continuously creates and deletes megawidgets and' 307 print 'their components. It calls the "top" program, so' 308 print 'may not work on non-Unix operating systems. Run it for a long,' 309 print 'long time and check that the process memory size does not' 310 print 'continue to increase. Kill with <Control-C>.' 311 312 pid = os.getpid() 313 314 label = Tkinter.Label() 315 label.pack() 316 317 # Setup each test: 318 319 # 1. Create/delete all megawidgets: 320 megawidgets = ( 321 Pmw.AboutDialog, Pmw.Balloon, Pmw.ButtonBox, Pmw.ComboBox, 322 Pmw.ComboBoxDialog, Pmw.Counter, Pmw.CounterDialog, Pmw.Dialog, 323 Pmw.EntryField, Pmw.Group, Pmw.HistoryText, Pmw.LabeledWidget, 324 Pmw.MainMenuBar, Pmw.MenuBar, Pmw.MessageBar, Pmw.MessageDialog, 325 Pmw.NoteBook, Pmw.OptionMenu, Pmw.PanedWidget, Pmw.PromptDialog, 326 Pmw.RadioSelect, Pmw.ScrolledCanvas, Pmw.ScrolledField, 327 Pmw.ScrolledFrame, Pmw.ScrolledListBox, Pmw.ScrolledText, 328 Pmw.SelectionDialog, Pmw.TextDialog, Pmw.TimeCounter, 329 ) 330 331 # 2. Balloon binding: 332 toplevel = Tkinter.Toplevel() 333 balloon = Pmw.Balloon(toplevel) 334 button = Tkinter.Button(toplevel) 335 button.pack() 336 canvas = Tkinter.Canvas(toplevel) 337 item = canvas.create_rectangle(0, 0, 100, 100) 338 canvas.pack() 339 340 # 3. Adding and deleting menu: 341 toplevel = Tkinter.Toplevel() 342 mainmenu = Pmw.MainMenuBar(toplevel) 343 mainmenu.addmenu('Foo', 'help') 344 toplevel.configure(menu = mainmenu) 345 346 # 4. Adding and deleting notebook page: 347 toplevel = Tkinter.Toplevel() 348 notebook = Pmw.NoteBook(toplevel) 349 notebook.pack() 350 351 # 5. Adding and deleting panedwidget pane: 352 toplevel = Tkinter.Toplevel() 353 panedwidget = Pmw.PanedWidget(toplevel) 354 panedwidget.pack() 355 panedwidget.insert('Foo', size = 100) 356 357 # 6. Adding and deleting MenuBar menu: 358 toplevel = Tkinter.Toplevel() 359 menubar = Pmw.MenuBar(toplevel) 360 menubar.pack() 361 362 # 7. Setting OptionMenu items: 363 toplevel = Tkinter.Toplevel() 364 optionmenu = Pmw.OptionMenu(toplevel, items = ('XXX', 'YYY', 'ZZZ')) 365 optionmenu.pack() 366 367 # 8. Setting Tkinter.Canvas scrollcommand option: 368 toplevel = Tkinter.Toplevel() 369 scrollcanvas = Pmw.ScrolledCanvas(toplevel) 370 scrollcanvas.pack() 371 372 global prevSize 373 prevSize = -1 374 375 # Loop and run each test: 376 count = 0 377 while 1: 378 count = count + 1 379 label.configure(text = count) 380 381 # 1. Create/delete all megawidgets: 382 for widgetClass in megawidgets: 383 widget = widgetClass() 384 if widgetClass == Pmw.MainMenuBar: 385 root.configure(menu = widget) 386 elif hasattr(widgetClass, 'pack'): 387 widget.pack() 388 root.update() 389 widget.destroy() 390 391 # 2. Balloon binding: 392 balloon.bind(button, 'help') 393 balloon.tagbind(canvas, item, 'help') 394 # tagbind leaks due to a bug in Tkinter (v1.127) Canvas - it adds 395 # bindings to self._tagcommands but does not delete them. 396 root.update() 397 398 # 3. Adding and deleting MainMenuBar menu: 399 mainmenu.addmenu('File', 'help') 400 root.update() 401 mainmenu.deletemenu('File') 402 root.update() 403 404 # 4. Adding and deleting notebook page: 405 notebook.insert('File') 406 root.update() 407 notebook.delete('File') 408 root.update() 409 410 # 5. Adding and deleting panedwidget pane: 411 panedwidget.insert('File', size = 100) 412 root.update() 413 panedwidget.delete('File') 414 root.update() 415 416 # 6. Adding and deleting MenuBar menu: 417 menubar.addmenu('File', 'help') 418 root.update() 419 menubar.deletemenu('File') 420 root.update() 421 422 # 7. Setting OptionMenu items: 423 optionmenu.setitems(('aaa', 'bbb', 'ccc')) 424 root.update() 425 426 # 8. Setting Tkinter.Canvas scrollcommand option: 427 scrollcanvas.configure(hscrollmode = 'static') 428 scrollcanvas.configure(hscrollmode = 'dynamic') 429 430 # Check memory usage: 431 # lines = os.popen('top').readlines() 432 lines = os.popen('top -b -n 1 -p %d' % pid).readlines() 433 for line in lines: 434 # if string.find(line, 'python1.5.2') > 0: 435 if string.find(line, '^ *%d' % pid) > 0: 436 break 437 # size = string.atoi(string.lstrip(line[27:32])) 438 size = string.atoi(string.lstrip(line[22:29])) 439 if prevSize != size: 440 print time.strftime('%H:%M:%S', time.localtime(time.time())), 441 print line[:-1] 442 prevSize = size 443 444# ---------------------------------------------------------------------- 445 446def usageExit(): 447 print 'Usage:', sys.argv[0], '<test>' 448 print ' where <test> is one of:' 449 for test in tests: 450 print ' ', test 451 sys.exit() 452 453tests = [] 454for name in locals().keys(): 455 if name[-5:] == '_test': 456 tests.append(name) 457tests.sort() 458 459if len(sys.argv) != 2: 460 usageExit() 461 462testName = sys.argv[1] 463if testName not in tests: 464 print 'Unknown test "' + testName + '"' 465 usageExit() 466 467if testName == 'reinitialise_test': 468 # Run this by itself, since it calls Tkinter.Tk, mainloop, etc. 469 reinitialise_test() 470 sys.exit() 471 472# Use Pmw version in this distribution: 473Test.initialise() 474root = Test.root 475root.deiconify() 476 477# To use a different version of Pmw, comment out the three above lines 478# and the "import Test" line and uncomment these three: 479# root = Tkinter.Tk() 480# Pmw.setversion('1.0') 481# Pmw.initialise(root) 482 483testFunction = locals()[testName] 484testFunction() 485 486if testName != 'memoryleak2_test': 487 # This does not use mainloop. 488 root.mainloop() 489