Fox FXProgressBar refresh issue

I am having a refresh issue with the FXProgressBar that I'd like to resolve.
First, I would like to state that I am not an experienced GUI programmer, so
I'd like some guidance. I am working with Fox, trying to implement a
progress bar. I've stripped the code below to what I think is the simplest
base level design. If it may be done simpler, please let me know.

The issue is this. When I run this program and let it complete with no
interaction, it works fine. However, if I start clicking on the title bar,
it will eventually stop refreshing the application GUI. During my tests,
this will generally occur at 9% or shortly thereafter. When I have caused
the GUI to stop refreshing, the program still runs to completion, then
refreshes when the progress bar hits 100%.

Here's what I'd like to know:

   1. Am I implementing this correctly?
   2. Is there a better way to implement this? In the doStuff def, I
   would actually be performing real work.
   3. Am I not making the correct calls to refresh the GUI?

C:\>ruby -v
ruby 1.8.2 (2004-12-25) [i386-mswin32]
This is the 1.8.2-15 One-Click Installer for Windows
I am running it on Windows XP SP1. I have duplicated this behavior on
Windows 2000 with the same One-Click Installer. I don't think this is an
issue with the One-Click Installer. I think that I am doing something wrong.

As an aside, which other cross-platform GUIs have progress bars available? I
have used wxRuby and Tk in the past and my skill level is limited with both.
Thanks in advance for any help that is provided.
Craig

#!/usr/bin/env ruby
require 'fox12'
include Fox

TOTAL = 500000

class ProgressWindow < FXMainWindow
def initialize(app)
super(app, "Progress Bar", nil, nil, DECOR_ALL,
0, 0, 400, 0)
$pbar = FXProgressBar.new(self, nil, 0,
LAYOUT_FILL_X|FRAME_SUNKEN|
FRAME_THICK|PROGRESSBAR_PERCENTAGE)
$pbar.total = TOTAL
end # def initialize

def doStuff
TOTAL.times { |x|
$pbar.setProgress(x)
getApp.repaint
}
end # def doStuff

def create
super
show(PLACEMENT_SCREEN)
doStuff
end # def create
end # class ProgressWindow

def run
application = FXApp.new("Progress", "Test")
ProgressWindow.new(application)
application.create
application.run
end # def run

run

progressBar.rb (727 Bytes)

I am having a refresh issue with the FXProgressBar that I'd like to resolve.
First, I would like to state that I am not an experienced GUI programmer,
so I'd like some guidance. I am working with Fox, trying to implement a
progress bar. I've stripped the code below to what I think is the simplest
base level design. If it may be done simpler, please let me know.

The issue is this. When I run this program and let it complete with no
interaction, it works fine. However, if I start clicking on the title bar,
it will eventually stop refreshing the application GUI. During my tests,
this will generally occur at 9% or shortly thereafter. When I have caused
the GUI to stop refreshing, the program still runs to completion, then
refreshes when the progress bar hits 100%.

Here's what I'd like to know:

Am I implementing this correctly?

No. :wink:

The basic problem is that you're calling doStuff() directly from the
create() method, which means that the program never actually enters
the main event loop until after doStuff() gets completely finished.
That is to say, when you call create() on the application object
(application.create) it indirectly calls your main window's create()
method, and so the program hangs there until you eventually get
through TOTAL iterations of updating the progress bar. Finally, it
exits the main window's create() method, and then the application's
create() method will also exit, and then we finally get around to
calling the application's run() method, which is how the event loop is
initiated.

So, although your program kinda-sorta seems to be working, it's not
structured quite right, and that's why you're seeing this weird
behavior.

Is there a better way to implement this? In the doStuff def, I would
actually be performing real work.

A minimal change to get this working more along the correct lines
would be to perhaps put the call to doStuff() in a worker thread of
some kind. In other words, you could start by changing your create()
method to look like this:

    def create
      super
      show(PLACEMENT_SCREEN)
      Thread.new { doStuff }
    end

This change will allow the create() method to proceed, and so on, but
the "work" that doStuff() is simulating will begin and continue to
progress. Now, as you have noted, in a real application, you'd want to
be doing something more useful in that worker thread, and have some
more meaningful measure of the progress towards that task's completion
-- but that's obviously a pretty application-specific consideration.

Am I not making the correct calls to refresh the GUI?

The call to getApp().repaint() is unnecessary, but it's not really
hurting anything. You can go ahead and remove it.

ยทยทยท

On 4/29/05, Craig Moran <craig.m.moran.ruby@gmail.com> wrote: