Returning control from a wxDialog...

I have a quick question about using a wxDialog. I have a small class
that uses a wxDialog. In it I have a sizer with a label and a wxGauge.
I have one process that populates a list and if the data is big enough,
it takes 10 or 15 seconds. I thought it would be cool to add a little
progress bar showing that something is happening, and when it would be
finished. My process is nice and incrimental, so updating the position
of the gauge would work nicely.

The problem is, I can't figure out how to update the gauge from my base
app. The idea is...base app starts process...pops up wxDialog with
gauge in it...then base app periodically updates the gauge value. Right
now, once the dialog opens, it keeps control. Anyway to release it?

Thanks, Matt

I did something similar just today, but I was able to spawn the work in
the dialog. In this particular case, the processing was also simple and
I was able to successfully use yield. Something along these lines
(distilled and untested):

    def ShowModal(self):
        wx.CallAfter(self.doTasks)
        return wx.Dialog.ShowModal(self)

    def doTasks(self):
        print 'doTasks'
        self.isWorking = True
        wx.GetApp().Yield(True)
          # ^ trying to get rid of display lag weirdness. seems to work.
        try:
            try:
                for i in range(self.numTasks):
                    self.doTask(i)
                    wx.GetApp().Yield(True)
            except StopError:
                return
        finally:
            self.isWorking = False

class StopError(Exception): pass

doTask() updates various controls like a list box and a static text. And
it can raise StopError if the processing should stop for some reason
(say due to an error).

You could have the dialog talk back to the main app:

  dialog = MyDialog(foo, bar)
  dialog.doTask = self.doTask

Now when doTasks() says "self.doTask()" it will be calling someone elses
code. I've been using these kinds of callbacks frequently lately;
they're simple and they work seemlessly. Basically, you can subclass
and override the method, or simply make an attribute that points to
something callable.

HTH!

···

On Friday 18 April 2003 03:26 pm, Matt G wrote:

I have a quick question about using a wxDialog. I have a small class
that uses a wxDialog. In it I have a sizer with a label and a
wxGauge. I have one process that populates a list and if the data is
big enough, it takes 10 or 15 seconds. I thought it would be cool to
add a little progress bar showing that something is happening, and
when it would be finished. My process is nice and incrimental, so
updating the position of the gauge would work nicely.

The problem is, I can't figure out how to update the gauge from my
base app. The idea is...base app starts process...pops up wxDialog
with gauge in it...then base app periodically updates the gauge
value. Right now, once the dialog opens, it keeps control. Anyway
to release it?

Thanks, Matt

--
Chuck
http://ChuckEsterbrook.com

Matt G wrote:

The problem is, I can't figure out how to update the gauge from my base
app. The idea is...base app starts process...pops up wxDialog with
gauge in it...then base app periodically updates the gauge value. Right
now, once the dialog opens, it keeps control. Anyway to release it?

The dialog only has control if you call its ShowModal() method. You can create the dialog and display it using dlg.Show(1). You can then progressively Update() the progress bar. There's already a standard wxProgressDialog. I created this class to encapsulate a wxProgressDialog in an even-simpler interface:

class ProgressBar:
    def __init__(self, maximum, title, text):
        self.dlg = wxProgressDialog(title, text, maximum,
                        style=wxPD_APP_MODAL|wxPD_AUTO_HIDE)
        self.count = 0
        self.max = maximum - 1
        self.dlg.Raise()

    def Tick(self, label=''):
        self.count += 1
        self.dlg.Update( self.count, label )
        return self.count < self.max

    def Destroy(self):
        self.dlg.Update( self.max, '' ) # this should hide the dialog
        self.dlg.Destroy()

    def Show(self, flag):
        return self.dlg.Show(flag)

With this class, I can do something like the following:

        dlg = ProgressBar( len(tasklist), "Progress...",
                      "Performing %d tasks..." % len(tasklist) )
        for task in tasklist:
            do_task(task)
            dlg.Tick()
        dlg.Show(0)
        dlg.Destroy()

I've also made it easy to change the text label by passing an optional string to tick(). Note that my call to dlg.Show(0) is probably unnecessary (the dialog should automatically hide itself once its count reaches the maximum count), but it doesn't hurt.

Jeff Shannon
Technician/Programmer
Credit International

Jeff:

Thanks! This worked perfectly for what I needed. I appreciate your
time.

Matt

···

On Fri, 2003-04-18 at 18:04, Jeff Shannon wrote:

Matt G wrote:

>The problem is, I can't figure out how to update the gauge from my base
>app. The idea is...base app starts process...pops up wxDialog with
>gauge in it...then base app periodically updates the gauge value. Right
>now, once the dialog opens, it keeps control. Anyway to release it?
>

The dialog only has control if you call its ShowModal() method. You can
create the dialog and display it using dlg.Show(1). You can then
progressively Update() the progress bar. There's already a standard
wxProgressDialog. I created this class to encapsulate a
wxProgressDialog in an even-simpler interface:

class ProgressBar:
    def __init__(self, maximum, title, text):
        self.dlg = wxProgressDialog(title, text, maximum,
                        style=wxPD_APP_MODAL|wxPD_AUTO_HIDE)
        self.count = 0
        self.max = maximum - 1
        self.dlg.Raise()

    def Tick(self, label=''):
        self.count += 1
        self.dlg.Update( self.count, label )
        return self.count < self.max

    def Destroy(self):
        self.dlg.Update( self.max, '' ) # this should hide the dialog
        self.dlg.Destroy()

    def Show(self, flag):
        return self.dlg.Show(flag)

With this class, I can do something like the following:

        dlg = ProgressBar( len(tasklist), "Progress...",
                      "Performing %d tasks..." % len(tasklist) )
        for task in tasklist:
            do_task(task)
            dlg.Tick()
        dlg.Show(0)
        dlg.Destroy()

I've also made it easy to change the text label by passing an optional
string to tick(). Note that my call to dlg.Show(0) is probably
unnecessary (the dialog should automatically hide itself once its count
reaches the maximum count), but it doesn't hurt.

Jeff Shannon
Technician/Programmer
Credit International

---------------------------------------------------------------------
To unsubscribe, e-mail: wxPython-users-unsubscribe@lists.wxwindows.org
For additional commands, e-mail: wxPython-users-help@lists.wxwindows.org