I've changed Example 4 to use a TextView instead of a Label and renamed report_progress() to gui_print().
//========== Example 5 Begin ============// #include <gtkmm.h> #include <unistd.h> #include <queue> class CallbackDispatcher { public: CallbackDispatcher() { dispatcher.connect(sigc::mem_fun(this, &CallbackDispatcher::on_dispatch)); } typedef sigc::slot<void> Message; void send(Message msg) { Glib::Threads::Mutex::Lock lock(mutex); queue.push(msg); dispatcher(); } private: /* CallbackDispatcher may not be copied, so we must hide these * constructors. */ CallbackDispatcher(const CallbackDispatcher&); CallbackDispatcher& operator=(const CallbackDispatcher&); Glib::Threads::Mutex mutex; std::queue<Message> queue; Glib::Dispatcher dispatcher; void on_dispatch() { Glib::Threads::Mutex::Lock lock(mutex); while (!queue.empty()) { queue.front()(); queue.pop(); } } }; class Example { private: Glib::RefPtr<Gtk::Application> app; Gtk::Window win; Gtk::TextView tv; Glib::RefPtr<Gtk::TextBuffer> tb; CallbackDispatcher callback_dispatcher; Glib::Threads::Thread *thread; void gui_print(const Glib::ustring& str) { /* Get a function pointer to the set_text method we want to * use. We must explicitly declare the method pointer * signature because Gtk::TextBuffer::set_text is an * overloaded method. */ void (Gtk::TextBuffer::*fptr)(const Glib::ustring&) = &Gtk::TextBuffer::set_text; /* Create a functor that points at the TextBuffer method we * want to use. Because tb is a Glib::RefPtr and sigc::mem_fun * needs the actual Gtk::TextBuffer object, we must use * operator->(). See GNOME Bugzilla #495762. */ sigc::slot<void, const Glib::ustring&> set_text_functor = sigc::mem_fun(tb.operator->(), fptr); /* Bind the arguments of the functor to create a * sigc::slot<void> that can be sent to the callback * dispatcher. */ sigc::slot<void> bound_functor = sigc::bind(set_text_functor, str); /* callback_dispatcher can execute any sigc::slot<void> on the * Main Loop. Since we have one now, send it. */ callback_dispatcher.send(bound_functor); } /* This function is called on a separate thread so as to avoid * blocking GTK+'s main loop. */ void blocking_operation() { /* This simulates a blocking process */ sleep(5); gui_print("5% complete."); sleep(5); gui_print("15% complete."); sleep(5); gui_print("35% complete."); sleep(5); gui_print("55% complete."); sleep(5); gui_print("75% complete."); sleep(5); gui_print("95% complete."); sleep(5); gui_print("100% complete."); /* When the process is finished, we notify the GTK+ Main Loop by * using the dispatcher */ callback_dispatcher.send(sigc::mem_fun(this, &Example::blocking_operation_finished)); }; /* This function is called on GTK+'s main loop via a * Glib::Dispatcher */ void blocking_operation_finished() { cleanup_thread(); tb->set_text("Operation finished."); }; void cleanup_thread() { /* We must call Glib::Threads::Thread::join() in order to * correctly clean up the resource. */ if (thread) { thread->join(); thread = NULL; } } public: ~Example() { /* This will prevent the Window from being closed while * the blocking operation is ongoing. */ cleanup_thread(); } Example(int argc, char *argv[]) : app(Gtk::Application::create(argc, argv, "com.example")), tb(tv.get_buffer()), thread(NULL) { win.add(tv); win.show_all(); } void run() { /* Create a slot to the blocking_operation() member function * to pass to Glib::Threads::Thread::create(). */ sigc::slot<void> op_functor = sigc::mem_fun(this, &Example::blocking_operation); /* Create a worker thread to perform the blocking_operation * function. */ thread = Glib::Threads::Thread::create(op_functor); /* Now set the text in the buffer. */ tb->set_text("Operation started."); app->run(win); } }; int main(int argc, char *argv[]) { Example example(argc, argv); example.run(); return 0; } //========== Example 5 End ============// _______________________________________________ gtkmm-list mailing list gtkmm-list@gnome.org https://mail.gnome.org/mailman/listinfo/gtkmm-list