Doug
Doug

Reputation: 615

wxPython - How to force UI refresh?

I've boiled my problem down to the example code shown in this post. Note that I'm not calling app.MainLoop() because this isn't an interactive window; I want it to pop up at the beginning, show some progress bars while work happens, and disappear when complete.

My (limited) understanding of wxPython and wx.Yield() led me to believe that calling wx.Yield() after some UI work would flush those changes to the display. That is not occurring -- when I run this script, there is a gray box where "Hello World" should be.

What am I doing wrong?

import wx

class MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, size=(400,400))
        self.panel = wx.Panel(self, -1)
        wx.StaticText(self.panel, -1, "Hello World", (20,20))
        wx.Yield()


class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, -1)
        self.frame.Show(True)
        self.SetTopWindow(self.frame)
        return True


def run():
    app = MyApp(redirect=False)
    import time; time.sleep(5)

run()

Upvotes: 1

Views: 9644

Answers (4)

Rolf of Saxony
Rolf of Saxony

Reputation: 22433

Not that it will do the original poster any good after all this time but wx.Yield() would have done the job. It just needs to be in the right place as does the self.Show()
The following outputs a progress bar which gets updated.

import wx
import time
class MyFrame(wx.Frame):
    def __init__(self, parent, id):
        wx.Frame.__init__(self, parent, id, size=(290,200))
        self.panel = wx.Panel(self, -1)
        wx.StaticText(self.panel, -1, "Hello World", (20,20))
        self.gauge = wx.Gauge(self.panel, -1, 50, pos=(20,50), size=(250, 20))
        self.Show()
        n = 0
        while n < 50:
            n = n+1
            self.gauge.SetValue(n)
            wx.Yield()
            time.sleep(1)

class MyApp(wx.App):
    def OnInit(self):
        self.frame = MyFrame(None, -1)
        self.SetTopWindow(self.frame)
        return True

def run():
    app = MyApp()

run()

Upvotes: 0

Gerald Spreer
Gerald Spreer

Reputation: 413

Without the MainLoop no events will be fired and also .Refresh will not work.

I guess wxSplashscreen may be what you are looking for. Example: http://wiki.wxpython.org/SplashScreen

Upvotes: 0

Kylotan
Kylotan

Reputation: 18449

You need to be yielding or updating on a regular basis, so that when your OS/window manager sends repaint messages to your app, it can handle them. I am not 100% sure about wxPython as I haven't used it recently but I don't think you can do what you want without the main loop to handle the messages appropriately.

You might find something useful here about threading the main loop, however (as well as explanation of why the main loop is important): http://wiki.wxpython.org/MainLoopAsThread

Upvotes: 3

Joran Beasley
Joran Beasley

Reputation: 113930

instead of wx.Yield()

just call self.Update()

Upvotes: 0

Related Questions