Why doesn't the gauge bar show up when the button is pressed?

Hi,

I have a gauge bar on a panel. And a start button. The Gauge bar is hidden. What I want is: when the “start” button is pressed, the gauge should show up, the program should count to 10 and the gauge should display the progress. However, when I press the “start” button, the gauge bar is not displayed. It is displayed only when the counting to 10 is over.

When I comment out self.start_progress(), however, the gauge bar is displayed when I press the “start” button.

What is wrong here?

import wx
import wx.lib.agw.pygauge as PG
import time

class MyFrame(wx.Frame):

    def __init__(self, parent):

        wx.Frame.__init__(self, parent, -1, "Gauge")

        self.panel = wx.Panel(self)

        self.gauge = PG.PyGauge(self.panel, -1, size=(100, 25), style=wx.GA_HORIZONTAL)
        self.gauge.SetBackgroundColour(wx.WHITE)
        self.gauge.SetBorderColor(wx.BLACK)

        self.value = 0
        self.range = 10
        self.gauge.SetRange(self.range)
        self.gauge.SetValue(self.value)

        self.button = wx.Button(self.panel, -1, "Start", size=(55, 24))
        self.Bind(wx.EVT_BUTTON, self.start_it, self.button)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.gauge, 0, wx.ALIGN_CENTER | wx.ALL, 20)
        sizer.Add(self.button, 0, wx.ALIGN_CENTER | wx.ALL, 20)
        self.gauge.Hide()

        self.panel.SetSizer(sizer)
        sizer.Layout()

    def start_it(self, evt):
        self.show_gauge()
        self.start_progress()

    def show_gauge(self):
        self.gauge.Show()
        self.panel.Layout()

    def start_progress(self):
        for i in range(10):
            self.updateProgress()
            time.sleep(1)

    def updateProgress(self):
        self.value += 1
        if self.value <= self.range:
            self.gauge.SetValue(self.value)
            self.gauge.Refresh()
            self.Refresh()
        else:
            pass


app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()

Hi Steve,

Your code is either generating events or sleeping. It doesn’t give the MainLoop any opportunity to process the events until after the for-loop has terminated.

Below is a possible solution for this simple case.

import wx
import wx.lib.agw.pygauge as PG
import time

class MyFrame(wx.Frame):

    def __init__(self, parent):

        wx.Frame.__init__(self, parent, -1, "Gauge")

        self.panel = wx.Panel(self)

        self.gauge = PG.PyGauge(self.panel, -1, size=(100, 25), style=wx.GA_HORIZONTAL)
        self.gauge.SetBackgroundColour(wx.WHITE)
        self.gauge.SetBorderColor(wx.BLACK)

        self.value = 0
        self.range = 10
        self.gauge.SetRange(self.range)
        self.gauge.SetValue(self.value)

        self.button = wx.Button(self.panel, -1, "Start", size=(55, 24))
        self.Bind(wx.EVT_BUTTON, self.start_it, self.button)

        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer.Add(self.gauge, 0, wx.ALIGN_CENTER | wx.ALL, 20)
        sizer.Add(self.button, 0, wx.ALIGN_CENTER | wx.ALL, 20)
        self.gauge.Hide()

        self.panel.SetSizer(sizer)
        sizer.Layout()

    def start_it(self, evt):
        self.show_gauge()
        wx.CallAfter(self.start_progress)

    def show_gauge(self):
        self.gauge.Show()
        self.panel.Layout()

    def start_progress(self):
        for i in range(10):
            self.updateProgress()
            wx.Yield()
            time.sleep(1)

    def updateProgress(self):
        self.value += 1
        if self.value <= self.range:
            self.gauge.SetValue(self.value)
            self.gauge.Refresh()
            self.Refresh()
        else:
            pass


app = wx.App(0)
frame = MyFrame(None)
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()

Tested using Python 3.10.12 + wxPython 4.2.1 gtk3 (phoenix) wxWidgets 3.2.2.1 on Linux Mint 21.2

2 Likes

Just as an aside, you could use self.Update() rather than wx.Yield() in this case.
Although, then you wouldn’t be able to add a Stop button, because it wouldn’t be yielding to wx.App for the Stop event.

1 Like

wx.Yield() should be replaced with wx.GetApp().Yield()

1 Like