On 4/29/05, Craig Moran <craig.m.moran.ruby at gmail.com> wrote:
> 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. ;)
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.