PHP-GTK2 Newsletter

PHP-GTK2 Tips & Techniques
FREE Newsletter
by kksou



Sample Code 68: How to display progress bar while processing long task - Part 2 using_idle_add?
Written by kksou   
Saturday, 21 October 2006
Problem

You have displayed a progress bar while processing a long task in Part 1.

However, the problem with that method is that if the user closes the progress bar dialog in the midst of the long task, the dialog disappears, but the process continues in the background. The whole application will appear to "hang" until the long task completes. This is undesirable.

A more "elegant" method to display progress bar while processing a long task is to use the Gtk::idle_add as described below:

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


Solution
  • Just before the long task is started, first set up a dialog that contains a GtkProgressBar.
  • Then begin the task by setting up Gtk::idle_add to call your function (that process the long task) whenever it's idle.
  • Every time php-gtk has nothing to do, it will make a trip to your function. In your function, do whatever subtask you want to do. If there are more tasks to be completed, return a true. If all tasks are completed, return a false.
  • When all tasks is completed, you should also call Gtk::idle_remove to let php-gtk know that you're done. Of course, you may also want to close the progress bar dialog.
  • To trap the event in which the user closes the progress bar dialog, we set up a connect('delete-event').
  • When the user closes the progress bar in the midst of the long task, just like above, we call Gtk::idle_remove then close the progress bar dialog.
  • As explained in Part 1, don't forget to call while (Gtk::events_pending()) {Gtk::main_iteration();} so that the progress bar gets updated.

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   
28   
29   
30   
31   
32   
33   
34   
35   
36   
37   
38   
39   
40   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
52   
53   
54   
55   
56   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
67   
<?php
$window = new GtkWindow();
$window->set_size_request(400, 175);
$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 - Part 2");
$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(new GtkLabel('using Gtk::idle_add()'), 0, 0);
$vbox->pack_start(new GtkLabel('you can also interrupt the long task'), 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);
$vbox->pack_start(new GtkLabel()); // add a small gap
$button->connect('clicked', 'start_processing');

$window->show_all();
Gtk::main();

function start_processing($button) {
    $do_long_task = new DoLongTask(); // note 1
    $do_long_task->idle_ID = Gtk::idle_add(
        array(&$do_long_task, 'process_task')); // note 2
}

class DoLongTask { // note 1

    var $progress_bar;
    var $dialog;
    var $subtask_count = 0;
    var $max_task_count = 10;
    var $idle_ID;

    function DoLongTask() {
        // setup a dialog containing progress bar
        $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

        $dialog->connect('delete-event',
            array( &$this, "on_delete_event")); // note 3
    }

    // this is where you process your task
    function process_task() {
        echo "processing subtask $this->subtask_count: ";
        for ($i=0; $i<10; ++$i) {
            usleep(50000); // sleep for half a second
            print ".";
        }
        print "\n";
  • Note that this is only 70% of the sample code. You have to be a registered member to see the entire sample code. Please login or register.
  • Registration is free and immediate.
  • Have some doubt about the registration? Please read this forum article.
Explanation
  1. Wrap this in a class to avoid any global variables.
  2. Ask php-gtk to process your long task whenever it's free.
  3. Let us know if user closes the progress bar dialog.
  4. Update the percent value.
  5. Update the displayed text.
  6. Don't forget this so that progress bar gets updated.

Related Links

User reviews   Average user ratings:    3.5   (from 6 users)
  1. Manisekaran from India
    March 15, 2007 2:28am

    Nice

  2. Yuval Hofshy
    February 24, 2008 7:28am

  3. shahi
    June 27, 2008 11:15am

  4. Ris
    July 11, 2008 2:25am

  5. eliskcage
    September 02, 2008 10:18am

  6. pawlak
    September 08, 2008 2:29pm

Note: You have to be a registered member to leave a comment. Free registration here.

 
< Prev   Next >

Copyright © 2006-2008. kksou.com. All Rights Reserved