Size: 3343
Comment: remove old code since there's a revised example for 2.8
|
Size: 3346
Comment: code spacing
|
Deletions are marked like this. | Additions are marked like this. |
Line 45: | Line 45: |
tctl = wx.TextCtrl(self, value="What's up Doc?", size=(150,-1)) | tctl = wx.TextCtrl(self, value="What's up Doc?", size=(150, -1)) |
Line 53: | Line 53: |
sizer.Add((25,25)) | sizer.Add((25, 25)) |
Line 65: | Line 65: |
f = wx.Frame(None, title="PushEventHandler Tester", size=(400,350)) | f = wx.Frame(None, title="PushEventHandler Tester", size=(400, 350)) |
How do I use PushEventHandler?
Rick Zoerner wrote:
- Can someone explain to a non-C++ and new-to-Python programmer how to
implement the concept of PushEventHandler? Slowly, as if to a child, because every attempted explanation I've seen so far only seems to re-iterate exactly what it says in the wxWindows Reference (which I quite obviously don't understand).
First of all, in probably 85% of the cases where you would use PushEventHandler in C++ you do not need to do it in Python because you do not have to attach events to methods of the same class where the events happen.
But since you asked: PushEventHandler allows you to define event handlers in a class separate from the window class where they happen, and then set things up such that the new class gets first crack at handling the events for the class. They are often used when you want to add same or similar functionality to a variety of existing classes, without having to derive a new subclass of each of them. For example, suppose you wanted to track mouse down events for all the controls on a panel, and also on the panel itself. In the following code we push a new instance of MouseDownTracker on to each window we are interested in. Since MouseDownTracker binds to the EVT_LEFT_DOWN then its OnMouseDown will be called for each of the controls first, and then since it calls evt.Skip() the system will continue processing the event and default behaviour will happen for the mouse event too.
Of course, since this is Python we could have done almost exactly the same thing simply by putting OnMouseDown in the MyPanel class, and then using EVT_LEFT_DOWN to hook each of the controls to it, but using a separate wxEvtHandler helps separate the code a bit and helps promote reusability.
Comments
Thank you. Very helpful. Here is code updated to wxPython 2.8.9.x
1 import sys
2 import wx
3
4 class MouseDownTracker(wx.EvtHandler):
5 def __init__(self, log):
6 wx.EvtHandler.__init__(self)
7 self.log = log
8 wx.EVT_LEFT_DOWN(self, self.OnMouseDown)
9
10 def OnMouseDown(self, evt):
11 pos = evt.GetPosition()
12 window = self.GetNextHandler()
13 self.log.write("Mouse down at %s on %s\n" % (pos, window.__class__.__name__))
14 evt.Skip()
15
16
17 class MyPanel(wx.Panel):
18 def __init__(self, parent, log):
19 wx.Panel.__init__(self, parent)
20
21 stxt = wx.StaticText(self, label="Hello")
22 tctl = wx.TextCtrl(self, value="What's up Doc?", size=(150, -1))
23 btn = wx.Button(self, label="Click Me!")
24
25 stxt.PushEventHandler(MouseDownTracker(sys.stdout))
26 tctl.PushEventHandler(MouseDownTracker(sys.stdout))
27 btn.PushEventHandler(MouseDownTracker(sys.stdout))
28
29 sizer = wx.BoxSizer(wx.VERTICAL)
30 sizer.Add((25, 25))
31
32 row = wx.BoxSizer(wx.HORIZONTAL)
33 row.Add((25,1))
34 row.Add(stxt, 0, wx.ALL, 5)
35 row.Add(tctl, 0, wx.ALL, 5)
36 row.Add(btn, 0, wx.ALL, 5)
37 sizer.Add(row)
38 self.SetSizer(sizer)
39
40
41 app = wx.App(False)
42 f = wx.Frame(None, title="PushEventHandler Tester", size=(400, 350))
43 p = MyPanel(f, sys.stdout)
44 p.PushEventHandler(MouseDownTracker(sys.stdout))
45 f.Show()
46 app.MainLoop()