The Timer class simplifies the use of delays between user
actions, without freezing the UI.
The standard way to uses delays with php-gtk is
Gtk::timeout_add ; but it is not very compact :
- you have to define a new function that will be called after
X miliseconds,
- it's not a blocking call ; this is a
callback
type code design,
- you could use
sleep() or
usleep(), but in that case, the code does not
reenter the main loop, so Gtk events won't be processed,
meaning the user interface will be frozen
Our goal is to be able to write this :
<?php
# label is a GtkLabel
function foobar($label)
{
$timer = new Timer(); #(1)
$delay = 2000; # ms
$label->set_text('hello');
$timer->wait($delay); #(2)
$label->set_text('hello World');
return true;
}
?>
So here what we do is :
- create a new instance of the Timer class,
- call the wait method ;
Isn't it an easy way to processes some delays ? Here is how
to achieve that task :
<?php
class Timer
{
protected $timeout;
protected $timeout_id;
public function wait($time)
{
$this->timeout_id = Gtk::timeout_add($time, array($this, 'do_wait'));
Gtk::main();
return true;
}
public function do_wait()
{
Gtk::main_quit();
return false;
}
public function release()
{
Gtk::timeout_remove($this->timeout_id);
Gtk::main_quit();
}
}
?>
Some explanations :
wait() method is based
on Gtk::main() loop.
- When you enter in main loop, all Gtk events are
processed.
- This call is blocking until
Gtk::main_quit()
is invoked
Limitations
Take care : this class design won't work correctly if you
make simultaneous calls to the wait() method.
There is a demonstration code in the attachment files
showing this limitation. So delays should be very short and
you should not not use this class in a loop.
Example
You can find an attachment file below. It contains a combination
of multiple Timer->wait() uses. This file contains
an XML description for a Glade interface so you don't need to
download any extra file.
The most interesting part of this file are :
TimerDemo::run() : the main loop with
blocking design ; in the loop we get an integer value from a
label and increment that value and then wait for a few
milliseconds
- in the
__constructor method, we just have
to create an instance of the Timer class.
<?php
class TimerDemo
{
protected $button_start;
protected $button_stop;
protected $label;
protected $entry;
protected $timer;
protected $running;
public function __construct($start, $stop, $label, $entry)
{
$this->button_start = $start;
$this->button_stop = $stop;
$this->label = $label;
$this->entry = $entry;
$this->timer = new Timer(); # (2)
$this->running = false;
$this->button_start->connect_simple('clicked', array($this, 'on_button_start'));
$this->button_stop->connect_simple('clicked', array($this, 'on_button_stop'));
}
public function on_button_start()
{
if ($this->running)
return false;
$this->running = true;
$this->run();
}
public function on_button_stop()
{
$this->running = false;
}
# (1)
protected function run()
{
while($this->running)
{
$this->label_increment();
$this->timer->wait($this->delay() * 100);
}
}
protected function label_increment()
{
$val = $this->label->get_text();
$this->label->set_text(intval($val+1));
}
protected function delay()
{
return intval($this->entry->get_text());
}
}
?>
Recent comments
6 weeks 2 days ago
12 weeks 1 day ago
13 weeks 6 days ago
20 weeks 2 days ago
21 weeks 4 days ago
21 weeks 5 days ago
22 weeks 6 days ago
23 weeks 5 days ago
34 weeks 3 days ago
34 weeks 4 days ago