超时
你可能想知道如何使gtkmm在空闲的时候做一些有用的工作。幸运的是你有几种选择。你可以创建一个每几毫秒就调用的超时方法。
sigc::connection Glib::SignalTimeout::connect(const sigc::slot<bool()>& slot, unsigned int interval, int priority = Glib::PRIORITY_DEFAULT);
第一个参数是超时时你希望被调用的slot。第二个参数是调用该方法的时间间隔(多少毫秒)。你将收到一个sigc::connection对象,可以在该对象上调用disconnect()方法断开连接。
my_connection.disconnect();
破坏连接的另一种方法是通过你的信号处理函数的返回值。其类型必须是sigc::slot<bool()>。从定义可以看出信号处理函数必须返回一个bool类型的值。示例方法的定义可能如下所示:
bool MyCallback() { std::cout << "Hello World!\n" << std::endl; return true; }
你可以通过让你的信号处理函数返回false以停止此超时方法。因此,如果你还想重复调用此方法,则你需要让信号处理函数返回true。
这是此技术的示例:
File: timerexample.h (For use with gtkmm 4)
#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: main.cc (For use with gtkmm 4)
#include "timerexample.h" #include <gtkmm/application.h> int main (int argc, char *argv[]) { auto app = Gtk::Application::create("org.gtkmm.example"); return app->make_window_and_run<TimerExample>(argc, argv); }
File: timerexample.cc (For use with gtkmm 4)
#include "timerexample.h" TimerExample::TimerExample() : m_Box(Gtk::Orientation::HORIZONTAL, 10), m_ButtonAddTimer("_Add", true), m_ButtonDeleteTimer("_Remove", true), m_ButtonQuit("_Quit", true), 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 { m_Box.set_margin(10); set_child(m_Box); m_Box.append(m_ButtonAddTimer); m_Box.append(m_ButtonDeleteTimer); m_Box.append(m_ButtonQuit); m_ButtonAddTimer.set_expand(); m_ButtonDeleteTimer.set_expand(); m_ButtonQuit.set_expand(); // 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)); } 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() auto 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; }