Chapter 11 – Graphical User Interface Components: Part 2 Outline 11.1 11.2 11.3 11.4 11.5 11.6 11.7 11.8 11.9 Introduction Overview of Pmw ScrolledListbox Component ScrolledText Component MenuBar Component Popup Menus Canvas Component Scale Component Other GUI Toolkits 2002 Prentice Hall. All rights reserved. 1 2 11.1 Introduction • More advanced components and more complex GUIs • Python megawidgets (Pmw) toolkit provides highlevel GUI components developed from smaller Tkinter components • Introduce more Tkinter classes 2002 Prentice Hall. All rights reserved. 3 11.2 Overview of Pmw • Each Pmw component combines Tkinter components to create a useful, more complex component • Each subcomponent can be configured independently • Pmw option names have the form subcomponent_option • Method configure alters Pmw options 2002 Prentice Hall. All rights reserved. 4 11.3 ScrolledListbox Component • List box – Sometimes called a drop-down list – Provides a list of items from which a user can select – Implemented by Tkinter class Listbox – Scrolling through a list can be accomplished with a Tkinter Scrollbar • Pmw ScrolledListbox megawidget combines Tkinter classes Listbox and Scrollbar 2002 Prentice Hall. All rights reserved. 5 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # Fig. 11.1: fig11_01.py # ScrolledListBox used to select image. Import Pmw from Tkinter import * import Pmw module Outline fig11_01.py class ImageSelection( Frame ): """List of available images and an area to display them""" def __init__( self, images ): """Create list of PhotoImages and Label to display them""" Initialize Pmw Frame.__init__( self ) Pmw.initialise() self.pack( expand = YES, fill = BOTH ) self.master.title( "Select an image" ) self.photos = [] # add PhotoImage objects to list photos for item in images: self.photos.append( PhotoImage( file = item ) ) Create ScrolledListBox Assign component list to option items # create scrolled list boxnumber with vertical scrollbar Default of list items to display Scrollbar self.listBox = Pmw.ScrolledListBox( self, items = always images,present for list selection event listbox_height = Set 3, callback vscrollmode = "static", selectioncommand = self.switchImage ) self.listBox.pack( side = LEFT, expand = YES, fill = BOTH, padx = 5, pady = 5 ) self.display = Label( self, image = self.photos[ 0 ] ) self.display.pack( padx = 5, pady = 5 ) def switchImage( self ): """Change image in Label to current selection""" 2002 Prentice Hall. All rights reserved. 6 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 Return tuple containing index of selectedOutline item # get tuple containing index of selected list item chosenPicture = self.listBox.curselection() # configure label to display selected image if chosenPicture: choice = int( chosenPicture[ 0 ] ) self.display.config( image = self.photos[ choice ] ) fig11_01.py def main(): images = [ "bug1.gif", "bug2.gif", "travelbug.gif", "buganim.gif" ] ImageSelection( images ).mainloop() if __name__ == "__main__": main() 2002 Prentice Hall. All rights reserved. 7 11.4 ScrolledText Component • Pmw ScrolledText component combines Tkinter Text and Scrollbar components • Sometimes an external event (i.e., an event generated by a different GUI component) indicates when to process the text in a ScrolledText component 2002 Prentice Hall. All rights reserved. 8 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Outline # Fig. 11.2: fig11_02.py # Copying selected text from one text area to another. from Tkinter import * import Pmw fig11_02.py class CopyTextWindow( Frame ): """Demonstrate ScrolledTexts""" def __init__( self ): """Create two ScrolledTexts and a Button""" Frame.__init__( self ) Pmw.initialise() self.pack( expand = YES, fill = BOTH ) self.master.title( "ScrolledText Demo" ) Create Pmw ScrolledText component # create scrolled text box with word wrap enabled Enable word wrap Set number of columns Set number of rows self.text1 = Pmw.ScrolledText( self, Vertical scrollbar always present text_width =Horizontal 25, text_height 12, text_wrap scrollbar=always present = WORD, hscrollmode = "static", vscrollmode = "static" ) self.text1.pack( side = LEFT, expand = YES, fill = BOTH, padx = 5, pady = 5 ) self.copyButton = Button( self, text = "Copy >>>", command = self.copyText ) self.copyButton.pack( side = LEFT, padx = 5, pady = 5 ) Create uneditable ScrolledText component # create uneditable scrolled text box self.text2 = Pmw.ScrolledText( self, text_state = DISABLED, text_width = 25, text_height = 12, text_wrap = WORD, hscrollmode = "static", vscrollmode = "static" ) self.text2.pack( side = LEFT, expand = YES, fill = BOTH, padx = 5, pady = 5 ) 2002 Prentice Hall. All rights reserved. 9 36 37 38 39 40 41 42 43 44 45 def copyText( self ): Retrieve text """Set the text in the second ScrolledText""" Outlinetext1 from ScrolledText component self.text2.settext( self.text1.get( SEL_FIRST, SEL_LAST ) ) def fig11_02.py Arguments specify range of text to retrieve main(): Display text1’s selected text in ScrolledText component text2 CopyTextWindow().mainloop() if __name__ == "__main__": main() 2002 Prentice Hall. All rights reserved. 10 11.5 MenuBar Component • Menus – Contain lists of actions – Simply the appearance of GUIs • Pmw MenuBar contains methods necessary to manage a menu bar, a container for menus • Menu item – GUI component inside a menu that performs an action when selected by a user – command menu item – initiates an action – checkbutton menu item – toggled on or off – radiobutton menu item – a group presents mutually exclusive options 2002 Prentice Hall. All rights reserved. 11 11.5 Menubar Component – separator menu item – horizontal line groups related menu items – cascade menu item – submenu (or cascade menu) provides more menu items from which users can select • Balloons (also called tool-tips) display descriptions of menus and menu items 2002 Prentice Hall. All rights reserved. 12 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Outline # Fig. 11.3: fig11_03.py # MenuBars with Balloons demonstration. from Tkinter import * import Pmw import sys fig11_03.py class MenuBarDemo( Frame ): """Create window with a MenuBar""" def __init__( self ): """Create a MenuBar with items and a Canvas with text""" Frame.__init__( self ) Pmw.initialise() self.pack( expand = YES, fill = BOTH ) self.master.title( "MenuBar Demo" ) Create a Pmw self.master.geometry( "500x200" ) Balloon component Create Pmw MenuBar component self.myBalloon = Pmw.Balloon( self ) Specify Balloon component attached to MenuBar self.choices = Pmw.MenuBar( self, balloon = self.myBalloon ) self.choices.pack( fill = X ) Second argument specifies text of balloon Additems menu File to Pmw choices # create File menu and Add command menuMenuBar item to File menu Associate menu item with event Set name handler of menu item self.choices.addmenu( "File", "Exit" ) self.choices.addmenuitem( "File", "command", command = self.closeDemo, label = "Exit" ) Add submenu Color to menu Format # create Format menu and items Add separator menu item to menu Format self.choices.addmenu( "Format", "Change font/color" ) self.choices.addcascademenu( "Format", "Color" ) self.choices.addmenuitem( "Format", "separator" ) self.choices.addcascademenu( "Format", "Font" ) 2002 Prentice Hall. All rights reserved. 13 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 # add items to Format/Color menu colors = [ "Black", "Blue", "Red", "Green" ] self.selectedColor = StringVar() self.selectedColor.set( colors[ 0 ] ) Outline Create radiobutton menu items fig11_03.py Associate grouped radiobutton menu items with same callback for item in colors: self.choices.addmenuitem( "Color", "radiobutton", Associate grouped radiobutton menu items label = item, command = self.changeColor, variable = self.selectedColor ) with same variable # add items to Format/Font menu fonts = [ "Times", "Courier", "Helvetica" ] self.selectedFont = StringVar() self.selectedFont.set( fonts [ 0 ] ) for item in fonts: self.choices.addmenuitem( "Font", "radiobutton", label = item, command = self.changeFont, variable = self.selectedFont ) # add a horizontal separator in Font menu self.choices.addmenuitem( "Font", "separator" ) Create checkbutton menu item # associate checkbutton menu item with BooleanVar object self.boldOn = BooleanVar() self.choices.addmenuitem( "Font", "checkbutton", label = "Bold", command = self.changeFont, variable = self.boldOn ) # associate checkbutton menu item with BooleanVar object self.italicOn = BooleanVar() self.choices.addmenuitem( "Font", "checkbutton", label = "Italic", command = self.changeFont, variable = self.italicOn ) 2002 Prentice Hall. All rights reserved. 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 Create a Tkinter Canvas component with a white background text Outline # create Canvas with self.display = Canvas( self, bg = "white" ) self.display.pack( expand = YES, fill = BOTH ) Display Canvas text item fig11_03.py self.display.create_text( 250, 100, self.sampleText = text = "Sample Text", font = "Times 48" ) def changeColor( self ): Method configures """Change the color of the text itemconfig on the Canvas""" Canvas items Set fill color of Canvas item self.display.itemconfig( self.sampleText, fill = self.selectedColor.get() ) def changeFont( self ): """Change the font of the text on the Canvas""" # get selected font and attach size newFont = self.selectedFont.get() + " 48" # determine which checkbutton menu items selected if self.boldOn.get(): newFont += " bold" if self.italicOn.get(): newFont += " italic" # configure sample text to be displayed in selected style self.display.itemconfig( self.sampleText, font = newFont ) def closeDemo( self ): """Exit the program""" Terminate the program sys.exit() 2002 Prentice Hall. All rights reserved. 14 15 105 106 107 108 109 def main(): MenuBarDemo().mainloop() if __name__ == "__main__": main() Outline fig11_03.py 2002 Prentice Hall. All rights reserved. 16 11.6 Popup Menus • Context-sensitive popup menus created with Tkinter class Menu • Provide options specific to the component for which generated the popup trigger event 2002 Prentice Hall. All rights reserved. 17 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 Outline # Fig. 11.4: fig11_04.py # Popup menu demonstration. from Tkinter import * fig11_04.py class PopupMenuDemo( Frame ): """Demonstrate popup menus""" def __init__( self ): """Create a Menu but do not add it to the Frame""" Frame.__init__( self ) self.pack( expand = YES, fill = BOTH ) self.master.title( "Popup Menu Demo" ) self.master.geometry( "300x200" ) # create and pack frame with initial white background self.frame1 = Frame( self, bg = "white" ) self.frame1.pack( expand = YES, fill = BOTH ) Create Tkinter Menu component Remove default first entry, a dashed separator item # create menu without packing it self.menu = Menu( self.frame1, tearoff = 0 ) colors = [ "White", "Blue", "Yellow", "Red" ] self.selectedColor = StringVar() self.selectedColor.set( colors[ 0 ] ) Add radiobutton menu item to Tkinter Menu component for item in colors: self.menu.add_radiobutton( label = item, variable = self.selectedColor, command = self.changeBackgroundColor Associate right-mouse click) event # popup menu on right-mouse click self.frame1.bind( "<Button-3>", self.popUpMenu ) with callback popupMenu 2002 Prentice Hall. All rights reserved. 18 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 def popUpMenu( self, event ): """Add the Menu to the Frame""" Outline Display Menu component at given coordinates self.menu.post( event.x_root, event.y_root ) fig11_04.py def changeBackgroundColor( self ): """Change the Frame background color""" Set Frame component’s background color self.frame1.config( bg = self.selectedColor.get() ) def main(): PopupMenuDemo().mainloop() if __name__ == "__main__": main() 2002 Prentice Hall. All rights reserved. 19 11.7 Canvas Component • Tkinter component Canvas displays text, images, lines and shapes • Blank by default • Program creates canvas items to display items on a Canvas • New items drawn on existing items unless otherwise specified 2002 Prentice Hall. All rights reserved. 20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 Outline # Fig. 11.5: fig11_05.py # Canvas paint program. from Tkinter import * fig11_05.py class PaintBox( Frame ): """Demonstrate drawing on a Canvas""" def __init__( self ): """Create Canvas and bind paint method to mouse dragging""" Frame.__init__( self ) self.pack( expand = YES, fill = BOTH ) self.master.title( "A simple paint program" ) self.master.geometry( "300x150" ) self.message = Label( self, text = "Drag the mouse to draw" ) self.message.pack( side = BOTTOM ) Create Tkinter Canvas component # create Canvas component self.myCanvas = Canvas( self ) self.myCanvas.pack( expand = YES, fill =event BOTH to ) Bind mouse dragging Canvas component # bind mouse dragging event to Canvas self.myCanvas.bind( "<B1-Motion>", self.paint ) def paint( self, event ): """Create an oval of radiusx-4 and around the mouse of position""" Retrieve y- coordinates mouse position Create oval Canvas x1, y1 = ( event.x - 4 ), ( event.y - 4 ) item x2, y2 = ( event.x + 4 ), ( event.y + 4 ) self.myCanvas.create_oval( x1, y1, x2, y2, fill = "black" ) 2002 Prentice Hall. All rights reserved. 21 35 36 37 38 39 def main(): PaintBox().mainloop() if __name__ == "__main__": main() Outline fig11_05.py 2002 Prentice Hall. All rights reserved. 22 11.8 Scale Component • Tkinter component Scale enables user to select from a range of integer values • Has numeric values and a slider • Horizontal orientation: minimum value at extreme left and maximum value at extreme right • Vertical orientation: minimum value at extreme top and maximum value at extreme bottom 2002 Prentice Hall. All rights reserved. 23 11.8 Scale Component Numeric value slider 2002 Prentice Hall. All rights reserved. 24 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 # Fig. 11.7: fig11_07.py # Scale used to control the size of a circle. from Tkinter import * Outline fig11_07.py class ScaleDemo( Frame ): """Demonstrate Canvas and Scale""" def __init__( self ): """Create Canvas with a circle controlled by a Scale""" Frame.__init__( self ) self.pack( expand = YES, fill = BOTH ) self.master.title( "Scale Demo" ) self.master.geometry( "220x270" ) Specify Scale’s maximum value Create Tkinter Specify Scale Scale’s component minimum value # create Scale self.control = Scale( self, from_ = 0, to = 200, Set initial Scale value orient = HORIZONTAL, command = self.updateCircle ) self.control.pack( side = BOTTOM, fill = X ) self.control.set( 10 ) # create Canvas and draw circle self.display = Canvas( self, bg = "white" ) self.display.pack( expand = YES, fill = BOTH ) def updateCircle( self, scaleValue ): """Delete the circle, determine new size, draw again""" Delete previously drawn Canvas item end = int( scaleValue ) + 10 oval Canvas item Create self.display.delete( "circle" ) Option tags sets Canvas item’s name self.display.create_oval( 10, 10, end, end, fill = "red", tags = "circle" ) def main(): 2002 Prentice Hall. All rights reserved. 25 36 37 38 39 ScaleDemo().mainloop() if __name__ == "__main__": main() Outline fig11_07.py 2002 Prentice Hall. All rights reserved. 26 11.9 Other GUI Toolkits • PyGTK provides object-oriented interface for the Gimp Toolkit component set • wxPython extension module enables access to wxWindows, a GUI C++ library • PyOpenGL interface to OpenGL 2002 Prentice Hall. All rights reserved.