1

I am using:

wxPython 4.0.7.post2

Pypubsub 4.0.3

Python 3.8.1

I have the following example program I have written:

import wx
import time
from threading import Thread
from pubsub import pub

TIME_UPDATED = "time.updated"


class MyFrame(wx.Frame):

    def __init__(self):
        super().__init__(parent=None, title="Example")
        self.text = wx.StaticText(self, label="I will display seconds elapsed!")
        self.othertext = wx.StaticText(self, label="I will Update")

        sizer = wx.BoxSizer(orient=wx.VERTICAL)
        sizer.Add(self.text)
        sizer.Add(self.othertext)
        self.SetSizer(sizer)

        self.timer = wx.Timer(self)
        pub.subscribe(self.UpdateTime, TIME_UPDATED)
        self.Bind(wx.EVT_TIMER, self.OnTime, self.timer)
        self.Show()

        self.i = 0
        self.timer.Start(500)

    def OnTime(self, _):
        self.i += 1
        self.othertext.SetLabel(str(self.i))

    def UpdateTime(self, seconds):
        self.text.SetLabel("{seconds} seconds have elapsed".format(seconds=seconds))
        self.text.Refresh()


class BackgroundThread(Thread):

    def run(self):
        time_elapsed = 0
        while True:
            # Lets sleep 1 second
            time.sleep(1)
            time_elapsed += 1
            # <<<<---- This line is what I am worried about.
            pub.sendMessage(TIME_UPDATED, seconds=time_elapsed)


if __name__ == '__main__':

    app = wx.App()
    frame = MyFrame()

    background = BackgroundThread(daemon=True)
    background.start()

    app.MainLoop()

I am performing a pub.sendMessage(TIME_UPDATED, seconds=time_elapsed) without a wx.CallAfter and it seems to be working fine. I am not sure why.

Could someone please explain if wx.CallAfter is necessary anymore?

If it is can you explain why that is? Is it that some wx methods put something onto the dispatch queue whereas others do not?

Har
  • 3,727
  • 10
  • 41
  • 75

1 Answers1

1

Yes, you should still ensure that UI operations occur on the UI thread. Just because something is not safe to do does not mean that it doesn't happen to work okay (or apprear to work okay) in some cases.

RobinDunn
  • 6,116
  • 1
  • 15
  • 14
  • Okay, so the behavior in wxPython 4.0 has not changed. Thanks Robin. – Har Apr 23 '20 at 12:38
  • I have a program that use this mechanism with wxPython 4.1.1 to update a progress bar on the main UI form, I put the worker in its own thread similar to the approach here, then upon click on a button on the main form, it will call the worker thread's `start()` method to run it. I suppose this means it is in a separate thread than the main UI thread. I've tried to wrap the `pub.sendMessage` call in `wx.CallAfter`, but keep getting error message complaining about the argument listing format. Could you give an example how to correctly wrap `pub.sendMessage` call? – For Comment Jul 20 '22 at 01:04