Reputation: 1393
In my project, I am using wxPython and have a number of custom events that have to be caught, usually when a variable changes. So, here's how I have it set up:
- Event happens (inside a function), it sends a louie signal
- Event Handler catches all event louie signals and performs a func call
- Function call posts the event
- Binding from widget catches it
- Widget sends it to a function in the Event Handler for handling
That seems like an awful lot of runaround. Shouldn't there be a way to simply catch a variable change in a binding and send it to a function? My senses are telling me I'm going about this all wrong. Is there an easier way?
EDIT 1: Here is the minimal, runnable code for my setup, the louie dispatches are because of the threading:
import time
import threading
import wx
from wx.lib.newevent import NewEvent
from louie import dispatcher
customEvent, EVT_CUSTOM_TEST = NewEvent()
def eventFire(changeTo):
global customEvent
changerContainer = customEvent(changeTo=changeTo)
wx.PostEvent(text, changerContainer)
def change(event):
text.SetLabel(event.changeTo)
class customThread(threading.Thread):
def __init__(self, group=None, target=None, name=None, verbose=None, **kwargs):
super(customThread, self).__init__(group=group, target=target, name=name, verbose=verbose)
self.daemon = True
def run(self):
for i in range(10):
if i == 5:
dispatcher.send("CHANGE ME", changeTo="Changed Text")
time.sleep(1)
dispatcher.connect(eventFire, "CHANGE ME")
app = wx.App()
frame = wx.Frame(None, wx.ID_ANY, title="test", size=(100,100))
panel = wx.Panel(frame)
text = wx.StaticText(panel, wx.ID_ANY, "Tester")
frame.Center()
frame.Show()
text.Bind(EVT_CUSTOM_TEST, change)
newThread = customThread()
newThread.start()
app.MainLoop()
EDIT 2: Using wxPython 2.8.12.1 and Ubuntu 14.04
Upvotes: 0
Views: 1478
Reputation: 33111
You can use threads in wxPython and just call a thread-safe method instead of using dispatcher. A thread-safe method is wx.PostEvent
or wx.CallAfter
. I like using pubsub to pass the data around. So instead of
dispatcher.send("CHANGE ME", changeTo="Changed Text")
I would just do something like
wx.CallAfter(Publisher().sendMessage, "msg_name", "Changed Text")
Then the method that pubsub is connected to will fire. So you can make a common method
def change(text):
text.SetLabel(text)
And call that via pubsub. Here are some links:
Note that that article uses wxPython 2.8 and the pubsub API changed in 2.9+. So you might want to look at this too:
Upvotes: 2