1 / 43

Object-Oriented Programming in Python Goldwasser and Letscher Chapter 15 Event-Driven Programming

Object-Oriented Programming in Python Goldwasser and Letscher Chapter 15 Event-Driven Programming. Terry Scott University of Northern Colorado 2007 Prentice Hall. Introduction: What is Covered in Chapter 15. Basics of event-driven programming. Event Handling in cs1graphics. Event class.

alcina
Télécharger la présentation

Object-Oriented Programming in Python Goldwasser and Letscher Chapter 15 Event-Driven Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Object-Oriented Programming in PythonGoldwasser and LetscherChapter 15Event-Driven Programming Terry Scott University of Northern Colorado 2007 Prentice Hall

  2. Introduction: What is Covered in Chapter 15 • Basics of event-driven programming. • Event Handling in cs1graphics. • Event class. • Programming using events. • Case Study: a full GUI for mastermind. Terry Scott University of Northern Colorado 2007 Prentice Hall

  3. Programming Styles • Programming style so far might be described as flow control: • Program flows in a preplanned way. • It may wait for input from the user. • Event-driven programming: • program decides what to do next based on events that occur (mouse clicks, keyboard clicks). • Graphical user interface (GUI) pronounced gooey is one kind of event-driven programming. • GUI is what most of us are used to when using an operating system whether it is Windows, a Mac, or X-windows on Linux. Terry Scott University of Northern Colorado 2007 Prentice Hall

  4. Basics of Event-Driven Programming • name = raw_input() • The program waits for the user to enter a response. • The entering of the response is an event. • The following code waits for the user to click the mouse on the paper. This is also an event. paper = Canvas() cue = paper.wait() ball = Circle(10, cue.getMouseLocation()) paper.add(ball) Terry Scott University of Northern Colorado 2007 Prentice Hall

  5. Basics of Event-Driven Programming • Both previous examples are event driven. • However they are still both sequential. • Program advances to the spot where it waits until the event occurs and then it continues. • For true event handling the program is described by what is to be done when various events occur. Terry Scott University of Northern Colorado 2007 Prentice Hall

  6. Basics of Event-Driven Programming • Event handlers – code that is called when an event occurs. • A stand-alone event handler is referred to as a callback function. • Event loop is a code loop that waits for various prescribed events to occur. This is something like an infinite while loop but it is part of the class and is hidden from the user of the class. • A thread is a way for a single processor to execute different pieces of code. Terry Scott University of Northern Colorado 2007 Prentice Hall

  7. cs1graphics Event Programming • When cs1graphics is started the event loop is started as well. • Included in the cs1graphics module is an EventHandler class. • Basic handler that prints Event Triggered when an event occurs is shown below. class BasicHandler(EventHandler): def handle(self, event): print 'Event Triggered' Terry Scott University of Northern Colorado 2007 Prentice Hall

  8. Registering a Handler with a Graphics Object #The following code will print 'Event Triggered' #every time the mouse is clicked on the Canvas. simple = BasicHandler() #create handler object paper = Canvas() paper.addHandler(simple) #adds handler to paper # Could just as well have added a circle to # the paper and then added the handler to the # circle and then would respond only when the # circle was clicked. Terry Scott University of Northern Colorado 2007 Prentice Hall

  9. A Handler with State Information #Handler keeps track of how many times it. #has been clicked. Displays results on shell. class CountingHandler(EventHandler): def __init__(self): EventHandler.__init__(self) #call parent self.__count = 0 #constructor def handle(self, event): self._count += 1 print 'Event Triggered. Count: ', self._count Terry Scott University of Northern Colorado 2007 Prentice Hall

  10. Event Handler with State Info. #Displays number of clicks on the canvas. class TallyHandler(EventHandler): def __init__(self, textObj): EventHandler.__init__(self) self.__count = 0 self._text = textObj self._textObj.setMessage(str(self._count)) #reset to 0 def handle(self, event): self._count += 1 self._textObj.setMessage(str(self._count)) paper = Canvas(100,100) score = Text(' ', 12, Point(40,40)) paper.add(score) referee = TallyHandler(score) #create handler paper.addHandler(referee) #activate handler Terry Scott University of Northern Colorado 2007 Prentice Hall

  11. Event Handler That Closes After One Event class HandleOnce(EventHandler): def __init__(self, eventTrigger): EventHandler.__init__(self) self._trigger = eventTrigger def handle(self, event): print "That's all folks!!!" self._trigger.removeHandler(self) paper = Canvas( ) oneTime = HandleOnce(paper) paper.addHandler(oneTime) Terry Scott University of Northern Colorado 2007 Prentice Hall

  12. The Event Class • So far the signature of the handler has been: def handle(self, event): • Have not done anything with event. • One method in the event class is getTrigger(). This returns a reference to the object where the event occurred. • Can use this to write the HandleOnce class with fewer lines of code. Terry Scott University of Northern Colorado 2007 Prentice Hall

  13. Using getTrigger Method class HandleOnce(EventHandler): def handle(self, event): print "That's all folks!!!" event.getTrigger().removeHandler(self) paper = Canvas( ) oneTime = HandleOnce(paper) paper.addHandler(oneTime) Terry Scott University of Northern Colorado 2007 Prentice Hall

  14. Mouse Events • Event object method: getDescription(). This returns the event type. For the mouse this can be: • 'mouse click' – mouse button clicked • 'mouse release' – mouse button released • 'mouse drag' – mouse moved • Event object method: getMouseLocation(). This returns the mouse coordinates when the mouse is clicked. Terry Scott University of Northern Colorado 2007 Prentice Hall

  15. Mouse Events #Draws circle when the mouse is clicked. class CircleDrawHandler(EventHandler): def handle(self, event): if event.getDescription() == 'mouse click': c = Circle(5, event.getMouseLocation()) event.getTrigger().add(c) #adds circle to #canvas paper = Canvas(100,100) handler = CircleDrawHandler( ) paper.addHandler(handler) Terry Scott University of Northern Colorado 2007 Prentice Hall

  16. Mouse Events • In a 'mouse drag' event the getOldMouseLocation() method remembers where the mouse was originally. • A program might want different behavior for stationary click than one where the mouse was dragged and then clicked. • See code on next page for an example of detecting whether the mouse was dragged before it was clicked. • _mouseDragged keeps track of whether mouse was dragged since the last mouse click. Terry Scott University of Northern Colorado 2007 Prentice Hall

  17. class ClickAndReleaseHandler(EventHandler): def __init__(self): EventHandler.__init__(self) self._mouseDragged = False def handle(self, event): if event.getDescription( ) = 'mouse click': self._mouseDragged = False elif event.getDescription() = 'mouse drag' self._mouseDragged = True elif event.getDescription() == 'mouse release': if self._mouseDragged: print 'Mouse was dragged' else: print 'Mouse was clicked without dragging' paper = Canvas( ) dragDetector = ClickAndReleaseHandler() paper.addHandler(dragDetector) Terry Scott University of Northern Colorado 2007 Prentice Hall

  18. Keyboard Events • Keyboard causes an event. • Method getKey() determines which key was depressed. • Code on next slide allows keyboard presses to be displayed on the Canvas Text widget. Terry Scott University of Northern Colorado 2007 Prentice Hall

  19. Keyboard Events Code class KeyHandler(EventHandler): def __init__(self, textObj): EventHandler.__init__(self) self._textobj = textObj def handle(self, event): if event.getDescription( ) = 'keyboard': self._textObj.setMessage(self._textObj.getMessage() + event.getKey()) elif event.getDescription() = 'mouse click' self._textObj.setMessage(' ') #clears the text paper = Canvas( ) textDisplay = Text(' ', 12, Point(100,100)) paper.add(textDisplay) echo = KeyHandler(textDisplay) paper.addHandler(echo) Terry Scott University of Northern Colorado 2007 Prentice Hall

  20. Timers • alarm = timer(10, True) • 10: The timer generates an event after 10 seconds. • True: timer repeats. If set to False or left off, then is a one time event. • alarm.start() – starts timer. • Second slide rotates a circle around a point outside the circle. Terry Scott University of Northern Colorado 2007 Prentice Hall

  21. Timer Code alarm = Timer(1, True) stopwatch = CountingHandler() alarm.addHandler(stopwatch) print 'Ready . . .' alarm.start( ) #displays Ready … every sec. Terry Scott University of Northern Colorado 2007 Prentice Hall

  22. Rotate a Circle class RotationHandler(EventHandler): def __init__(self, shape): self._shape = shape def handle(self, event): self._shape.rotate paper = Canvas(100,100) sampleCircle = Circle(20, Point(50,20)) sampleCircle.adjustReference(0,30) paper.add(sampleCircle) alarm = Timer(0.1, True) rotator = RotationHandler(sampleCircle) alarm.addHandler(rotator) alarm.start() Terry Scott University of Northern Colorado 2007 Prentice Hall

  23. Monitor • Class with two methods: • wait( ) : forces a wait for an event. • release( ): event occurs causes the wait to be released. • Monitor like wait() except it is released on any event but the monitor can be set to only release on certain events. Terry Scott University of Northern Colorado 2007 Prentice Hall

  24. Code Using a Monitor class ShapeHandler(EventHandler): def __init__(self, monitor): EventHandler.__init__(self) self._monitor = monitor def handle(self,event): if event.getDescription( ) == 'mouse drag': self._monitor.release( ) #release on mouse #drag #code using this class on next slide Terry Scott University of Northern Colorado 2007 Prentice Hall

  25. Coding Using a Monitor (continue) paper = Canvas() checkpoint = Monitor() handler = ShapeHandler(checkpoint) cir = Circle(10, Point(50,50)) cir.setFillColor('blue') cir.addHandler(handler) paper.add(cir) checkpoint.wait() #forced to wait until mouse is #dragged inside circle paper.setBackgroundColor('green') Terry Scott University of Northern Colorado 2007 Prentice Hall

  26. Adding and Moving Shapes on a Canvas • Code on the next slides does the following: • when mouse is clicked on canvas it creates a new shape. Cycles through circle, square, rectangle, and a triangle. • dragging mouse on existing shape moves it. • when mouse clicked it enlarges object. • typing on keyboard changes color of current in-focus shape. Terry Scott University of Northern Colorado 2007 Prentice Hall

  27. Adding and Moving Shapes Code # class ShapeHandler(EventHandler): def __init__(self): EventHandler.__init__(self): self._mouseDragged= False Terry Scott University of Northern Colorado 2007 Prentice Hall

  28. Adding and Moving Shapes Code (continued) def handle(self, event): shape = event.getTrigger( ) if event.getDescription( ) == 'mouse drag': old = event.getOldMouseLocation( ) new = event.getMouseLocation( ) shape.move(new.getX()–old.getX(),new.getY() - old.getY( ) self._mouseDragged = True elif even.getDescription( ) == 'mouse click': self._mouseDragged = False elif event.getDescription() == 'mouse release': if not self._mouseDragged: shape.scale(1.5) elif event.getDescription() == 'keyboard': shape.setFillColor(Color.randomColor()) Terry Scott University of Northern Colorado 2007 Prentice Hall

  29. Adding and Moving Shapes Code (continued) class NewShapeHandler(EventHandler): def __init__(self): EventHandler.__init__(self) self._shapeCode = 0 self._handler = ShapeHandler() #single instance handles all shapes Terry Scott University of Northern Colorado 2007 Prentice Hall

  30. Adding and Moving Shapes Code (continued) def handle(self, event): if event.getDescription() == 'mouse click': s = Circle(10) elif self._shapeCode == 1: s = Square(10) elif self._shAapeCode == 2 s = Rectangle(15, 5) elif self._shapeCode == 3: s = Polygon(Point(5,5), Point(0,-5),Point(-5,5)) Terry Scott University of Northern Colorado 2007 Prentice Hall

  31. Adding and Moving Shapes Code (continued) self._shapeCode = (self._shapeCode+1)% 4 #advance cyclically s.move(event.getMouseLocation().getX(), event.getMouseLocation().getY()) s.setFillColor('white') event.getTrigger().add(s) #add shape to canvas s.addHandler(self._handler) #register the #ShapeHandler with new shape paper = Canvas(400, 300, 'white', 'Click me!') paper.addHandler(self._handler) #instantiate handler and #register all at once Terry Scott University of Northern Colorado 2007 Prentice Hall

  32. Dialog Box Class • Dialog is not a full fledged window. Can not change its size. • Used for asking a question such as: Do you wish to continue? • The dialog class constructor is called with: Dialog(prompt, options, title, width, height). Terry Scott University of Northern Colorado 2007 Prentice Hall

  33. Dialog Box Code survey = Dialog('How would you rate this', 'interface', 'good','so-so','poor'), 'User Survey') answer = survey.display() if answer != 'good' print "Let's see you do better" Terry Scott University of Northern Colorado 2007 Prentice Hall

  34. Dialog Box Survey Output Terry Scott University of Northern Colorado 2007 Prentice Hall

  35. Stopwatch Widget Class • Unlike the dialog box this creates an actual component to go on the window. • Called a widget. • This uses multiple inheritance: • Layer. • EventHandler. • See code on pages 511-512. Terry Scott University of Northern Colorado 2007 Prentice Hall

  36. Stopwatch Widget Terry Scott University of Northern Colorado 2007 Prentice Hall

  37. Stopwatch Widget Code class Stopwatch(Layer, EventHandler): def __init__(self): #create stopwatch instance Layer.__init__(self) border = Rectangle(200,100) border.setFillColor('white') border.setDepth(52) self._display = Text('0:00', 36, Point(-25,-40) self._start = Square(40,Point(-60,25)) self._reset = Square(40, Point(60,26)) buttons=[self._start, self._stop, self._reset) Terry Scott University of Northern Colorado 2007 Prentice Hall

  38. Stopwatch Widget Code (continued) for b in buttons: b.setFillColor('lightgray') b.setDepth(51) #in front of border, behind icons starIcon = Polygon(Point(-70,15),Point(-70,35), Point(-50,25)) startIcon.setFillColor('black') stopIcon =Square(20,Point(0,25)) stopIcon.setFillColor('black') resetIcon = Text('00',24,Point(47,15)) for obj in buttons+[self._display,border,startIcon, stopIcon,resetIcon]: self.add(obj) #add to the layer Terry Scott University of Northern Colorado 2007 Prentice Hall

  39. Stopwatch Widget Code (continued) self._clock = 0 #measured in seconds self._timer = Timer(1, True) for active in (self._timer,self._start,self._stop,self._reset): active.addHandle(self) #handle all events def getTime(self): """Convert clock's time to a string with minutes and seconds""" min = str(self._clock //60) sec = str(self._clock %60) if (len(sec) == 1: sec = '0' + sec #pad with leading 0 return min + ':' +sec Terry Scott University of Northern Colorado 2007 Prentice Hall

  40. Stopwatch Widget Code (continued) def handle(self, event): #deal with each event if event.getDescription() == 'timer': self._clock += 1 self._display.setText(self.getTime()) elif event.getDescription() == 'mouse click': if event.getTrigger() == self._start: self._timer.start() elif event.getTrigger() == self.stop: self._time.stop() else: self._clock = 0 self._display.setText(self.getTime()) Terry Scott University of Northern Colorado 2007 Prentice Hall

  41. Stopwatch Widget Code (continued) if __name__ == '__main__': paper = Canvas(400,400) clock = Stopwatch() paper.add(clock) clock.move(200,200) Terry Scott University of Northern Colorado 2007 Prentice Hall

  42. Mastermind GUI • MastermindGUI must perform all tasks of both the input and output classes. • Full code is on pages 515 – 518. Terry Scott University of Northern Colorado 2007 Prentice Hall

  43. A Full GUI for Mastermind Terry Scott University of Northern Colorado 2007 Prentice Hall

More Related