/examples/thinking_in_tkinter/tt060.py

https://github.com/jasoncbautista/Focus-Motivator · Python · 131 lines · 114 code · 8 blank · 9 comment · 2 complexity · 84d944aa43e5f5c5c4ce52ff6ec8fe75 MD5 · raw file

  1. """<tt060.py
  2. Now it is time to get our buttons to do something. We turn our attention to the
  3. last two (or our original four) basic GUI tasks -- writing event handler
  4. routines to do the actual work of our program, and binding the event handler
  5. routines to widgets and events.
  6. Note that in this program we have abandoned all the buttons that we created in
  7. our last program, and have returned to a simpler situation in which our GUI
  8. contains only two buttons: "OK" and "Cancel".
  9. As you will remember from the discussion in our first program, one of the basic
  10. GUI task is "binding". "Binding" is the process of defining a connection or
  11. relationship between (usually):
  12. * a widget,
  13. * a type of event, and
  14. * an "event handler".
  15. An "event handler" is a method or subroutine that handles events when they
  16. occur. [In Java, event handlers are called "listeners". I like this name,
  17. because it suggests exactly what they do -- "listen" for events, and respond to
  18. them.]
  19. In Tkinter, the way that you create this binding is through the bind() method
  20. that is a feature of all Tkinter widgets. You use the bind() method in a
  21. statement of the form:
  22. widget.bind(event_type_name, event_handler_name)
  23. This kind of binding is called "event binding".
  24. [There is another way of binding an event_handler to a widget. It is called
  25. "command binding" and we will look at it a couple of programs from now. But for
  26. now, let's look at event binding. Once we understand what event binding is, it
  27. will make it easier to explain command binding.]
  28. Before we begin, we need to point out a possible point of confusion. The word
  29. "button" can be used to refer to two entirely different things: (1) a button
  30. widget -- a GUI component that is displayed on the computer monitor -- and (2) a
  31. button on your mouse -- the kind of button that you press with your finger. In
  32. order to avoid confusion, I will usually try to distinguish them by referring to
  33. "button widget" or "mouse button" rather than simply to "button".
  34. (1)
  35. We bind "<Button-1>" events (clicks of the left mouse button) on the button1
  36. widget to the "self.button1Click" method. When button1 is left-clicked with the mouse,
  37. the self.button1Click() method will be invoked to handle the event.
  38. (3)
  39. Note that, although they aren't specified on the "bind" operation, self.button1Click()
  40. will be passed two arguments. The first, of course, will be "self", which is always the first
  41. argument to all class methods in Python. The second will be an event object. This technique of binding
  42. and event (that is, using the bind() method) always implicitly passes an event object as
  43. an argument.
  44. In Python/Tkinter, when an event occurs, it takes the form of an event object. An
  45. event object is extremely useful, because it carries with it all sorts of useful information
  46. and methods. You can examine the event object to find out what kind of event occurred,
  47. the widget where it occurred, and other useful bits of information.
  48. (4)
  49. So, what do we want to happen when button1 is clicked? Well, in this case we have
  50. it do something quite simple. It simply changes its color from green to yellow, and
  51. back again.
  52. (2)
  53. Let's make button2 (the "Goodbye!" button) actually do some useful work. We will make
  54. it shut down the window. So we bind a left-mouse click in button2 to the button2Click()
  55. method, and
  56. (6)
  57. We have the button2Click() method destroy the root window, the parent window of
  58. myapp. This will have a ripple effect, and will destroy all the children and
  59. descendents of the root. In short, every part of the GUI will be destroyed.
  60. Of course, to do this, myapp has to know who its parent is. So (7) we add code
  61. to its constructor to allow myapp to remember its parent.
  62. PROGRAM BEHAVIOR
  63. When you run this program, you will see two buttons. Clicking on the "OK" button
  64. will change its color. Clicking on the "Cancel" button will shut down the
  65. application.
  66. When our GUI is open, if you hit the TAB key on the keyboard, you will notice
  67. that the keyboard focus tabs between the two buttons. But if you hit the
  68. ENTER/RETURN key on the keyboard, nothing happens. That is because we have
  69. bound only mouse clicks, not keyboard events, to our buttons. Our next task
  70. will be to bind keyboard events to the buttons, also.
  71. Finally, notice that because the text of one button is shorter than the text of the
  72. other, the two buttons are of different sizes. This is rather ugly. We will
  73. fix that in a later program.
  74. [revised: 2002-10-01]
  75. >"""
  76. from Tkinter import *
  77. class MyApp:
  78. def __init__(self, parent):
  79. self.myParent = parent ### (7) remember my parent, the root
  80. self.myContainer1 = Frame(parent)
  81. self.myContainer1.pack()
  82. self.button1 = Button(self.myContainer1)
  83. self.button1.configure(text="OK", background= "green")
  84. self.button1.pack(side=LEFT)
  85. self.button1.bind("<Button-1>", self.button1Click) ### (1)
  86. self.button2 = Button(self.myContainer1)
  87. self.button2.configure(text="Cancel", background="red")
  88. self.button2.pack(side=RIGHT)
  89. self.button2.bind("<Button-1>", self.button2Click) ### (2)
  90. def button1Click(self, event): ### (3)
  91. if self.button1["background"] == "green": ### (4)
  92. self.button1["background"] = "yellow"
  93. else:
  94. self.button1["background"] = "green"
  95. def button2Click(self, event): ### (5)
  96. self.myParent.destroy() ### (6)
  97. root = Tk()
  98. myapp = MyApp(root)
  99. root.mainloop()