01 May 2013 - After the site upgrade, all passwords were reset and you will need to ask the site for a login reset on your first connection.

Timer class : simplifying gtk::timeout_add

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 :

  1. create a new instance of the Timer class,
  2. 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

Timer class 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 :

  1. 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
  2. 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());
    }
  }
?>
AnhangGröße
timer.php_.txt16.05 KB
CHANGELOG.txt41.12 KB