Re: What is the minimum number of lines to update a gui window without user clicking a button
- From: Andrew Potter <agpotter gmail com>
- To: "gtkmm-list gnome org" <gtkmm-list gnome org>
- Subject: Re: What is the minimum number of lines to update a gui window without user clicking a button
- Date: Mon, 19 Aug 2013 14:57:21 -0700
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 ============//
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]