360. How to prevent concurrent button clicks - Part 1 - using block?

Problem

This is in response to Benjamin Smith's post titled Preventing concurrent processing.

Suppose you have set up two buttons as shown below.

In this article, I will show you the first method in preventing concurrent clicks on the buttons. You will find that if you click on the first button1, until button1 finishes its processing, clicking on button1 or button2 will not have any effect.

How to prevent concurrent button clicks - Part 1 - using block?


Solution

Note: Would strongly encourage you to take a look at the article How to process concurrent button clicks? if you haven't. You will understand more about the problem and the solutions.


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   
44   
45   
46   
47   
48   
49   
50   
52   
53   
54   
55   
56   
57   
58   
59   
60   
61   
62   
63   
64   
65   
66   
68   
69   
70   
71   
72   
73   
74   
75   
76   
77   
78   
79   
80   
81   
82   
83   
84   
85   
<?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("Prevent concurrent button clicks\n".
"        Part 1 - using block()");
$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);

$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);
$handler[1] = $button1->connect('clicked', 'on_button', 1,
    $progress1, $status11, $status12);
$num_clicks[1] = 0;

$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);
$handler[2] = $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 $handler, $button1, $button2;
    $button1->block($handler[1]); // note 1
    $button2->block($handler[2]); // note 1

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

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);
    $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]}");
        while (Gtk::events_pending()) {Gtk::main_iteration();}

        global $handler, $button1, $button2;
        $button1->unblock($handler[1]); // note 2
        $button2->unblock($handler[2]); // note 2

        return false;
    }
}

?>

Output

As shown above.
 

Add comment


Security code
Refresh