359. How to process concurrent button clicks?

Solution

  • For each button click, we run the signal handler on_button().
  • Each button click will start a "long" process which is reflected by the progress bar running from 0% to 100%.
  • There are two status line. The first status line shows the total number of clicks, while the second status line shows which click PHP-GTK2 is processing now.
  • Try clicking each button a number of times, and notice the order in which the clicks are being processed.

Sample Code for PHP GTK

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   
45   
46   
47   
49   
50   
51   
63   
64   
65   
66   
67   
68   
69   
70   
71   
72   
73   
74   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
<?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("Processing concurrent button clicks");
$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);
$vbox->pack_start(new GtkLabel(), 0);

$vbox->pack_start($hbox = new GtkHBox(), 0);
$hbox->pack_start($vbox1 = new GtkVBox(), 0);
$hbox->pack_start(new GtkVBox());
$hbox->pack_start($vbox2 = new GtkVBox(), 0);

// set up button 1
$vbox1->pack_start($button1 = new GtkButton('Button 1'), 0);
$vbox1->pack_start($status11 = new GtkLabel(), 0);
$vbox1->pack_start($status12 = new GtkLabel(), 0);
$vbox1->pack_start($progress1 = new GtkProgressBar(), 0);
$progress1->set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT);
$progress1->set_size_request(175, -1);
$button1->connect('clicked', 'on_button', 1, $progress1, $status11, $status12);
$num_clicks[1] = 0;

// set up button 2
$vbox2->pack_start($button2 = new GtkButton('Button 2'), 0);
$vbox2->pack_start($status21 = new GtkLabel(), 0);
$vbox2->pack_start($status22 = new GtkLabel(), 0);
$vbox2->pack_start($progress2 = new GtkProgressBar(), 0);
$progress2->set_orientation(Gtk::PROGRESS_LEFT_TO_RIGHT);
$progress2->set_size_request(175, -1);
$button2->connect('clicked', 'on_button', 2, $progress2, $status21, $status22);
$num_clicks[2] = 0;

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

function on_button($button, $id, $progress, $status1, $status2) {
    global $num_clicks, $progress_count;
    ++$num_clicks[$id]; // note 1
    $progress_count[$id][$num_clicks[$id]] = 0; // note 2
    $status1->set_text("Total number of clicks ($id): {$num_clicks[$id]}");
    Gtk::idle_add('update_progressbar', $progress, $id, $num_clicks[$id],
        $status1, $status2); // note 3
}

function update_progressbar($progress, $id, $num_clicks, $status1, $status2) {
    $max = 1000;
    global $progress_count;
    ++$progress_count[$id][$num_clicks];
    $count = $progress_count[$id][$num_clicks];
    $percent_complete = $count/$max;
    $percent_complete2 = number_format($count/$max*100, 0);
    $progress->set_fraction($percent_complete); // note 4
    $progress->set_text($percent_complete2.'% Complete');
    while (Gtk::events_pending()) {Gtk::main_iteration();}
    $status2->set_text("Now running click #$num_clicks");
    if ($count < $max) { // task completed?
        return true; // not yet!
    } else {
        global $num_clicks;
        --$num_clicks[$id];
        $status1->set_text("Total number of clicks: {$num_clicks[$id]}");
        if ($num_clicks[$id]==0)
            $status2->set_text("All button clicks processed");
        while (Gtk::events_pending()) {Gtk::main_iteration();}
        return false;
    }
}

?>

Output for PHP GTK

As shown above.