• No se han encontrado resultados

7. Resultados y discusión

7.2 Evaluación de distribuciones de dosis mediante PRC

6.2 Tkinter events 98

6.3 Callbacks 102

6.4 Lambda expressions 103

6.5 Binding events and callbacks 104

6.6 Timers and background procedures 107

6.7 Dynamic callback handlers 107 6.8 Putting events to work 108 6.9 Summary 119

GUI applications rely heavily on events and binding callbacks to these events in order to attach functionality to widgets. I anticipate that many readers may have some familiarity with this topic. However, this may be a new area for some of you, so I will go into some detail to make sure that the subject has been fully covered. Advanced topics will be discussed, including dynamic callback handlers, data verification techniques and “smart” widgets.

6.1 Event-driven systems: a review

It quite possible to build complex GUI applications without knowing anything about the underlying event-mechanism, regardless of whether the application is running in a UNIX, Windows or Macintosh environment. However, it is usually easier to develop an application that behaves the way you want it to if you know how to request and handle events within your application.

96

C H A P T E R 6 E V E N T S , B I N D I NG S A N D C A L L B A C K S Readers familiar with events and event handlers in X or with Windows messages might wish to skip ahead to look at “Tkinter events” on page 98, since this information is specific to Tkinter.

6.1.1 What are events?

Events are notifications (messages in Windows parlance) sent by the windowing system (the X-server for X, for example) to the client code. They indicate that something has occurred or that the state of some controlled object has changed, either because of user input or because your code has made a request which causes the server to make a change.

In general, applications do not receive events automatically. However, you may not be aware of the events that have been requested by your programs indirectly, or the requests that widgets have made. For example, you may specify a command callback to be called when a but-ton is pressed; the widget binds an activate event to the callback. It is also possible to request notification of an event that is normally handled elsewhere. Doing this allows your application to change the behavior of widgets and windows generally; this can be a good thing but it can also wreck the behavior of complex systems, so it needs to be used with care.

All events are placed in an event queue. Events are usually removed by a function called from the application’s mainloop. Generally, you will use Tkinter’s mainloop but it is possible for you to supply a specialized mainloop if you have special needs (such as a threaded appli-cation which needs to manage internal locks in a way which makes it impossible to use the stan-dard scheme).

Tkinter provides implementation-independent access to events so that you do not need to know too much about the underlying event handlers and filters. For example, to detect when the cursor enters a frame, try the following short example:

from Tkinter import * root = Tk()

def enter(event):

print 'Entered Frame: x=%d, y=%d' % (event.x, event.y) frame = Frame(root, width=150, height=150)

frame.bind('<Any-Enter>', enter) # Bind event frame.pack()

root.mainloop()

The bind method of Frame is used to bind the enter callback to an Any-Enter event.

Whenever the cursor crosses the frame boundary from the outside to the inside, the message will be printed.

This example introduces an interesting issue. Depending on the speed with which the cursor enters the frame, you will observe that the x and y coordinates show some variability. This is because the x and y values are determined at the time that the event is processed by the event loop not at the time the actual event occurs.

Example_6_1.py

Note

E V E NT - D R I V E N S Y S T EM S : A R E V I E W

97

6.1.2 Event propagation

Events occur relative to a window, which is usually described as the source window of the event. If no client has registered for a particular event for the source window, the event is propagated up the window hierarchy until it either finds a window that a client has registered with, it finds a window that prohibits event propagation or it reaches the root window. If it does reach the root window, the event is ignored.

Only device events that occur as a result of a key, pointer motion or mouse click are prop-agated. Other events, such as exposure and configuration events, have to be registered for explicitly.

6.1.3 Event types

Events are grouped into several categories depending on X event masks. Tk maps Windows events to the same masks when running on a Windows architecture. The event masks recog-nized by Tk (and therefore Tkinter) are shown in table 6.1.

Keyboard events

Whenever a key is pressed, a KeyPress event is generated, and whenever a key is released, a KeyRelease event is generated. Modifier keys, such as SHIFT and CONTROL, generate key-board events.

Pointer events

If buttons on the mouse are pressed or if the mouse is moved, ButtonPress, ButtonRe-lease and MotionNotify events are generated. The window associated with the event is the lowest window in the hierarchy unless a pointer grab exists, in that case, the window that ini-tiated the grab will be identified. Like keyboard events, modifier keys may be combined with pointer events.

Crossing events

Whenever the pointer enters or leaves a window boundary, an EnterNotify or LeaveNo-tify event is generated. It does not matter whether the crossing was a result of moving the pointer or because of a change in the stacking order of the windows. For example, if a window containing the pointer is lowered behind another window, and the pointer now is in the top

Table 6.1 Event masks used to group X events

NoEventMask StructureNotifyMask Button3MotionMask

KeyReleaseMask SubstructureNotifyMask Button5MotionMask

ButtonReleaseMask FocusChangeMask KeymapStateMask

LeaveWindowMask ColormapChangeMask VisibilityChangeMask PointerMotionHintMask KeyPressMask ResizeRedirectMask Button2MotionMask ButtonPressMask SubstructureRedirectMask Button4MotionMask EnterWindowMask PropertyChangeMask ButtonMotionMask PointerMotionMask OwnerGrabButtonMask

ExposureMask Button1MotionMask

98

C H A P T E R 6 E V E N T S , B I N D I NG S A N D C A L L B A C K S window, the lowered window receives a LeaveNotify event and the top window receives an EnterNotify event.

Focus events

The window which receives keyboard events is known as the focus window. FocusIn and FocusOut events are generated whenever the focus window changes. Handling focus events is a little more tricky than handling pointer events because the pointer does not necessarily have to be in the window that is receiving focus events. You do not usually have to handle focus events yourself, because setting takefocus to true in the widgets allows you to move focus between the widgets by pressing the TAB key.

Exposure events

Whenever a window or a part of a window becomes visible, an Exposure event is generated.

You will not typically be managing exposure events in Tkinter GUIs, but you do have the ability to receive these events if you have some very specialized drawing to support.

Configuration events

When a window’s size, position or border changes, ConfigureNotify events are generated.

A ConfigureNotify event will be created whenever the stacking order of the windows changes. Other types of configuration events include Gravity, Map/Unmap, Reparent and Visibility.

Colormap events

If a new colormap is installed, a ColormapNotify event is generated. This may be used by your application to prevent the annoying colormap flashing which can occur when another application installs a colormap. However, most applications do not control their colormaps directly.

Documento similar