Discussion:
[Foxgui-users] Question on progress bars and execute
Julia Dudascik (Contractor)
2016-08-04 18:27:47 UTC
Permalink
I have recently created a FXProgressDialog to show the status of opening a
large file. If use the execute() command, the dialog with the progress bar
appears, but the code following it to open the file does not execute. If I
run fxtrace I can see that FOX events are still being processed, but my
code is stuck until execute returns.

What I had to do instead, is call create() then show() for my
FXProgressDialog. Then, in order to ensure FXProgressDialog displays before
the code starts to open the file, I have to call refresh() and afterwards
runWhileEvents(). This successfully displays the FXProgressDialog. As the
file opens I call refresh() and runWhileEvents() so that it shows the
status of the open.

I have several questions:

1.) Is there a way to use the execute() function so that it continues to
process my code and re-paint the progress bar while it is in this
runModalFor loop?

2.) Is what I am doing the best way to go about this? I don't want to run
into an issue where runWhileEvents takes a long time, causing my file open
time to take twice as long.

3.) If I use the function runUntil(condition), how do I set the condition
to a non-zero value so that it will then continue processing my code?

Thank you
Julia
JVZ
2016-08-04 19:26:01 UTC
Permalink
On Thu, 4 Aug 2016 14:27:47 -0400
Post by Julia Dudascik (Contractor)
I have recently created a FXProgressDialog to show the status of opening a
large file. If use the execute() command, the dialog with the progress bar
appears, but the code following it to open the file does not execute. If I
run fxtrace I can see that FOX events are still being processed, but my
code is stuck until execute returns.
What I had to do instead, is call create() then show() for my
FXProgressDialog. Then, in order to ensure FXProgressDialog displays before
the code starts to open the file, I have to call refresh() and afterwards
runWhileEvents(). This successfully displays the FXProgressDialog. As the
file opens I call refresh() and runWhileEvents() so that it shows the
status of the open.
1.) Is there a way to use the execute() function so that it continues to
process my code and re-paint the progress bar while it is in this
runModalFor loop?
2.) Is what I am doing the best way to go about this? I don't want to run
into an issue where runWhileEvents takes a long time, causing my file open
time to take twice as long.
3.) If I use the function runUntil(condition), how do I set the condition
to a non-zero value so that it will then continue processing my code?
Thank you
Julia
The execute() in FXDialogBox is really a shorthand convenience for the
following couple of calls:

create();
show();
getApp()->refresh();
getApp()->runModalFor(this);

The first three create the windows, and show them. The refresh() call ensures
that things are updated (GUI-update).

The last thing of course runs the modal loop while the dialog is being interacted
with.

This is of course not appropriate for the progress box, as the progress box should
remain up while the file-load is ongoing.

To show progress during the file load, it is necessary to periodically change the
current progress value, and dip into the event loop for a short time (for example,
to allow possibly obscured windows to repaint, and to allow a user to click the
cancel button maybe).

The best way, I think, is to call runOneEvent() repeatedly, until the event stream
has been exhausted and all repaints, mouse clicks, keystrokes, etc. have been processed.

Your FOX program communicates with another program (the X11 server), and there are queues
between the two; you would want to ensure that all the queues are indeed processed.

You can control the outgoing queue (draw commands) by calling flush(). The incoming
queue is not so easily controlled; the best way is to set a short timer and break
out of the event loop after a small interval has elapsed; for example, process
events for 300ms and then break out of the loop by letting the timer-handler
set a flag to exit the loop:


FXuint flag=0;

app->addTimeout(this,ID_EXITLOOP,300,&flag);

app->runUntil(flag);


and the handler:

long MyWindow::onExitLoop(FXObject*,FXSelector,void* ptr){
*((FXuint*)ptr)=1;
return 1;
}

This mechanism will run the event loop for just .3 second (should
probably be sufficient unless its a really large program).

You may want to experiment; the key idea is to process events to
keep the GUI responsive, by periodically dipping into the event
loop to process events backlogged while the program was working.

Hope this gives you some good ideas....


-- JVZ



+----------------------------------------------------------------------------+
| Copyright (C) 13:40 08/ 4/2016 Jeroen van der Zijp. All Rights Reserved. |
+----------------------------------------------------------------------------+

------------------------------------------------------------------------------
Loading...