Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5839015
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T11:31:48+00:00 2026-05-22T11:31:48+00:00

I seem to have nothing but trouble with wxPython and cross-platform compatibility :( I

  • 0

I seem to have nothing but trouble with wxPython and cross-platform compatibility 🙁

I have the function below. It’s called when the user clicks a button, it does some work which may take a while, during which a progress gauge is shown in the status bar.

def Go(self, event):       
    progress = 0
    self.statbar.setprogress(progress)
    self.Update()

    # ...

    for i in range(1, numwords + 1):
        progress = int(((float(i) / float(numwords)) * 100) - 1)
        self.wrdlst.Append(words.next())
        self.statbar.setprogress(progress)
        self.Update()

    self.wrdlst.Refresh() 

    # ...

    progress = 100
    self.PushStatusText(app.l10n['msc_genwords'] % numwords)        
    self.statbar.setprogress(progress)

The calls to self.Update() are apparently needed under Linux, otherwise the gauge doesn’t update until the function exits which makes it kinda pointless. These calls seem to have no effect under Windows (Win 7 at least).

The whole thing works perfectly under Linux (with the calls to Update()), but on Windows 7 the gauge seems to stop around the 20-25% mark, a while before the function exits. So it moves as it should until it reaches ~25%, then the gauge stops moving for no apparent reason but the function continues on just fine and exits with the proper output.

In my attempt to find out the problem, I tried inserting a print progress line just before updating the gauge inside the loop, thinking maybe the value of progress wasn’t what I thought it should be. To my big surprise, the gauge now worked as it should, but the moment I remove that print it stops working. I can also replace the print with a call to time.sleep(0.001), but even with such a short sleep the process still grinds to almost a halt, and if I lower it even further the problem returns, so it’s hardly very helpful.

I can’t figure out what is going on or how to fix it, but I guess somehow things move too fast under Windows so that progress doesn’t get updated properly after a while and just stays at a fixed value (~25). I have no idea why that would be, however, it makes no sense to me. And of course, neither print nor sleep are good solutions. Even if I print out “nothing”, Windows still opens another window for the non-existent output, which is annoying.

Let me know if you need further info or code.

Edit: Ok, here’s a working application which (for me at least) has the problem. It’s still pretty long, but I tried to cut out everything not related to the problem at hand.

It works on Linux, just like the complete app. Under Windows it either fails or works depending on the value of numwords in the Go function. If I increase its value to 1000000 (1 million) the problem goes away. I suspect this may depend on the system, so if it works for you try to tweak the value of numwords. It may also be because I changed it so it Append()s a static text rather than calling a generator as it does in the original code.

Still, with the current value of numwords (100000) it does fail on Windows for me.

import wx

class Wordlist(wx.TextCtrl):    
    def __init__(self, parent):
        super(Wordlist, self).__init__(parent,
                                       style=wx.TE_MULTILINE|wx.TE_READONLY)
        self.words = []
        self.SetValue("")

    def Get(self):
        return '\r\n'.join(self.words)

    def Refresh(self):
        self.SetValue(self.Get())

    def Append(self, value):
        if isinstance(value, list):
            value = '\r\n'.join(value)        
        self.words.append(unicode(value))

class ProgressStatusBar(wx.StatusBar):
    def __init__(self, *args, **kwargs):
        super(ProgressStatusBar, self).__init__(*args, **kwargs)

        self._changed = False

        self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL)
        self.prog.Hide()

        self.SetFieldsCount(2)
        self.SetStatusWidths([-1, 150])

        self.Bind(wx.EVT_IDLE, lambda evt: self.__reposition())
        self.Bind(wx.EVT_SIZE, self.onsize)

    def __reposition(self): 
        if self._changed:
            lfield = self.GetFieldsCount() - 1
            rect = self.GetFieldRect(lfield)
            prog_pos = (rect.x + 2, rect.y + 2)
            self.prog.SetPosition(prog_pos)
            prog_size = (rect.width - 8, rect.height - 4)
            self.prog.SetSize(prog_size)
        self._changed = False

    def onsize(self, evt):
        self._changed = True
        self.__reposition()
        evt.Skip()

    def setprogress(self, val):
        if not self.prog.IsShown():
            self.showprogress(True)

        if val == self.prog.GetRange():
            self.prog.SetValue(0)
            self.showprogress(False)
        else:
            self.prog.SetValue(val)

    def showprogress(self, show=True):
        self.__reposition()
        self.prog.Show(show)

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(*args, **kwargs)

        self.SetupControls()

        self.statbar = ProgressStatusBar(self)
        self.SetStatusBar(self.statbar)

        self.panel.Fit()
        self.SetInitialSize()
        self.SetupBindings()

    def SetupControls(self):
        self.panel = wx.Panel(self)

        self.gobtn = wx.Button(self.panel, label="Go")                               
        self.wrdlst = Wordlist(self.panel)

        wrap = wx.BoxSizer()
        wrap.Add(self.gobtn, 0, wx.EXPAND|wx.ALL, 10)
        wrap.Add(self.wrdlst, 0, wx.EXPAND|wx.ALL, 10)
        self.panel.SetSizer(wrap)

    def SetupBindings(self):
        self.Bind(wx.EVT_BUTTON, self.Go, self.gobtn)

    def Go(self, event):       
        progress = 0
        self.statbar.setprogress(progress)
        self.Update()

        numwords = 100000

        for i in range(1, numwords + 1):
            progress = int(((float(i) / float(numwords)) * 100) - 1)
            self.wrdlst.Append("test " + str(i))
            self.statbar.setprogress(progress)
            self.Update()

        self.wrdlst.Refresh()

        progress = 100
        self.statbar.setprogress(progress)

class App(wx.App):
    def __init__(self, *args, **kwargs):
        super(App, self).__init__(*args, **kwargs)
        framestyle = wx.MINIMIZE_BOX|wx.CLOSE_BOX|wx.CAPTION|wx.SYSTEM_MENU|\
                     wx.CLIP_CHILDREN
        self.frame = MainFrame(None, title="test", style=framestyle)
        self.SetTopWindow(self.frame)
        self.frame.Center()
        self.frame.Show()

if __name__ == "__main__":
    app = App()
    app.MainLoop()

Edit 2: Below is an even simpler version of the code. I don’t think I can make it much smaller. It still has the problem for me. I can run it from within IDLE, or directly by double clicking the .py file in Windows, either way works the same.

I tried with various values of numwords. It seems the problem doesn’t actually go away as I first said, instead when I increase numwords the gauge just reaches further and further before the print is called. At the current value of 1.000.000 this shorter version reaches around 50%. In the longer version above, a value of 1.000.000 reaches around 90%, a value of 100.000 reaches around 25%, and a value of 10.000 only reaches around 10%.

In the version below, once the print is called, the progress continues on and reaches 99% even though the loop must have ended by then. In the original version the call to self.wrdlst.Refresh(), which takes a few seconds when numwords is high, must have caused the gauge to pause. So I think that what happens is this: In the loop the gauge only reaches a certain point, when the loop exits the function continues on while the gauge stays still, and when the function exits the gauge continues on until it reaches 99%. Because a print statement doesn’t take a lot of time, the version below makes it seem like the gauge moves smoothly from 0% to 99%, but the print suggests otherwise.

import wx

class MainFrame(wx.Frame):
    def __init__(self, *args, **kwargs):
        super(MainFrame, self).__init__(*args, **kwargs)        
        self.panel = wx.Panel(self)        
        self.gobtn = wx.Button(self.panel, label="Go")
        self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL)
        wrap = wx.BoxSizer()
        wrap.Add(self.gobtn, 0, wx.EXPAND|wx.ALL, 10)
        wrap.Add(self.prog, 0, wx.EXPAND|wx.ALL, 10)
        self.panel.SetSizer(wrap)
        self.panel.Fit()
        self.SetInitialSize()        
        self.Bind(wx.EVT_BUTTON, self.Go, self.gobtn)

    def Go(self, event):        
        numwords = 1000000
        self.prog.SetValue(0)
        for i in range(1, numwords + 1):
            progress = int(((float(i) / float(numwords)) * 100) - 1)
            self.prog.SetValue(progress)
        print "Done"

if __name__ == "__main__":
    app = wx.App()
    frame = MainFrame(None)
    frame.Show()
    app.MainLoop()
  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T11:31:48+00:00Added an answer on May 22, 2026 at 11:31 am

    So, actually, you are blocking the GUI thread by your long running task. It may and may not run fine on some platforms and/or computers.

    import wx
    from wx.lib.delayedresult import startWorker
    
    class MainFrame(wx.Frame):
        def __init__(self, *args, **kwargs):
            super(MainFrame, self).__init__(*args, **kwargs)        
            self.panel = wx.Panel(self)        
            self.gobtn = wx.Button(self.panel, label="Go")
            self.prog = wx.Gauge(self, style=wx.GA_HORIZONTAL)
            self.timer = wx.Timer(self)
    
            wrap = wx.BoxSizer()
            wrap.Add(self.gobtn, 0, wx.EXPAND|wx.ALL, 10)
            wrap.Add(self.prog, 0, wx.EXPAND|wx.ALL, 10)
            self.panel.SetSizer(wrap)
            self.panel.Fit()
            self.SetInitialSize()        
    
            self.Bind(wx.EVT_BUTTON, self.Go, self.gobtn)
            self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
    
    
        def Go(self, event):
            # Start actual work in another thread and start timer which 
            # will periodically check the progress and draw it
            startWorker(self.GoDone, self.GoCompute)
            self.progress = 0
            self.timer.Start(100)
    
        def OnTimer(self, event):
            # Timer draws the progress
            self.prog.SetValue(self.progress)
    
        def GoCompute(self):
            # This method will run in another thread not blocking the GUI
            numwords = 10000000
            self.prog.SetValue(0)
            for i in range(1, numwords + 1):
                self.progress = int(((float(i) / float(numwords)) * 100) - 1)
    
        def GoDone(self, result):
            # This is called when GoCompute finishes
            self.prog.SetValue(100)
            self.timer.Stop()
            print "Done"
    
    if __name__ == "__main__":
        app = wx.App()
        frame = MainFrame(None)
        frame.Show()
        app.MainLoop()
    

    Also notice that contrary your example:

    • Button goes back to unclicked state after clicked
    • You can move the window and it will not freeze

    As a rule of thumb, every method which looks like this def Something(self, event) should run just a few milliseconds.

    EDIT: Another thing what I have observed on Windows 7. The gauge starts to grow at the time you call self.prog.SetValue() and grows in some time to specified value. It does not “jump” to that value, rather it grows slowly to hit set value. It seems to be Windows 7 feature. I had to switch off “Animate controls and element inside windows” in performance options to get rid of this behavior.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I have a small ncurse program I'm running, but the output doesn't seem to
I've been having nothing but trouble with python2.6 and Snow Leopard. One major problem
I have create a module which at this point does nothing but exist the
I seem to have a problem with this SQL query: SELECT * FROM appts
I seem to have an app on my Dev server that has lots of
I seem to have a problem with getting MVC to fill in my custom
I seem to have the exact opposite problem than this question on stopping dock
I seem to have a problem understanding how to conditionally test a boolean value
I seem to have missed something - in this step through it talks through
I seem to have an issue with connecting to an embedded FireBird database from

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.