067. How to display progress bar while processing long task - Part 1?

Problem

You would like to display a progress bar while processing a long task as shown below:

How to display progress bar while processing long task - Part 1?


Solution


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

  1. Wrap this in a class to avoid any global variables.
  2. The "long task" here is just to loop $i from 1 to 30,000.
  3. 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.
  4. Update the percent value.
  5. Update the displayed text.
  6. 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.

Related Links

Add comment


Security code
Refresh