Problem
You would like to display a progress bar while processing a long task as shown below:
Solution
- Just before the long task is started, display a dialog that contains a GtkProgressBar.
- Break down the long task into smaller pieces. In between the pieces, set the current percentage value with GtkProgressbar::set_fraction(), and the displayed text with GtkProgressbar::set_text()
- We make use of main_iteration to update the progress bar in between the pieces.
- When the task is completed, destroy the dialog.
Sample Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 29 30 31 32 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 50 51 52 53 54 55 56 57 58 61 62 63 64 | <?php $window = new GtkWindow(); $window->set_size_request(400, 120); $window->connect_simple('destroy', array('Gtk','main_quit')); $window->add($vbox = new GtkVBox()); // display title $title = new GtkLabel("Display progress bar while processing long task"); $title->modify_font(new PangoFontDescription("Times New Roman Italic 10")); $title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff")); $title->set_size_request(-1, 40); $vbox->pack_start($title, 0, 0); $vbox->pack_start(new GtkLabel(), 0, 0); // add a small gap $vbox->pack_start($hbox = new GtkHBox(), 0, 0); $hbox->pack_start($button = new GtkButton('Start processing'), 1, 0); $button->connect('clicked', 'start_processing'); $window->show_all(); Gtk::main(); function start_processing($button, $entry) { $show_progress_dialog = new ShowProgress(); // note 1 $max = 30000; // note 2 for ($i=0; $i<$max; ++$i) { echo "$i "; if ($i%1000==0) { // note 3 $percent_complete = number_format($i/$max*100, 0); $show_progress_dialog->progress_bar->set_fraction($i/$max); // note 4 $show_progress_dialog->progress_bar->set_text( $percent_complete.'% Complete'); // note 5 while (Gtk::events_pending()) {Gtk::main_iteration();} // note 6 } } $show_progress_dialog->dialog->destroy(); // done. close the dialog box. } class ShowProgress { // note 1 var $progress_bar; var $dialog; function ShowProgress() { $dialog = new GtkDialog('Work in progress...', null, Gtk::DIALOG_MODAL); // create a new dialog $top_area = $dialog->vbox; $top_area->pack_start(new GtkLabel( 'Please hold on while processing data...')); $this->progress_bar = new GtkProgressBar(); $this->progress_bar->set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT); $top_area->pack_start($this->progress_bar, 0, 0); $dialog->set_has_separator(false); $dialog->show_all(); // show the dialog $this->dialog = $dialog; // keep a copy of the dialog ID } } ?> |
Output
As shown above.Explanation
- Wrap this in a class to avoid any global variables.
- The "long task" here is just to loop
$i
from 1 to 30,000. - As mentioned above, your long task has to be able to be divided into smaller pieces. Here we have a "break" for each 1000. We update the progress bar in between these breaks.
- Update the percent value.
- Update the displayed text.
- Try commenting this line and see what happens. Without this, you will find that the progress bar will not be updated until your task completes. By using main_iteration, we let gtk updates the progress bar during the "break" time.
Note
It is important that the long task can be broken down into smaller pieces.
For example, if you issue a mysql statement that takes 10 minutes to retrieve the entire set of data, you will find that the progress bar will not show anything during this 10 minutes.
Instead of this, you might want to fetch your data sets across 20 or more batches so that you can display the progress status in between the batches.
Read more...