Investigating mouse events


Just started a new small project for which some low level mouse event tracking seems handy. So I started with reading about events and event handlers. My first tryout is translating mouse event numbers (obtained by evt,GeteventType() back to some meaningfull text. No luck so far. Could someone please have a look at this code and tell me what I am missing?

import wx

class Example(wx.Frame):
    def __init__(self, *args, **kw):
        super(Example, self).__init__(*args, **kw)
        self.Bind(wx.EVT_MOUSE_EVENTS, self.OnMouseEvent)

    def OnMouseEvent (self, evt):
        et = evt.GetEventType()

        if et == wx.EVT_ENTER_WINDOW:
            print ("EVT_ENTER_WINDOW")
        elif et == wx.EVT_LEAVE_WINDOW:
            print ("EVT_LEAVE_WINDOW")

        elif et == wx.EVT_LEFT_DOWN:
            print ("EVT_LEFT_DOWN")            
        elif et == wx.EVT_LEFT_UP:
            print ("EVT_LEFT_UP")     
        elif et == wx.EVT_LEFT_DCLICK:
            print ("EVT_LEFT_DCLICK")     

        elif et == wx.EVT_MIDDLE_DOWN:
            print ("EVT_MIDDLE_DOWN")            
        elif et == wx.EVT_MIDDLE_UP:
            print ("EVT_MIDDLE_UP")     
        elif et == wx.EVT_MIDDLE_DCLICK:
            print ("EVT_MIDDLE_DCLICK")     

        elif et == wx.EVT_RIGHT_DOWN:
            print ("EVT_RIGHT_DOWN")            
        elif et == wx.EVT_RIGHT_UP:
            print ("EVT_RIGHT_UP")     
        elif et == wx.EVT_RIGHT_DCLICK:
            print ("EVT_RIGHT_DCLICK")     

        elif et == wx.EVT_MOUSE_AUX1_DOWN:
            print ("EVT_MOUSE_AUX1_DOWN")            
        elif et == wx.EVT_MOUSE_AUX1_UP:
            print ("EVT_MOUSE_AUX1_UP")     
        elif et == wx.EVT_MOUSE_AUX1_DCLICK:
            print ("EVT_MOUSE_AUX1_DCLICK")     

        elif et == wx.EVT_MOUSE_AUX2_DOWN:
            print ("EVT_MOUSE_AUX2_DOWN")            
        elif et == wx.EVT_MOUSE_AUX2_UP:
            print ("EVT_MOUSE_AUX2_UP")     
        elif et == wx.EVT_MOUSE_AUX2_DCLICK:
            print ("EVT_MOUSE_AUX2_DCLICK")     

        elif et == wx.EVT_MOTION:
            print ("EVT_MOTION")            

        elif et == wx.EVT_MOUSEWHEEL:
            print ("EVT_MOUSEWHEEL")            

        elif et == wx.EVT_MOUSE_EVENTS:
            print ("EVT_MOUSE_EVENTS")            

            print (et)

if __name__ == '__main__':
    app = wx.App()
    frm = Example(None)

Uhm, I’m afraid you’re way off your mark here. Sometimes you can dig deeper by simply firing up a shell and

>>> import wx

Now, first of all, names like “wx.EVT_***” are not event types at all, they are event binders, and, in fact, objects (yes, despite their constant-like appearance… it’s a long story…):

>>> wx.EVT_BUTTON # this guy is really an object in disguise... 
<wx.core.PyEventBinder object at 0x.....>

Event types are attached to binders and they are, indeed, numerical constants. They are stored in the “evtType” attribute of the binder object:

>>> wx.EVT_BUTTON.evtType

except, the “evtType” attribute is really a list, not a number yet. This is because, while most binders have just one event type, a few “collective” binders may have many types attached:

>>> wx.EVT_MOUSE_EVENTS.evtType
[10030, 10031, 10032, 10033, 10034, 10035, 10036, 10039, 10040, 10041, 
 10037, 10038, 10045, 10046, 10047, 10048, 10049, 10050, 10051]

Now for the fun part: every single event type (numerical constant) also comes with its own symbol, in the form of “wx.wxEVT_***”:

>>> wx.wxEVT_BUTTON  # now, that's what I call a *number*!

Of course you cannot have also a “wx.wxEVT_MOUSE_EVENTS”, but you do have the likes of

>>> wx.wxEVT_LEFT_UP
>>> wx.wxEVT_LEFT_DOWN

and so on.

Wrapping things up, your code works fine either if you write

    def OnMouseEvent (self, evt):
        et = evt.GetEventType()  # this is a *number*
        if [et] == wx.EVT_ENTER_WINDOW.evtType:  # but evtType is a *list* !
            print ("EVT_ENTER_WINDOW")
        elif [et] == wx.EVT_LEAVE_WINDOW.evtType:
            print ("EVT_LEAVE_WINDOW")
        # etc etc


    def OnMouseEvent (self, evt):
        et = evt.GetEventType()  # this is a *number*
        if et == wx.wxEVT_ENTER_WINDOW:  # this is a number too!
            print ("EVT_ENTER_WINDOW")
        elif et == wx.wxEVT_LEAVE_WINDOW:
            print ("EVT_LEAVE_WINDOW")
        # etc etc

With all that being said, no one would ever do something like that.
Just use the handy wx.MouseEvent methods to query what kind of action was performed:

    def OnMouseEvent (self, evt):
        if evt.LeftDown():
            print('left down')
        elif evt.LeftUp():
            print('left up')
        # etc. etc.

or, if you want to save a few lines, even something like

    def OnMouseEvent (self, evt):
        for meth_name in ('LeftDown', 'LeftUp', 'Entering', 'Leaving'): # add to taste
            if getattr(evt, meth_name)():

Thank you very much for explaining! I’ll dig into this stuff some more :man_facepalming:

Hi Adriaan,

If you are new to wxPython, I recommend you to run wxdemo ("/Scripts/wxdemo.exe") first.
In wxdemo, you can call InspectorTool to inspect objects and trace all events triggered by the user or system.

In wxdemo,

  1. Select the module from the left treeview pane
  2. From menu [Help], open [Widget Inspector]

In InspectionTool,

  1. Click [Find] and click the (demonstrating) control you want to inspect.
    Then, the object tree will be expanded under [Widget Tree].
  2. To watch events, click [Events]
  3. To watch events of extra modules (e.g., press [Add Module], and input
    To watch the contents of the event, just d-click the items to popup the tooltips.
  4. In Pycrust window, you can access the target with obj for more inspection.

If you like, please check my previous post to see how to call it programatically.

Thank you komoto48g, I did indeed discover the demo app and had a peek in the code here and there. In the meantime i am way further now by reworking my test code and reading more about the event handling etc… My next newbie question is on the way.