Tiempos de espera
Puede preguntarse cómo hacer que gtkmm haga trabajo útil mientras está en espera. Afortunadamente, cuenta con varias opciones. Usando los siguientes métodos puede crear un método de tiempo de espera que se llamará cada una cierta cantidad de milisegundos.
sigc::connection Glib::SignalTimeout::connect(const sigc::slot<bool>& slot, unsigned int interval, int priority = Glib::PRIORITY_DEFAULT);
El primer argumento es un slot al que quiere que se llame cuando pase el período de espera. El segundo argumento es el número de milisegundos entre llamadas a ese método. Recibirá un objeto sigc::connection que podrá usar para desactivar la conexión utilizando su método disconnect():
my_connection.disconnect();
Otra manera de destruir la conexión es su manejador de señales. Tiene que ser del tipo sigc::slot<bool>. Como puede observar en la definición, su manejador de señales tiene que devolver un valor del tipo bool. Una definición de un método de ejemplo podría verse así:
bool MyCallback() { std::cout << "Hello World!\n" << std::endl; return true; }
Puede detener el método del período de espera mediante la devolución de false desde su manejador de señales. Por lo tanto, si quiere que su método se llame repetidamente, debe devolver true.
Un ejemplo de esta técnica:
File: timerexample.h (For use with gtkmm 3, not gtkmm 2)
#ifndef GTKMM_EXAMPLE_TIMEREXAMPLE_H #define GTKMM_EXAMPLE_TIMEREXAMPLE_H #include <gtkmm.h> #include <iostream> #include <map> class TimerExample : public Gtk::Window { public: TimerExample(); protected: // signal handlers void on_button_add_timer(); void on_button_delete_timer(); void on_button_quit(); // This is the callback function the timeout will call bool on_timeout(int timer_number); // Member data: Gtk::Box m_Box; Gtk::Button m_ButtonAddTimer, m_ButtonDeleteTimer, m_ButtonQuit; // Keep track of the timers being added: int m_timer_number; // These two constants are initialized in the constructor's member initializer: const int count_value; const int timeout_value; // STL map for storing our connections std::map<int, sigc::connection> m_timers; // STL map for storing our timer values. // Each timer counts back from COUNT_VALUE to 0 and is removed when it reaches 0 std::map<int, int> m_counters; }; #endif // GTKMM_EXAMPLE_TIMEREXAMPLE_H
File: timerexample.cc (For use with gtkmm 3, not gtkmm 2)
#include "timerexample.h" TimerExample::TimerExample() : m_Box(Gtk::ORIENTATION_HORIZONTAL, 10), // use Gtk::Stock wherever possible for buttons, etc. m_ButtonAddTimer(Gtk::Stock::ADD), m_ButtonDeleteTimer(Gtk::Stock::REMOVE), m_ButtonQuit(Gtk::Stock::QUIT), m_timer_number(0), // start numbering the timers at 0 count_value(5), // each timer will count down 5 times before disconnecting timeout_value(1500) // 1500 ms = 1.5 seconds { set_border_width(10); add(m_Box); m_Box.pack_start(m_ButtonAddTimer); m_Box.pack_start(m_ButtonDeleteTimer); m_Box.pack_start(m_ButtonQuit); // Connect the three buttons: m_ButtonQuit.signal_clicked().connect(sigc::mem_fun(*this, &TimerExample::on_button_quit)); m_ButtonAddTimer.signal_clicked().connect(sigc::mem_fun(*this, &TimerExample::on_button_add_timer)); m_ButtonDeleteTimer.signal_clicked().connect(sigc::mem_fun(*this, &TimerExample::on_button_delete_timer)); show_all_children(); } void TimerExample::on_button_quit() { hide(); } void TimerExample::on_button_add_timer() { // Creation of a new object prevents long lines and shows us a little // how slots work. We have 0 parameters and bool as a return value // after calling sigc::bind. sigc::slot<bool> my_slot = sigc::bind(sigc::mem_fun(*this, &TimerExample::on_timeout), m_timer_number); // This is where we connect the slot to the Glib::signal_timeout() sigc::connection conn = Glib::signal_timeout().connect(my_slot, timeout_value); // Remember the connection: m_timers[m_timer_number] = conn; // Initialize timer count: m_counters[m_timer_number] = count_value + 1; // Print some info to the console for the user: std::cout << "added timeout " << m_timer_number++ << std::endl; } void TimerExample::on_button_delete_timer() { // any timers? if(m_timers.empty()) { // no timers left std::cout << "Sorry, there are no timers left." << std::endl; } else { // get the number of the first timer int timer_number = m_timers.begin()->first; // Give some info to the user: std::cout << "manually disconnecting timer " << timer_number << std::endl; // Remove the entry in the counter values m_counters.erase(timer_number); // Diconnect the signal handler: m_timers[timer_number].disconnect(); // Forget the connection: m_timers.erase(timer_number); } } bool TimerExample::on_timeout(int timer_number) { // Print the timer: std::cout << "This is timer " << timer_number; // decrement and check counter value if (--m_counters[timer_number] == 0) { std::cout << " being disconnected" << std::endl; // delete the counter entry in the STL MAP m_counters.erase(timer_number); // delete the connection entry in the STL MAP m_timers.erase(timer_number); // Note that we do not have to explicitly call disconnect() on the // connection since Gtk::Main does this for us when we return false. return false; } // Print the timer value std::cout << " - " << m_counters[timer_number] << "/" << count_value << std::endl; // Keep going (do not disconnect yet): return true; }
File: main.cc (For use with gtkmm 3, not gtkmm 2)
#include "timerexample.h" #include <gtkmm/application.h> int main (int argc, char *argv[]) { Glib::RefPtr<Gtk::Application> app = Gtk::Application::create(argc, argv, "org.gtkmm.example"); TimerExample example; return app->run(example); }