Module easygui
[hide private]
[frames] | no frames]

Source Code for Module easygui

   1  """ 
   2  EasyGuiRevisionInfo = "version 0.83 2008-06-12" 
   3   
   4  EasyGui provides an easy-to-use interface for simple GUI interaction 
   5  with a user.  It does not require the programmer to know anything about 
   6  tkinter, frames, widgets, callbacks or lambda.  All GUI interactions are 
   7  invoked by simple function calls that return results. 
   8   
   9  Documentation is in an accompanying file, easygui.txt. 
  10   
  11  WARNING about using EasyGui with IDLE 
  12  ===================================== 
  13   
  14  You may encounter problems using IDLE to run programs that use EasyGui. Try it 
  15  and find out.  EasyGui is a collection of Tkinter routines that run their own 
  16  event loops.  IDLE is also a Tkinter application, with its own event loop.  The 
  17  two may conflict, with the unpredictable results. If you find that you have 
  18  problems, try running your program outside of IDLE. 
  19   
  20  Note that EasyGui requires Tk release 8.0 or greater. 
  21  """ 
  22  EasyGuiRevisionInfo = "version 0.83 2008-06-12" 
  23   
  24  # see easygui.txt for revision history information 
  25   
  26  __all__ = ['ynbox' 
  27          , 'ccbox' 
  28          , 'boolbox' 
  29          , 'indexbox' 
  30          , 'msgbox' 
  31          , 'buttonbox' 
  32          , 'integerbox' 
  33          , 'multenterbox' 
  34          , 'enterbox' 
  35          , 'choicebox' 
  36          , 'codebox' 
  37          , 'textbox' 
  38          , 'diropenbox' 
  39          , 'fileopenbox' 
  40          , 'filesavebox' 
  41          , 'passwordbox' 
  42          , 'multpasswordbox' 
  43          , 'multchoicebox' 
  44          , 'abouteasygui' 
  45          ] 
  46   
  47  import sys, os 
  48  from Tkinter import * 
  49  if TkVersion < 8.0 : 
  50          print "\n" * 3 
  51          print "*"*75 
  52          print "Running Tk version:", TkVersion 
  53          print "You must be using Tk version 8.0 or greater to use EasyGui." 
  54          print "Terminating." 
  55          print "*"*75 
  56          print "\n" * 3 
  57          sys.exit(0) 
  58   
59 -def dq(s): return '"%s"' % s
60 61 rootWindowPosition = "+300+200" 62 import string 63 64 DEFAULT_FONT_FAMILY = ("MS", "Sans", "Serif") 65 MONOSPACE_FONT_FAMILY = ("Courier") 66 DEFAULT_FONT_SIZE = 10 67 BIG_FONT_SIZE = 12 68 SMALL_FONT_SIZE = 9 69 CODEBOX_FONT_SIZE = 9 70 TEXTBOX_FONT_SIZE = DEFAULT_FONT_SIZE 71 72 73 import tkFileDialog 74 75 #------------------------------------------------------------------- 76 # various boxes built on top of the basic buttonbox 77 #----------------------------------------------------------------------- 78 79 #----------------------------------------------------------------------- 80 # ynbox 81 #-----------------------------------------------------------------------
82 -def ynbox(msg="Shall I continue?", title=" ", choices=("Yes", "No"), image=None):
83 """ 84 Display a msgbox with choices of Yes and No. 85 86 The default is "Yes". 87 88 The returned value is calculated this way:: 89 if the first choice ("Yes") is chosen, or if the dialog is cancelled: 90 return 1 91 else: 92 return 0 93 94 If invoked without a msg argument, displays a generic request for a confirmation 95 that the user wishes to continue. So it can be used this way:: 96 if ynbox(): pass # continue 97 else: sys.exit(0) # exit the program 98 99 @arg msg: the msg to be displayed. 100 @arg title: the window title 101 @arg choices: a list or tuple of the choices to be displayed 102 """ 103 return boolbox(msg, title, choices, image=None)
104 105 #----------------------------------------------------------------------- 106 # ccbox 107 #-----------------------------------------------------------------------
108 -def ccbox(msg="Shall I continue?", title=" ",choices=("Continue", "Cancel"), image=None):
109 """ 110 Display a msgbox with choices of Continue and Cancel. 111 112 The default is "Continue". 113 114 The returned value is calculated this way:: 115 if the first choice ("Continue") is chosen, or if the dialog is cancelled: 116 return 1 117 else: 118 return 0 119 120 If invoked without a msg argument, displays a generic request for a confirmation 121 that the user wishes to continue. So it can be used this way:: 122 123 if ccbox(): 124 pass # continue 125 else: 126 sys.exit(0) # exit the program 127 128 @arg msg: the msg to be displayed. 129 @arg title: the window title 130 @arg choices: a list or tuple of the choices to be displayed 131 """ 132 return boolbox(msg, title, choices, image=None)
133 134 135 #----------------------------------------------------------------------- 136 # boolbox 137 #-----------------------------------------------------------------------
138 -def boolbox(msg="Shall I continue?", title=" ", choices=("Yes","No"), image=None):
139 """ 140 Display a boolean msgbox. 141 142 The default is the first choice. 143 144 The returned value is calculated this way:: 145 if the first choice is chosen, or if the dialog is cancelled: 146 returns 1 147 else: 148 returns 0 149 """ 150 reply = buttonbox(msg=msg, choices=choices, title=title, image=None) 151 if reply == choices[0]: return 1 152 else: return 0
153 154 155 #----------------------------------------------------------------------- 156 # indexbox 157 #-----------------------------------------------------------------------
158 -def indexbox(msg="Shall I continue?", title=" ", choices=("Yes","No"), image=None):
159 """ 160 Display a buttonbox with the specified choices. 161 Return the index of the choice selected. 162 """ 163 reply = buttonbox(msg=msg, choices=choices, title=title, image=None) 164 index = -1 165 for choice in choices: 166 index = index + 1 167 if reply == choice: return index 168 raise AssertionError("There is a program logic error in the EasyGui code for indexbox.")
169 170 171 #----------------------------------------------------------------------- 172 # msgbox 173 #-----------------------------------------------------------------------
174 -def msgbox(msg="(Your message goes here)", title=" ", buttons="OK",image=None):
175 """ 176 Display a messagebox 177 """ 178 if type(buttons) == type("abc"): pass 179 else: raise AssertionError("The 'buttons' argument to msgbox must be a string.") 180 181 return buttonbox(msg=msg, title=title, choices=[buttons], image=image)
182 183 184 #------------------------------------------------------------------- 185 # buttonbox 186 #-------------------------------------------------------------------
187 -def buttonbox(msg="",title=" ",choices=("Button1", "Button2", "Button3"), image=None):
188 """ 189 Display a msg, a title, and a set of buttons. 190 The buttons are defined by the members of the choices list. 191 Return the text of the button that the user selected. 192 193 @arg msg: the msg to be displayed. 194 @arg title: the window title 195 @arg choices: a list or tuple of the choices to be displayed 196 """ 197 global root, __replyButtonText, __widgetTexts, buttonsFrame 198 ImageErrorMsg = ( 199 "\n\n---------------------------------------------\n" 200 "%s NOT SHOWN\n%s") 201 202 if image: 203 image = os.path.normpath(image) 204 junk,ext = os.path.splitext(image) 205 if ext.lower() == ".gif": 206 if os.path.exists(image): 207 pass 208 else: 209 msg += ImageErrorMsg % (image, "Image file not found.") 210 image = None 211 else: 212 msg += ImageErrorMsg % (image, "Image file is not a .gif file.") 213 image = None 214 215 # Initialize __replyButtonText to the first choice. 216 # This is what will be used if the window is closed by the close button. 217 __replyButtonText = choices[0] 218 219 root = Tk() 220 root.protocol('WM_DELETE_WINDOW', denyWindowManagerClose ) 221 root.title(title) 222 root.iconname('Dialog') 223 root.geometry(rootWindowPosition) 224 root.minsize(400, 100) 225 226 # ------------- define the frames -------------------------------------------- 227 messageFrame = Frame(root) 228 messageFrame.pack(side=TOP, fill=BOTH) 229 230 if image: 231 imageFrame = Frame(root) 232 imageFrame.pack(side=BOTTOM, fill=BOTH) 233 234 buttonsFrame = Frame(root) 235 buttonsFrame.pack(side=BOTTOM, fill=BOTH) 236 237 # -------------------- place the widgets in the frames ----------------------- 238 messageWidget = Message(messageFrame, text=msg, width=400) 239 messageWidget.configure(font=(DEFAULT_FONT_FAMILY,DEFAULT_FONT_SIZE)) 240 messageWidget.pack(side=TOP, expand=YES, fill=X, padx='3m', pady='3m') 241 242 if image: 243 image = PhotoImage(file=image) 244 label = Label(image=image) 245 label.image = image # keep a reference! 246 label.pack(side=TOP, expand=YES, fill=X, padx='1m', pady='1m') 247 248 __put_buttons_in_buttonframe(choices) 249 250 # -------------- the action begins ----------- 251 # put the focus on the first button 252 __firstWidget.focus_force() 253 root.mainloop() 254 root.destroy() 255 return __replyButtonText
256 257 258 #------------------------------------------------------------------- 259 # integerbox 260 #-------------------------------------------------------------------
261 -def integerbox(msg="", title=" ", default="", argLowerBound=0, argUpperBound=99):
262 """ 263 Show a box in which a user can enter an integer. 264 265 In addition to arguments for msg and title, this function accepts 266 integer arguments for default_value, lowerbound, and upperbound. 267 268 The default_value argument may be None. 269 270 When the user enters some text, the text is checked to verify 271 that it can be converted to an integer between the lowerbound and upperbound. 272 273 If it can be, the integer (not the text) is returned. 274 275 If it cannot, then an error msg is displayed, and the integerbox is 276 redisplayed. 277 278 If the user cancels the operation, None is returned. 279 """ 280 if default != "": 281 if type(default) != type(1): 282 raise AssertionError( 283 "integerbox received a non-integer value for " 284 + "default of " + dq(str(default)) , "Error") 285 286 if type(argLowerBound) != type(1): 287 raise AssertionError( 288 "integerbox received a non-integer value for " 289 + "argLowerBound of " + dq(str(argLowerBound)) , "Error") 290 291 if type(argUpperBound) != type(1): 292 raise AssertionError( 293 "integerbox received a non-integer value for " 294 + "argUpperBound of " + dq(str(argUpperBound)) , "Error") 295 296 if msg == "": 297 msg = ("Enter an integer between " + str(argLowerBound) 298 + " and " 299 + str(argUpperBound) 300 ) 301 302 while 1: 303 reply = enterbox(msg, title, str(default)) 304 if reply == None: return None 305 306 try: 307 reply = int(reply) 308 except: 309 msgbox ("The value that you entered:\n\t%s\nis not an integer." % dq(str(reply)) 310 , "Error") 311 continue 312 313 if reply < argLowerBound: 314 msgbox ("The value that you entered is less than the lower bound of " 315 + str(argLowerBound) + ".", "Error") 316 continue 317 318 if reply > argUpperBound: 319 msgbox ("The value that you entered is greater than the upper bound of " 320 + str(argUpperBound) + ".", "Error") 321 continue 322 323 # reply has passed all validation checks. 324 # It is an integer between the specified bounds. 325 return reply
326 327 #------------------------------------------------------------------- 328 # multenterbox 329 #-------------------------------------------------------------------
330 -def multenterbox(msg="Fill in values for the fields.", title=" " 331 , fields = (), values = () ):
332 """ 333 Show screen with multiple data entry fields. 334 335 If there are fewer values than names, the list of values is padded with 336 empty strings until the number of values is the same as the number of names. 337 338 If there are more values than names, the list of values 339 is truncated so that there are as many values as names. 340 341 Returns a list of the values of the fields, 342 or None if the user cancels the operation. 343 344 Here is some example code, that shows how values returned from 345 multenterbox can be checked for validity before they are accepted:: 346 ---------------------------------------------------------------------- 347 msg = "Enter your personal information" 348 title = "Credit Card Application" 349 fieldNames = ["Name","Street Address","City","State","ZipCode"] 350 fieldValues = [] # we start with blanks for the values 351 fieldValues = multenterbox(msg,title, fieldNames) 352 353 # make sure that none of the fields was left blank 354 while 1: 355 if fieldValues == None: break 356 errmsg = "" 357 for i in range(len(fieldNames)): 358 if fieldValues[i].strip() == "": 359 errmsg = errmsg + ('"%s" is a required field.\n\n' % fieldNames[i]) 360 if errmsg == "": break # no problems found 361 fieldValues = multenterbox(errmsg, title, fieldNames, fieldValues) 362 363 print "Reply was:", fieldValues 364 ---------------------------------------------------------------------- 365 366 @arg msg: the msg to be displayed. 367 @arg title: the window title 368 @arg fields: a list of fieldnames. 369 @arg values: a list of field values 370 """ 371 return __multfillablebox(msg,title,fields,values,None)
372 373 374 #----------------------------------------------------------------------- 375 # multpasswordbox 376 #-----------------------------------------------------------------------
377 -def multpasswordbox(msg="Fill in values for the fields.", title=" " 378 , fields = (), values = () ):
379 """ 380 Same interface as multenterbox. But in multpassword box, 381 the last of the fields is assumed to be a password, and 382 is masked with asterisks. 383 384 Here is some example code, that shows how values returned from 385 multpasswordbox can be checked for validity before they are accepted:: 386 ---------------------------------------------------------------------- 387 msg = "Enter logon information" 388 title = "Demo of multpasswordbox" 389 fieldNames = ["Server ID", "User ID", "Password"] 390 fieldValues = [] # we start with blanks for the values 391 fieldValues = multpasswordbox(msg,title, fieldNames) 392 393 # make sure that none of the fields was left blank 394 while 1: 395 if fieldValues == None: break 396 errmsg = "" 397 for i in range(len(fieldNames)): 398 if fieldValues[i].strip() == "": 399 errmsg = errmsg + ('"%s" is a required field.\n\n' % fieldNames[i]) 400 if errmsg == "": break # no problems found 401 fieldValues = multpasswordbox(errmsg, title, fieldNames, fieldValues) 402 403 print "Reply was:", fieldValues 404 ---------------------------------------------------------------------- 405 """ 406 return __multfillablebox(msg,title,fields,values,"*")
407 408 #----------------------------------------------------------------------- 409 # __multfillablebox 410 #-----------------------------------------------------------------------
411 -def __multfillablebox(msg="Fill in values for the fields.", title=" " 412 , fields=(), values=(), argMaskCharacter = None ):
413 414 global root, __multenterboxText, __multenterboxDefaultText, cancelButton, entryWidget, okButton 415 416 choices = ["OK", "Cancel"] 417 if len(fields) == 0: return None 418 419 fields = list(fields[:]) # convert possible tuples to a list 420 values = list(values[:]) # convert possible tuples to a list 421 422 if len(values) == len(fields): pass 423 elif len(values) > len(fields): 424 fields = fields[0:len(values)] 425 else: 426 while len(values) < len(fields): 427 values.append("") 428 429 root = Tk() 430 root.protocol('WM_DELETE_WINDOW', denyWindowManagerClose ) 431 root.title(title) 432 root.iconname('Dialog') 433 root.geometry(rootWindowPosition) 434 root.bind("<Escape>", __multenterboxCancel) 435 436 # -------------------- put subframes in the root -------------------- 437 messageFrame = Frame(root) 438 messageFrame.pack(side=TOP, fill=BOTH) 439 440 #-------------------- the msg widget ---------------------------- 441 messageWidget = Message(messageFrame, width="4.5i", text=msg) 442 messageWidget.configure(font=(DEFAULT_FONT_FAMILY,DEFAULT_FONT_SIZE)) 443 messageWidget.pack(side=RIGHT, expand=1, fill=BOTH, padx='3m', pady='3m') 444 445 global entryWidgets 446 entryWidgets = [] 447 448 lastWidgetIndex = len(fields) - 1 449 450 for widgetIndex in range(len(fields)): 451 argFieldName = fields[widgetIndex] 452 argFieldValue = values[widgetIndex] 453 entryFrame = Frame(root) 454 entryFrame.pack(side=TOP, fill=BOTH) 455 456 # --------- entryWidget ---------------------------------------------- 457 labelWidget = Label(entryFrame, text=argFieldName) 458 labelWidget.pack(side=LEFT) 459 460 entryWidgets.append(Entry(entryFrame, width=40)) 461 entryWidgets[widgetIndex].configure(font=(DEFAULT_FONT_FAMILY,BIG_FONT_SIZE)) 462 entryWidgets[widgetIndex].pack(side=RIGHT, padx="3m") 463 entryWidgets[widgetIndex].bind("<Return>", __multenterboxGetText) 464 entryWidgets[widgetIndex].bind("<Escape>", __multenterboxCancel) 465 466 # for the last entryWidget, if this is a multpasswordbox, 467 # show the contents as just asterisks 468 if widgetIndex == lastWidgetIndex: 469 if argMaskCharacter: 470 entryWidgets[widgetIndex].configure(show=argMaskCharacter) 471 472 # put text into the entryWidget 473 entryWidgets[widgetIndex].insert(0,argFieldValue) 474 widgetIndex += 1 475 476 # ------------------ ok button ------------------------------- 477 478 buttonsFrame = Frame(root) 479 buttonsFrame.pack(side=BOTTOM, fill=BOTH) 480 481 482 okButton = Button(buttonsFrame, takefocus=1, text="OK") 483 okButton.pack(expand=1, side=LEFT, padx='3m', pady='3m', ipadx='2m', ipady='1m') 484 okButton.bind("<Return>" , __multenterboxGetText) 485 okButton.bind("<Button-1>", __multenterboxGetText) 486 487 # ------------------ cancel button ------------------------------- 488 cancelButton = Button(buttonsFrame, takefocus=1, text="Cancel") 489 cancelButton.pack(expand=1, side=RIGHT, padx='3m', pady='3m', ipadx='2m', ipady='1m') 490 cancelButton.bind("<Return>" , __multenterboxCancel) 491 cancelButton.bind("<Button-1>", __multenterboxCancel) 492 493 # ------------------- time for action! ----------------- 494 entryWidgets[0].focus_force() # put the focus on the entryWidget 495 root.mainloop() # run it! 496 497 # -------- after the run has completed ---------------------------------- 498 root.destroy() # button_click didn't destroy root, so we do it now 499 return __multenterboxText
500 501 #----------------------------------------------------------------------- 502 # __multenterboxGetText 503 #-----------------------------------------------------------------------
504 -def __multenterboxGetText(event):
505 global root, __multenterboxText, entryWidget 506 __multenterboxText = [] 507 global entryWidgets 508 for entryWidget in entryWidgets: 509 __multenterboxText.append(entryWidget.get()) 510 511 root.quit()
512
513 -def __multenterboxCancel(event):
514 global root, __multenterboxDefaultText, __multenterboxText 515 __multenterboxText = None 516 517 root.quit()
518 519 520 #------------------------------------------------------------------- 521 # enterbox 522 #-------------------------------------------------------------------
523 -def enterbox(msg="Enter something.", title=" ", default="",strip=True):
524 """ 525 Show a box in which a user can enter some text. 526 527 You may optionally specify some default text, which will appear in the 528 enterbox when it is displayed. 529 530 Returns the text that the user entered, or None if he cancels the operation. 531 532 By default, enterbox strips its result (i.e. removes leading and trailing 533 whitespace). (If you want it not to strip, use keyword argument: strip=False.) 534 This makes it easier to test the results of the call:: 535 536 reply = enterbox(....) 537 if reply: 538 ... 539 else: 540 ... 541 """ 542 result = __fillablebox(msg, title, default=default, argMaskCharacter=None) 543 if result and strip: 544 result = result.strip() 545 return result
546 547
548 -def passwordbox(msg="Enter your password.", title=" ", default=""):
549 """ 550 Show a box in which a user can enter a password. 551 The text is masked with asterisks, so the password is not displayed. 552 Returns the text that the user entered, or None if he cancels the operation. 553 """ 554 return __fillablebox(msg, title, default, "*")
555 556
557 -def __fillablebox(msg, title="", default="", argMaskCharacter=None):
558 """ 559 Show a box in which a user can enter some text. 560 You may optionally specify some default text, which will appear in the 561 enterbox when it is displayed. 562 Returns the text that the user entered, or None if he cancels the operation. 563 """ 564 565 global root, __enterboxText, __enterboxDefaultText, cancelButton, entryWidget, okButton 566 567 if title == None: title == "" 568 if default == None: default = "" 569 __enterboxDefaultText = default 570 __enterboxText = __enterboxDefaultText 571 choices = ["OK", "Cancel"] 572 573 root = Tk() 574 root.protocol('WM_DELETE_WINDOW', denyWindowManagerClose ) 575 root.title(title) 576 root.iconname('Dialog') 577 root.geometry(rootWindowPosition) 578 root.bind("<Escape>", __enterboxCancel) 579 580 # -------------------- put subframes in the root -------------------- 581 messageFrame = Frame(root) 582 messageFrame.pack(side=TOP, fill=BOTH) 583 584 entryFrame = Frame(root) 585 entryFrame.pack(side=TOP, fill=BOTH) 586 587 buttonsFrame = Frame(root) 588 buttonsFrame.pack(side=BOTTOM, fill=BOTH) 589 590 #-------------------- the msg widget ---------------------------- 591 messageWidget = Message(messageFrame, width="4.5i", text=msg) 592 messageWidget.configure(font=(DEFAULT_FONT_FAMILY,DEFAULT_FONT_SIZE)) 593 messageWidget.pack(side=RIGHT, expand=1, fill=BOTH, padx='3m', pady='3m') 594 595 # --------- entryWidget ---------------------------------------------- 596 entryWidget = Entry(entryFrame, width=40) 597 entryWidget.configure(font=(DEFAULT_FONT_FAMILY,BIG_FONT_SIZE)) 598 if argMaskCharacter: 599 entryWidget.configure(show=argMaskCharacter) 600 entryWidget.pack(side=LEFT, padx="3m") 601 entryWidget.bind("<Return>", __enterboxGetText) 602 entryWidget.bind("<Escape>", __enterboxCancel) 603 # put text into the entryWidget 604 entryWidget.insert(0,__enterboxDefaultText) 605 606 # ------------------ ok button ------------------------------- 607 okButton = Button(buttonsFrame, takefocus=1, text="OK") 608 okButton.pack(expand=1, side=LEFT, padx='3m', pady='3m', ipadx='2m', ipady='1m') 609 okButton.bind("<Return>" , __enterboxGetText) 610 okButton.bind("<Button-1>", __enterboxGetText) 611 612 ''' dead code ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 613 # ------------------ (possible) restore button ------------------------------- 614 if default != None: 615 # make a button to restore the default text 616 restoreButton = Button(buttonsFrame, takefocus=1, text="Restore default") 617 restoreButton.pack(expand=1, side=LEFT, padx='3m', pady='3m', ipadx='2m', ipady='1m') 618 restoreButton.bind("<Return>" , __enterboxRestore) 619 restoreButton.bind("<Button-1>", __enterboxRestore) 620 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ dead code ''' 621 622 # ------------------ cancel button ------------------------------- 623 cancelButton = Button(buttonsFrame, takefocus=1, text="Cancel") 624 cancelButton.pack(expand=1, side=RIGHT, padx='3m', pady='3m', ipadx='2m', ipady='1m') 625 cancelButton.bind("<Return>" , __enterboxCancel) 626 cancelButton.bind("<Button-1>", __enterboxCancel) 627 628 # ------------------- time for action! ----------------- 629 entryWidget.focus_force() # put the focus on the entryWidget 630 root.mainloop() # run it! 631 632 # -------- after the run has completed ---------------------------------- 633 root.destroy() # button_click didn't destroy root, so we do it now 634 return __enterboxText
635 636 637
638 -def __enterboxGetText(event):
639 global root, __enterboxText, entryWidget 640 __enterboxText = entryWidget.get() 641 642 root.quit()
643
644 -def __enterboxRestore(event):
645 global root, __enterboxText, entryWidget 646 entryWidget.delete(0,len(entryWidget.get())) 647 entryWidget.insert(0, __enterboxDefaultText)
648
649 -def __enterboxCancel(event):
650 global root, __enterboxDefaultText, __enterboxText 651 __enterboxText = None 652 653 root.quit()
654
655 -def denyWindowManagerClose():
656 """ don't allow WindowManager close 657 """ 658 x = Tk() 659 x.withdraw() 660 x.bell() 661 x.destroy()
662 663 664 665 #------------------------------------------------------------------- 666 # multchoicebox 667 #-------------------------------------------------------------------
668 -def multchoicebox(msg="Pick as many items as you like.",title=" ",choices=(), **kwargs):
669 """ 670 Present the user with a list of choices. 671 allow him to select multiple items and return them in a list. 672 if the user doesn't choose anything from the list, return the empty list. 673 return None if he cancelled selection. 674 675 @arg msg: the msg to be displayed. 676 @arg title: the window title 677 @arg choices: a list or tuple of the choices to be displayed 678 """ 679 if len(choices) == 0: choices = ["Program logic error - no choices were specified."] 680 681 global __choiceboxMultipleSelect 682 __choiceboxMultipleSelect = 1 683 return __choicebox(msg, title, choices)
684 685 686 #----------------------------------------------------------------------- 687 # choicebox 688 #-----------------------------------------------------------------------
689 -def choicebox(msg="Pick something.",title=" ", choices=(), buttons=() ):
690 """ 691 Present the user with a list of choices. 692 return the choice that he selects. 693 return None if he cancels the selection selection. 694 695 @arg msg: the msg to be displayed. 696 @arg title: the window title 697 @arg choices: a list or tuple of the choices to be displayed 698 """ 699 if len(choices) == 0: choices = ["Program logic error - no choices were specified."] 700 701 global __choiceboxMultipleSelect 702 __choiceboxMultipleSelect = 0 703 return __choicebox(msg,title,choices,buttons)
704 705 706 #----------------------------------------------------------------------- 707 # __choicebox 708 #-----------------------------------------------------------------------
709 -def __choicebox(msg, title, choices, buttons=() ):
710 """ 711 internal routine to support choicebox() and multchoicebox() 712 """ 713 global root, __choiceboxResults, choiceboxWidget, defaultText 714 global choiceboxWidget, choiceboxChoices 715 #------------------------------------------------------------------- 716 # If choices is a tuple, we make it a list so we can sort it. 717 # If choices is already a list, we make a new list, so that when 718 # we sort the choices, we don't affect the list object that we 719 # were given. 720 #------------------------------------------------------------------- 721 choices = list(choices[:]) 722 if len(choices) == 0: choices = ["Program logic error - no choices were specified."] 723 defaultButtons = ["OK", "Cancel"] 724 725 # make sure all choices are strings 726 for index in range(len(choices)): 727 choices[index] = str(choices[index]) 728 729 if buttons: 730 if type(buttons) == type("abc"): # user sent a string 731 choiceboxButtons = [buttons] 732 else: # we assume user sent in a list or tuple of strings 733 choiceboxButtons = buttons 734 else: 735 choiceboxButtons = defaultButtons 736 737 lines_to_show = min(len(choices), 20) 738 lines_to_show = 20 739 740 if title == None: title = "" 741 742 # Initialize __choiceboxResults 743 # This is the value that will be returned if the user clicks the close icon 744 __choiceboxResults = None 745 746 root = Tk() 747 root.protocol('WM_DELETE_WINDOW', denyWindowManagerClose ) 748 screen_width = root.winfo_screenwidth() 749 screen_height = root.winfo_screenheight() 750 root_width = int((screen_width * 0.8)) 751 root_height = int((screen_height * 0.5)) 752 root_xpos = int((screen_width * 0.1)) 753 root_ypos = int((screen_height * 0.05)) 754 755 root.title(title) 756 root.iconname('Dialog') 757 rootWindowPosition = "+0+0" 758 root.geometry(rootWindowPosition) 759 root.expand=NO 760 root.minsize(root_width, root_height) 761 rootWindowPosition = "+" + str(root_xpos) + "+" + str(root_ypos) 762 root.geometry(rootWindowPosition) 763 764 # ---------------- put the frames in the window ----------------------------------------- 765 message_and_buttonsFrame = Frame(root) 766 message_and_buttonsFrame.pack(side=TOP, fill=X, expand=NO) 767 768 messageFrame = Frame(message_and_buttonsFrame) 769 messageFrame.pack(side=LEFT, fill=X, expand=YES) 770 #messageFrame.pack(side=TOP, fill=X, expand=YES) 771 772 buttonsFrame = Frame(message_and_buttonsFrame) 773 buttonsFrame.pack(side=RIGHT, expand=NO, pady=0) 774 #buttonsFrame.pack(side=TOP, expand=YES, pady=0) 775 776 choiceboxFrame = Frame(root) 777 choiceboxFrame.pack(side=BOTTOM, fill=BOTH, expand=YES) 778 779 # -------------------------- put the widgets in the frames ------------------------------ 780 781 # ---------- put a msg widget in the msg frame------------------- 782 messageWidget = Message(messageFrame, anchor=NW, text=msg, width=int(root_width * 0.9)) 783 messageWidget.configure(font=(DEFAULT_FONT_FAMILY,DEFAULT_FONT_SIZE)) 784 messageWidget.pack(side=LEFT, expand=YES, fill=BOTH, padx='1m', pady='1m') 785 786 # -------- put the choiceboxWidget in the choiceboxFrame --------------------------- 787 choiceboxWidget = Listbox(choiceboxFrame 788 , height=lines_to_show 789 , borderwidth="1m" 790 , relief="flat" 791 , bg="white" 792 ) 793 794 if __choiceboxMultipleSelect: 795 choiceboxWidget.configure(selectmode=MULTIPLE) 796 797 choiceboxWidget.configure(font=(DEFAULT_FONT_FAMILY,DEFAULT_FONT_SIZE)) 798 799 # add a vertical scrollbar to the frame 800 rightScrollbar = Scrollbar(choiceboxFrame, orient=VERTICAL, command=choiceboxWidget.yview) 801 choiceboxWidget.configure(yscrollcommand = rightScrollbar.set) 802 803 # add a horizontal scrollbar to the frame 804 bottomScrollbar = Scrollbar(choiceboxFrame, orient=HORIZONTAL, command=choiceboxWidget.xview) 805 choiceboxWidget.configure(xscrollcommand = bottomScrollbar.set) 806 807 # pack the Listbox and the scrollbars. Note that although we must define 808 # the textbox first, we must pack it last, so that the bottomScrollbar will 809 # be located properly. 810 811 bottomScrollbar.pack(side=BOTTOM, fill = X) 812 rightScrollbar.pack(side=RIGHT, fill = Y) 813 814 choiceboxWidget.pack(side=LEFT, padx="1m", pady="1m", expand=YES, fill=BOTH) 815 816 #--------------------------------------------------- 817 # sort the choices 818 # eliminate duplicates 819 # put the choices into the choiceboxWidget 820 #--------------------------------------------------- 821 for index in range(len(choices)): 822 choices[index] == str(choices[index]) 823 824 choices.sort( lambda x,y: cmp(x.lower(), y.lower())) # case-insensitive sort 825 lastInserted = None 826 choiceboxChoices = [] 827 for choice in choices: 828 if choice == lastInserted: pass 829 else: 830 choiceboxWidget.insert(END, choice) 831 choiceboxChoices.append(choice) 832 lastInserted = choice 833 834 root.bind('<Any-Key>', KeyboardListener) 835 836 # put the buttons in the buttonsFrame 837 if len(choices) > 0: 838 okButton = Button(buttonsFrame, takefocus=YES, text="OK", height=1, width=6) 839 okButton.pack(expand=NO, side=TOP, padx='2m', pady='1m', ipady="1m", ipadx="2m") 840 okButton.bind("<Return>", __choiceboxGetChoice) 841 okButton.bind("<Button-1>",__choiceboxGetChoice) 842 843 # now bind the keyboard events 844 choiceboxWidget.bind("<Return>", __choiceboxGetChoice) 845 choiceboxWidget.bind("<Double-Button-1>", __choiceboxGetChoice) 846 else: 847 # now bind the keyboard events 848 choiceboxWidget.bind("<Return>", __choiceboxCancel) 849 choiceboxWidget.bind("<Double-Button-1>", __choiceboxCancel) 850 851 cancelButton = Button(buttonsFrame, takefocus=YES, text="Cancel", height=1, width=6) 852 cancelButton.pack(expand=NO, side=BOTTOM, padx='2m', pady='1m', ipady="1m", ipadx="2m") 853 cancelButton.bind("<Return>", __choiceboxCancel) 854 cancelButton.bind("<Button-1>", __choiceboxCancel) 855 856 # add special buttons for multiple select features 857 if len(choices) > 0 and __choiceboxMultipleSelect: 858 selectionButtonsFrame = Frame(messageFrame) 859 selectionButtonsFrame.pack(side=RIGHT, fill=Y, expand=NO) 860 861 selectAllButton = Button(selectionButtonsFrame, text="Select All", height=1, width=6) 862 selectAllButton.bind("<Button-1>",__choiceboxSelectAll) 863 selectAllButton.pack(expand=NO, side=TOP, padx='2m', pady='1m', ipady="1m", ipadx="2m") 864 865 clearAllButton = Button(selectionButtonsFrame, text="Clear All", height=1, width=6) 866 clearAllButton.bind("<Button-1>",__choiceboxClearAll) 867 clearAllButton.pack(expand=NO, side=TOP, padx='2m', pady='1m', ipady="1m", ipadx="2m") 868 869 870 # -------------------- bind some keyboard events ---------------------------- 871 root.bind("<Escape>", __choiceboxCancel) 872 873 # --------------------- the action begins ----------------------------------- 874 # put the focus on the choiceboxWidget, and the select highlight on the first item 875 choiceboxWidget.select_set(0) 876 choiceboxWidget.focus_force() 877 878 # --- run it! ----- 879 root.mainloop() 880 881 root.destroy() 882 return __choiceboxResults
883 884
885 -def __choiceboxGetChoice(event):
886 global root, __choiceboxResults, choiceboxWidget 887 888 if __choiceboxMultipleSelect: 889 __choiceboxResults = [choiceboxWidget.get(index) for index in choiceboxWidget.curselection()] 890 891 else: 892 choice_index = choiceboxWidget.curselection() 893 __choiceboxResults = choiceboxWidget.get(choice_index) 894 895 # print "Debugging> mouse-event=", event, " event.type=", event.type 896 # print "Debugging> choice =", choice_index, __choiceboxResults 897 root.quit()
898 899
900 -def __choiceboxSelectAll(event):
901 global choiceboxWidget, choiceboxChoices 902 choiceboxWidget.selection_set(0, len(choiceboxChoices)-1)
903
904 -def __choiceboxClearAll(event):
905 global choiceboxWidget, choiceboxChoices 906 choiceboxWidget.selection_clear(0, len(choiceboxChoices)-1)
907 908 909
910 -def __choiceboxCancel(event):
911 global root, __choiceboxResults 912 913 __choiceboxResults = None 914 root.quit()
915 916
917 -def KeyboardListener(event):
918 global choiceboxChoices, choiceboxWidget 919 key = event.keysym 920 if len(key) <= 1: 921 if key in string.printable: 922 # Find the key in the list. 923 # before we clear the list, remember the selected member 924 try: 925 start_n = int(choiceboxWidget.curselection()[0]) 926 except IndexError: 927 start_n = -1 928 929 ## clear the selection. 930 choiceboxWidget.selection_clear(0, 'end') 931 932 ## start from previous selection +1 933 for n in range(start_n+1, len(choiceboxChoices)): 934 item = choiceboxChoices[n] 935 if item[0].lower() == key.lower(): 936 choiceboxWidget.selection_set(first=n) 937 choiceboxWidget.see(n) 938 return 939 else: 940 # has not found it so loop from top 941 for n in range(len(choiceboxChoices)): 942 item = choiceboxChoices[n] 943 if item[0].lower() == key.lower(): 944 choiceboxWidget.selection_set(first = n) 945 choiceboxWidget.see(n) 946 return 947 948 # nothing matched -- we'll look for the next logical choice 949 for n in range(len(choiceboxChoices)): 950 item = choiceboxChoices[n] 951 if item[0].lower() > key.lower(): 952 if n > 0: 953 choiceboxWidget.selection_set(first = (n-1)) 954 else: 955 choiceboxWidget.selection_set(first = 0) 956 choiceboxWidget.see(n) 957 return 958 959 # still no match (nothing was greater than the key) 960 # we set the selection to the first item in the list 961 lastIndex = len(choiceboxChoices)-1 962 choiceboxWidget.selection_set(first = lastIndex) 963 choiceboxWidget.see(lastIndex) 964 return
965 966 #------------------------------------------------------------------- 967 # codebox 968 #------------------------------------------------------------------- 969
970 -def codebox(msg="", title=" ", text=""):
971 """ 972 Display some text in a monospaced font, with no line wrapping. 973 This function is suitable for displaying code and text that is 974 formatted using spaces. 975 976 The text parameter should be a string, or a list or tuple of lines to be 977 displayed in the textbox. 978 """ 979 textbox(msg, title, text, codebox=1 )
980 981 #------------------------------------------------------------------- 982 # textbox 983 #-------------------------------------------------------------------
984 -def textbox(msg="", title=" ", text="", codebox=0):
985 """ 986 Display some text in a proportional font with line wrapping at word breaks. 987 This function is suitable for displaying general written text. 988 989 The text parameter should be a string, or a list or tuple of lines to be 990 displayed in the textbox. 991 """ 992 993 if msg == None: msg = "" 994 if title == None: title = "" 995 996 global root, __replyButtonText, __widgetTexts, buttonsFrame 997 choices = ["0K"] 998 __replyButtonText = choices[0] 999 1000 1001 root = Tk() 1002 1003 root.protocol('WM_DELETE_WINDOW', denyWindowManagerClose ) 1004 1005 screen_width = root.winfo_screenwidth() 1006 screen_height = root.winfo_screenheight() 1007 root_width = int((screen_width * 0.8)) 1008 root_height = int((screen_height * 0.5)) 1009 root_xpos = int((screen_width * 0.1)) 1010 root_ypos = int((screen_height * 0.05)) 1011 1012 root.title(title) 1013 root.iconname('Dialog') 1014 rootWindowPosition = "+0+0" 1015 root.geometry(rootWindowPosition) 1016 root.expand=NO 1017 root.minsize(root_width, root_height) 1018 rootWindowPosition = "+" + str(root_xpos) + "+" + str(root_ypos) 1019 root.geometry(rootWindowPosition) 1020 1021 1022 mainframe = Frame(root) 1023 mainframe.pack(side=TOP, fill=BOTH, expand=YES) 1024 1025 # ---- put frames in the window ----------------------------------- 1026 # we pack the textboxFrame first, so it will expand first 1027 textboxFrame = Frame(mainframe, borderwidth=3) 1028 textboxFrame.pack(side=BOTTOM , fill=BOTH, expand=YES) 1029 1030 message_and_buttonsFrame = Frame(mainframe) 1031 message_and_buttonsFrame.pack(side=TOP, fill=X, expand=NO) 1032 1033 messageFrame = Frame(message_and_buttonsFrame) 1034 messageFrame.pack(side=LEFT, fill=X, expand=YES) 1035 1036 buttonsFrame = Frame(message_and_buttonsFrame) 1037 buttonsFrame.pack(side=RIGHT, expand=NO) 1038 1039 # -------------------- put widgets in the frames -------------------- 1040 1041 # put a textbox in the top frame 1042 if codebox: 1043 character_width = int((root_width * 0.6) / CODEBOX_FONT_SIZE) 1044 textbox = Text(textboxFrame,height=25,width=character_width, padx="2m", pady="1m") 1045 textbox.configure(wrap=NONE) 1046 textbox.configure(font=(MONOSPACE_FONT_FAMILY, CODEBOX_FONT_SIZE)) 1047 1048 else: 1049 character_width = int((root_width * 0.6) / SMALL_FONT_SIZE) 1050 textbox = Text( 1051 textboxFrame 1052 , height=25 1053 , width=character_width 1054 , padx="2m" 1055 , pady="1m" 1056 ) 1057 textbox.configure(wrap=WORD) 1058 textbox.configure(font=(DEFAULT_FONT_FAMILY,TEXTBOX_FONT_SIZE)) 1059 1060 1061 # some simple keybindings for scrolling 1062 mainframe.bind("<Next>" , textbox.yview_scroll( 1,PAGES)) 1063 mainframe.bind("<Prior>", textbox.yview_scroll(-1,PAGES)) 1064 1065 mainframe.bind("<Right>", textbox.xview_scroll( 1,PAGES)) 1066 mainframe.bind("<Left>" , textbox.xview_scroll(-1,PAGES)) 1067 1068 mainframe.bind("<Down>", textbox.yview_scroll( 1,UNITS)) 1069 mainframe.bind("<Up>" , textbox.yview_scroll(-1,UNITS)) 1070 1071 1072 # add a vertical scrollbar to the frame 1073 rightScrollbar = Scrollbar(textboxFrame, orient=VERTICAL, command=textbox.yview) 1074 textbox.configure(yscrollcommand = rightScrollbar.set) 1075 1076 # add a horizontal scrollbar to the frame 1077 bottomScrollbar = Scrollbar(textboxFrame, orient=HORIZONTAL, command=textbox.xview) 1078 textbox.configure(xscrollcommand = bottomScrollbar.set) 1079 1080 # pack the textbox and the scrollbars. Note that although we must define 1081 # the textbox first, we must pack it last, so that the bottomScrollbar will 1082 # be located properly. 1083 1084 # Note that we need a bottom scrollbar only for code. 1085 # Text will be displayed with wordwrap, so we don't need to have a horizontal 1086 # scroll for it. 1087 if codebox: 1088 bottomScrollbar.pack(side=BOTTOM, fill=X) 1089 rightScrollbar.pack(side=RIGHT, fill=Y) 1090 1091 textbox.pack(side=LEFT, fill=BOTH, expand=YES) 1092 1093 1094 # ---------- put a msg widget in the msg frame------------------- 1095 messageWidget = Message(messageFrame, anchor=NW, text=msg, width=int(root_width * 0.9)) 1096 messageWidget.configure(font=(DEFAULT_FONT_FAMILY,DEFAULT_FONT_SIZE)) 1097 messageWidget.pack(side=LEFT, expand=YES, fill=BOTH, padx='1m', pady='1m') 1098 1099 # put the buttons in the buttonsFrame 1100 okButton = Button(buttonsFrame, takefocus=YES, text="OK", height=1, width=6) 1101 okButton.pack(expand=NO, side=TOP, padx='2m', pady='1m', ipady="1m", ipadx="2m") 1102 okButton.bind("<Return>" , __textboxOK) 1103 okButton.bind("<Button-1>", __textboxOK) 1104 okButton.bind("<Escape>" , __textboxOK) 1105 1106 1107 # ----------------- the action begins ---------------------------------------- 1108 try: 1109 # load the text into the textbox 1110 if type(text) == type("abc"): pass 1111 else: 1112 try: 1113 text = "".join(text) # convert a list or a tuple to a string 1114 except: 1115 msgbox("Exception when trying to convert "+ str(type(text)) + " to text in textbox") 1116 sys.exit(16) 1117 textbox.insert(END,text, "normal") 1118 1119 # disable the textbox, so the text cannot be edited 1120 textbox.configure(state=DISABLED) 1121 except: 1122 msgbox("Exception when trying to load the textbox.") 1123 sys.exit(16) 1124 1125 try: 1126 okButton.focus_force() 1127 except: 1128 msgbox("Exception when trying to put focus on okButton.") 1129 sys.exit(16) 1130 1131 root.mainloop() 1132 root.destroy() 1133 return __replyButtonText
1134 1135 #------------------------------------------------------------------- 1136 # __textboxOK 1137 #-------------------------------------------------------------------
1138 -def __textboxOK(event):
1139 global root 1140 1141 root.quit()
1142 1143 1144 1145 #------------------------------------------------------------------- 1146 # diropenbox 1147 #-------------------------------------------------------------------
1148 -def diropenbox(msg=None, title=None, default=None):
1149 """ 1150 A dialog to get a directory name. 1151 Note that the msg argument, if specified, is ignored. 1152 1153 Returns the name of a directory, or None if user chose to cancel. 1154 1155 If the "default" argument specifies a directory name, 1156 and that directory exists, 1157 then the dialog box will start with that directory. 1158 """ 1159 root = Tk() 1160 root.withdraw() 1161 if default == None: 1162 f = tkFileDialog.askdirectory(parent=root, title=title) 1163 else: 1164 f = tkFileDialog.askdirectory(parent=root, title=title, initialdir=default) 1165 if not f: return None 1166 return os.path.normpath(f)
1167 1168 1169 #------------------------------------------------------------------- 1170 # fileopenbox 1171 #-------------------------------------------------------------------
1172 -def fileopenbox(msg=None, title=None, default=None):
1173 """ 1174 A dialog to get a file name. 1175 Returns the name of a file, or None if user chose to cancel. 1176 1177 If the "default" argument specifies a file name, 1178 then the dialog box will start with that file. 1179 """ 1180 root = Tk() 1181 root.withdraw() 1182 f = tkFileDialog.askopenfilename(parent=root,title=title, initialfile=default) 1183 if not f: return None 1184 return os.path.normpath(f)
1185 1186 1187 #------------------------------------------------------------------- 1188 # filesavebox 1189 #-------------------------------------------------------------------
1190 -def filesavebox(msg=None, title=None, default=None):
1191 """ 1192 A file to get the name of a file to save. 1193 Returns the name of a file, or None if user chose to cancel. 1194 1195 If the "default" argument specifies a file name, 1196 then the dialog box will start with that file. 1197 """ 1198 root = Tk() 1199 root.withdraw() 1200 f = tkFileDialog.asksaveasfilename(parent=root, title=title, initialfile=default) 1201 if not f: return None 1202 return os.path.normpath(f)
1203 1204 1205 #------------------------------------------------------------------- 1206 # utility routines 1207 #------------------------------------------------------------------- 1208 # These routines are used by several other functions in the EasyGui module. 1209
1210 -def __buttonEvent(event):
1211 """ 1212 Handle an event that is generated by a person clicking a button. 1213 """ 1214 global root, __widgetTexts, __replyButtonText 1215 __replyButtonText = __widgetTexts[event.widget] 1216 root.quit() # quit the main loop
1217 1218
1219 -def __put_buttons_in_buttonframe(choices):
1220 """Put the buttons in the buttons frame 1221 """ 1222 global __widgetTexts, __firstWidget, buttonsFrame 1223 1224 __widgetTexts = {} 1225 i = 0 1226 1227 for buttonText in choices: 1228 tempButton = Button(buttonsFrame, takefocus=1, text=buttonText) 1229 tempButton.pack(expand=YES, side=LEFT, padx='1m', pady='1m', ipadx='2m', ipady='1m') 1230 1231 # remember the text associated with this widget 1232 __widgetTexts[tempButton] = buttonText 1233 1234 # remember the first widget, so we can put the focus there 1235 if i == 0: 1236 __firstWidget = tempButton 1237 i = 1 1238 1239 # bind the keyboard events to the widget 1240 tempButton.bind("<Return>", __buttonEvent) 1241 tempButton.bind("<Button-1>", __buttonEvent)
1242 1243 1244 #----------------------------------------------------------------------- 1245 # 1246 # test/demo easygui 1247 # 1248 #-----------------------------------------------------------------------
1249 -def _test():
1250 # simple way to clear the console 1251 print "\n" * 100 1252 # START DEMONSTRATION DATA =================================================== 1253 choices_abc = ["This is choice 1", "And this is choice 2"] 1254 msg = "Pick one! This is a huge choice, and you've got to make the right one " \ 1255 "or you will surely mess up the rest of your life, and the lives of your " \ 1256 "friends and neighbors!" 1257 title = "" 1258 1259 # ============================= define a code snippet ========================= 1260 code_snippet = ("dafsdfa dasflkj pp[oadsij asdfp;ij asdfpjkop asdfpok asdfpok asdfpok"*3) +"\n"+\ 1261 """# here is some dummy Python code 1262 for someItem in myListOfStuff: 1263 do something(someItem) 1264 do something() 1265 do something() 1266 if somethingElse(someItem): 1267 doSomethingEvenMoreInteresting() 1268 1269 """*16 1270 #======================== end of code snippet ============================== 1271 1272 #================================= some text =========================== 1273 text_snippet = ((\ 1274 """It was the best of times, and it was the worst of times. The rich ate cake, and the poor had cake recommended to them, but wished only for enough cash to buy bread. The time was ripe for revolution! """ \ 1275 *5)+"\n\n")*10 1276 1277 #===========================end of text ================================ 1278 1279 intro_message = ("Pick the kind of box that you wish to demo.\n\n" 1280 + "In EasyGui, all GUI interactions are invoked by simple function calls.\n\n" + 1281 "EasyGui is different from other GUIs in that it is NOT event-driven. It allows" + 1282 " you to program in a traditional linear fashion, and to put up dialogs for simple" + 1283 " input and output when you need to. If you are new to the event-driven paradigm" + 1284 " for GUIs, EasyGui will allow you to be productive with very basic tasks" + 1285 " immediately. Later, if you wish to make the transition to an event-driven GUI" + 1286 " paradigm, you can move to an event-driven style with a more powerful GUI package" + 1287 "such as anygui, PythonCard, Tkinter, wxPython, etc." 1288 + "\n\nEasyGui is running Tk version: " + str(TkVersion) 1289 ) 1290 1291 #========================================== END DEMONSTRATION DATA 1292 1293 1294 while 1: # do forever 1295 choices = [ 1296 "msgbox", 1297 "buttonbox", 1298 "buttonbox(image) -- an example of buttonbox with an 'image' specification", 1299 "choicebox", 1300 "multchoicebox", 1301 "textbox", 1302 "ynbox", 1303 "ccbox", 1304 "enterbox", 1305 "codebox", 1306 "integerbox", 1307 "boolbox", 1308 "indexbox", 1309 "filesavebox", 1310 "fileopenbox", 1311 "passwordbox", 1312 "multenterbox", 1313 "multpasswordbox", 1314 "diropenbox", 1315 "About EasyGui", 1316 " Help" 1317 ] 1318 choice = choicebox(msg=intro_message 1319 , title="EasyGui " + EasyGuiRevisionInfo 1320 , choices=choices) 1321 1322 if not choice: return 1323 1324 reply = choice.split() 1325 1326 if reply[0] == "msgbox": 1327 reply = msgbox("short msg", "This is a long title") 1328 print "Reply was:", repr(reply) 1329 1330 elif reply[0] == "About": 1331 reply = abouteasygui() 1332 1333 elif reply[0] == "Help": 1334 help("easygui") 1335 1336 elif reply[0] == "buttonbox": 1337 reply = buttonbox() 1338 print "Reply was:", repr(reply) 1339 1340 reply = buttonbox(msg=msg 1341 , title="Demo of Buttonbox with many, many buttons!" 1342 , choices=choices) 1343 print "Reply was:", repr(reply) 1344 1345 elif reply[0] == "buttonbox(image)": 1346 image = "python_and_check_logo.gif" 1347 msg = "Do you like this picture?" 1348 choices = ["Yes","No","No opinion"] 1349 1350 reply=buttonbox(msg,image=image,choices=choices) 1351 print "Reply was:", repr(reply) 1352 1353 image = os.path.normpath("python_and_check_logo.png") 1354 reply=buttonbox(msg,image=image, choices=choices) 1355 print "Reply was:", repr(reply) 1356 1357 image = os.path.normpath("zzzzz.gif") 1358 reply=buttonbox(msg,image=image, choices=choices) 1359 print "Reply was:", repr(reply) 1360 1361 elif reply[0] == "boolbox": 1362 reply = boolbox() 1363 print "Reply was:", repr(reply) 1364 1365 elif reply[0] == "enterbox": 1366 message = "Enter the name of your best friend."\ 1367 "\n(Result will be stripped.)" 1368 reply = enterbox(message, "Love!", " Suzy Smith ") 1369 print "Reply was:", repr(reply) 1370 1371 message = "Enter the name of your best friend."\ 1372 "\n(Result will NOT be stripped.)" 1373 reply = enterbox(message, "Love!", " Suzy Smith ",strip=False) 1374 print "Reply was:", repr(reply) 1375 1376 reply = enterbox("Enter the name of your worst enemy:", "Hate!") 1377 print "Reply was:", repr(reply) 1378 1379 elif reply[0] == "integerbox": 1380 reply = integerbox( 1381 "Enter a number between 3 and 333", 1382 "Demo: integerbox WITH a default value", 1383 222, 3, 333) 1384 print "Reply was:", repr(reply) 1385 1386 reply = integerbox( 1387 "Enter a number between 0 and 99", 1388 "Demo: integerbox WITHOUT a default value" 1389 ) 1390 print "Reply was:", repr(reply) 1391 1392 elif reply[0] == "diropenbox": 1393 title = "Demo of diropenbox" 1394 msg = "This is a test of the diropenbox.\n\nPick the directory that you wish to open." 1395 d = diropenbox(msg, title) 1396 print "You chose directory...:", d 1397 1398 elif reply[0] == "fileopenbox": 1399 f = fileopenbox() 1400 print "You chose to open file:", f 1401 1402 elif reply[0] == "filesavebox": 1403 f = filesavebox() 1404 print "You chose to save file:", f 1405 1406 elif reply[0] == "indexbox": 1407 title = reply[0] 1408 msg = "Demo of " + reply[0] 1409 choices = ["Choice1", "Choice2", "Choice3", "Choice4"] 1410 reply = indexbox(msg, title, choices) 1411 print "Reply was:", repr(reply) 1412 1413 elif reply[0] == "passwordbox": 1414 reply = passwordbox("Demo of password box WITHOUT default" 1415 + "\n\nEnter your secret password", "Member Logon") 1416 print "Reply was:", str(reply) 1417 1418 reply = passwordbox("Demo of password box WITH default" 1419 + "\n\nEnter your secret password", "Member Logon", "alfie") 1420 print "Reply was:", str(reply) 1421 1422 elif reply[0] == "multenterbox": 1423 msg = "Enter your personal information" 1424 title = "Credit Card Application" 1425 fieldNames = ["Name","Street Address","City","State","ZipCode"] 1426 fieldValues = [] # we start with blanks for the values 1427 fieldValues = multenterbox(msg,title, fieldNames) 1428 1429 # make sure that none of the fields was left blank 1430 while 1: 1431 if fieldValues == None: break 1432 errmsg = "" 1433 for i in range(len(fieldNames)): 1434 if fieldValues[i].strip() == "": 1435 errmsg = errmsg + ('"%s" is a required field.\n\n' % fieldNames[i]) 1436 if errmsg == "": break # no problems found 1437 fieldValues = multenterbox(errmsg, title, fieldNames, fieldValues) 1438 1439 print "Reply was:", fieldValues 1440 1441 elif reply[0] == "multpasswordbox": 1442 msg = "Enter logon information" 1443 title = "Demo of multpasswordbox" 1444 fieldNames = ["Server ID", "User ID", "Password"] 1445 fieldValues = [] # we start with blanks for the values 1446 fieldValues = multpasswordbox(msg,title, fieldNames) 1447 1448 # make sure that none of the fields was left blank 1449 while 1: 1450 if fieldValues == None: break 1451 errmsg = "" 1452 for i in range(len(fieldNames)): 1453 if fieldValues[i].strip() == "": 1454 errmsg = errmsg + ('"%s" is a required field.\n\n' % fieldNames[i]) 1455 if errmsg == "": break # no problems found 1456 fieldValues = multpasswordbox(errmsg, title, fieldNames, fieldValues) 1457 1458 print "Reply was:", fieldValues 1459 1460 1461 elif reply[0] == "ynbox": 1462 reply = ynbox(msg, title) 1463 print "Reply was:", repr(reply) 1464 1465 elif reply[0] == "ccbox": 1466 reply = ccbox(msg) 1467 print "Reply was:", repr(reply) 1468 1469 elif reply[0] == "choicebox": 1470 longchoice = "This is an example of a very long option which you may or may not wish to choose."*2 1471 listChoices = ["nnn", "ddd", "eee", "fff", "aaa", longchoice 1472 , "aaa", "bbb", "ccc", "ggg", "hhh", "iii", "jjj", "kkk", "LLL", "mmm" , "nnn", "ooo", "ppp", "qqq", "rrr", "sss", "ttt", "uuu", "vvv"] 1473 1474 msg = "Pick something. " + ("A wrapable sentence of text ?! "*30) + "\nA separate line of text."*6 1475 reply = choicebox(msg=msg, choices=listChoices) 1476 print "Reply was:", repr(reply) 1477 1478 msg = "Pick something. " 1479 reply = choicebox(msg=msg, choices=listChoices) 1480 print "Reply was:", repr(reply) 1481 1482 msg = "Pick something. " 1483 reply = choicebox(msg="The list of choices is empty!", choices=[]) 1484 print "Reply was:", repr(reply) 1485 1486 elif reply[0] == "multchoicebox": 1487 listChoices = ["aaa", "bbb", "ccc", "ggg", "hhh", "iii", "jjj", "kkk" 1488 , "LLL", "mmm" , "nnn", "ooo", "ppp", "qqq" 1489 , "rrr", "sss", "ttt", "uuu", "vvv"] 1490 1491 msg = "Pick as many choices as you wish." 1492 reply = multchoicebox(msg,"DEMO OF multchoicebox", listChoices) 1493 print "Reply was:", repr(reply) 1494 1495 elif reply[0] == "textbox": 1496 msg = "Here is some sample text. " * 16 1497 reply = textbox(msg, "Text Sample", text_snippet) 1498 print "Reply was:", repr(reply) 1499 1500 elif reply[0] == "codebox": 1501 msg = "Here is some sample code. " * 16 1502 reply = codebox(msg, "Code Sample", code_snippet) 1503 print "Reply was:", repr(reply) 1504 1505 else: 1506 msgbox("Choice\n\n" + choice + "\n\nis not recognized", "Program Logic Error") 1507 return
1508 1509 EASYGUI_ABOUT_INFORMATION = ''' 1510 ======================================================================== 1511 version 0.83 2008-06-12 1512 ======================================================================== 1513 1514 BUG FIXES 1515 ------------------------------------------------------ 1516 * fixed a bug in which fileopenbox, filesavebox, and diropenbox 1517 were returning an empty tuple, rather than None, when a user 1518 cancelled. Thanks to Nate Soares for reporting this and sending 1519 in a fix. 1520 1521 BACKWARD-INCOMPATIBLE CHANGES 1522 ------------------------------------------------------ 1523 * changed enterbox so that by default it strips its result 1524 (i.e. removes leading and trailing whitespace). 1525 If you want it not to strip, use keyword argument: strip=False. 1526 1527 This change makes it easier to test the results of the call:: 1528 1529 reply = enterbox(....) 1530 if reply: 1531 ... 1532 else: 1533 ... 1534 1535 * changed the name of the "button_text" (formerly "buttonMessage") parameter 1536 to "buttons" in the msgbox parameters. 1537 1538 ======================================================================== 1539 version 0.80 2008-06-02 1540 ======================================================================== 1541 1542 ENHANCEMENTS 1543 ------------------------------------------------------ 1544 * added image keyword to msgbox and buttonbox 1545 Note that it can display only .gif images. 1546 see: http://effbot.org/tkinterbook/photoimage.htm 1547 * improved a lot of the docstrings. 1548 * added a new abouteasygui() function 1549 1550 BUG FIXES 1551 ------------------------------------------------------ 1552 * changed mutable default arguments (lists) to tuples 1553 1554 * diropenbox, fileopenbox, and filesavebox now execute 1555 os.path.normpath() on the choice before returning it. 1556 This fixes a nasty bug/inconvenience for Windows users. 1557 1558 * In integerbox: 1559 old behavior: If user cancels, the default value is returned. 1560 new behavior: If user cancels, None is returned. 1561 1562 NOTE that this bugfix has the potential to break existing programs. 1563 1564 1565 CHANGES 1566 ------------------------------------------------------ 1567 * removed the "restore default" button on enterbox. 1568 It was non-standard and was too long to display properly in 1569 some environments. 1570 * default message for buttonbox changed from 1571 "Shall I continue?" to just "". 1572 1573 BACKWARD-INCOMPATIBLE CHANGES 1574 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1575 These changes may break backward compatibility. 1576 1577 Note that the following changes may break backward compatibility 1578 in programs that invoke EasyGui functions with keyword 1579 (rather than positional) arguments. 1580 1581 They have been changed in order to standardize keyword arguments, so 1582 that EasyGui functions can be more easily used with keyword arguments. 1583 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 1584 changed parameter name "message" to "msg" everywhere 1585 changed parameter name "buttonMessage" to "button_text" 1586 changed parameter name "argListOfFieldNames" to "fields" 1587 changed parameter name "argListOfFieldValues" to "values" 1588 1589 changed the following parameter names to "default": 1590 argDefault 1591 argDefaultPassword 1592 argDefaultText 1593 argInitialFile 1594 argInitialDir 1595 ''' 1596
1597 -def abouteasygui():
1598 """ 1599 shows the easygui revision history 1600 """ 1601 codebox("About EasyGui\n"+EasyGuiRevisionInfo,"EasyGui",EASYGUI_ABOUT_INFORMATION) 1602 return None
1603 1604 1605 1606 if __name__ == '__main__': 1607 _test() 1608