Explore Books related to Python. Click Here

wxPython: Get the Event Name Instead of an Integer

There was a recent post on StackOverflow that I thought was interesting. It asked how to get the event name from the event object, such as EVT_BUTTON, rather than the event's id number. So I did some investigation into the subject and there is nothing builtin to wxPython that does this task. Robin Dunn, creator of wxPython, recommended that I should create a dictionary of the events and their ids to accomplish this feat. So in this tutorial, we'll take a look at how to go about that.

I tried to figure this out myself, but then I decided to make sure that someone else hadn't already done it. After a brief Google search, I found a forum thread where Robin Dunn described how to do it. Here's the basic gist:

import wx

eventDict = {}
for name in dir(wx):
    if name.startswith('EVT_'):
        evt = getattr(wx, name)
        if isinstance(evt, wx.PyEventBinder):
            eventDict[evt.typeId] = name

That only gets the general events though. There are special events in some of the sub-libraries in wx, such as in wx.grid. You will have to account for that sort of thing. I haven't come up with a general solution yet. But in the following runnable example, I show how to add those events too. Let's take a look!

import wx
import wx.grid

########################################################################
class MyForm(wx.Frame):
 
    #----------------------------------------------------------------------
    def __init__(self):
        wx.Frame.__init__(self, None, title="Tutorial")
        
        self.eventDict = {}
        evt_names = [x for x in dir(wx) if x.startswith("EVT_")]
        for name in evt_names:
            evt = getattr(wx, name)
            if isinstance(evt, wx.PyEventBinder):
                self.eventDict[evt.typeId] = name
            
        grid_evt_names = [x for x in dir(wx.grid) if x.startswith("EVT_")]
        for name in grid_evt_names:
            evt = getattr(wx.grid, name)
            if isinstance(evt, wx.PyEventBinder):
                self.eventDict[evt.typeId] = name
 
        # Add a panel so it looks the correct on all platforms
        panel = wx.Panel(self, wx.ID_ANY)
        btn = wx.Button(panel, wx.ID_ANY, "Get POS")

        btn.Bind(wx.EVT_BUTTON, self.onEvent)
        panel.Bind(wx.EVT_LEFT_DCLICK, self.onEvent)
        panel.Bind(wx.EVT_RIGHT_DOWN, self.onEvent)

    #---------------------------------------------------------------------- 
    def onEvent(self, event):
        """
        Print out what event was fired
        """
        evt_id = event.GetEventType()
        print self.eventDict[evt_id]
       
#----------------------------------------------------------------------
# Run the program
if __name__ == "__main__":
    app = wx.App(False)
    frame = MyForm().Show()
    app.MainLoop()

As you can see, we changed the loop slightly. We took the loop in the first example and combined it with the first IF statement to create a list comprehension. This returns a list of event name strings. Then we loop over that using the other conditionals to add to the dictionary. We do it twice, once for the regular events and then again for the wx.grid events. Then we bind a few events to test our event dictionary. If you run this program, you will see that if you execute any of the bound events, it will print those event names to stdout. On most systems, that will be to a console window or a debugging window.

Wrapping Up

Now you know how to get the event name of the event instead of just the integer. This can be helpful when debugging as sometimes you want to bind multiple events to one handler and you need to check and see which event was fired. Happy coding!

Source

Copyright © 2022 Mouse Vs Python | Powered by Pythonlibrary