GUI signals from a thread (GTK+-3.10)
- From: Valentin But <valentin but eesti ee>
- To: gtk-app-devel-list gnome org
- Subject: GUI signals from a thread (GTK+-3.10)
- Date: Sat, 15 Feb 2014 04:51:50 +0200
Greetings gtk-app-devel-list.
I'm a newbie GTK+ developer and I have encountered with a problem.
I tried to create a DC Motor Transient process calculation as a
practice programm for learning.
I've wanted to have a feedback of the calculation process on a progress bar.
Documentation say that "the threading support has been deprecated in
GTK+ 3.6. Instead of calling GTK+ directly from multiple threads, it
is recommended to use g_idle_add(), g_main_context_invoke() and
similar functions to make these calls from the main thread instead".
I have no idea how g_main_context_invoke() could be usefull for that
and g_idle_add() is totally wrong: because if something heavy in the
function happens, then the GUI hangs anyway.
I don't adequate way to transfer status report from a thread, that
blocks a lot, for example very laggy socket connections.
Here's a minimal programm. Somehow GTK+ calls from thread are working.
How sinfull is that?
#include <stdlib.h>
#include <gtk/gtk.h>
struct CallbackObject
{
GtkWidget *win;
GtkWidget *button;
GtkWidget *progress;
};
gpointer thread_func( struct CallbackObject *callobj );
static void startstop_thread (GtkWidget *wid, struct CallbackObject *callobj);
GThread *pthread = NULL;
gboolean thread_run = FALSE;
const gchar *label_start = "Start thread";
const gchar *label_stop = "Stop thread";
gpointer thread_func( struct CallbackObject *callobj )
{
gdouble x = 0.0;
while (x < 1.0 && thread_run == TRUE)
{
usleep (20*1000);
x += 1.0 / 50;
gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (callobj->progress), x);
}
thread_run = FALSE;
pthread = NULL;
gtk_button_set_label (GTK_BUTTON (callobj->button), label_start);
return NULL;
}
static void startstop_thread (GtkWidget *wid, struct CallbackObject *callobj)
{
gpointer user_data = callobj;
if (thread_run == FALSE)
{
thread_run = TRUE;
pthread = g_thread_new ("thread", (GThreadFunc) thread_func, user_data);
gtk_button_set_label (GTK_BUTTON (callobj->button), label_stop);
}
else
{
thread_run = FALSE;
g_thread_join (pthread);
pthread = NULL;
gtk_button_set_label (GTK_BUTTON (callobj->button), label_start);
}
}
int main (int argc, char *argv[])
{
GtkWidget *button = NULL;
GtkWidget *vbox = NULL;
struct CallbackObject *callobj = NULL;
/* Initialize GTK+ */
g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, (GLogFunc) gtk_false, NULL);
gtk_init (&argc, &argv);
g_log_set_handler ("Gtk", G_LOG_LEVEL_WARNING, g_log_default_handler, NULL);
callobj = g_malloc (sizeof(struct CallbackObject));
/* Create the main window */
callobj->win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_container_set_border_width (GTK_CONTAINER (callobj->win), 8);
gtk_window_set_title (GTK_WINDOW (callobj->win), "GTK+-3.10.7-1 Threads");
gtk_window_set_position (GTK_WINDOW (callobj->win), GTK_WIN_POS_CENTER);
gtk_widget_realize (callobj->win);
g_signal_connect (callobj->win, "destroy", gtk_main_quit, NULL);
/* Create a vertical box with buttons */
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 8);
gtk_container_add (GTK_CONTAINER (callobj->win), vbox);
callobj->progress = gtk_progress_bar_new ();
gtk_progress_bar_set_show_text (GTK_PROGRESS_BAR (callobj->progress), TRUE);
gtk_box_pack_start (GTK_BOX (vbox), callobj->progress, TRUE, TRUE, 0);
callobj->button = gtk_button_new_with_label ("Start thread");
g_signal_connect (G_OBJECT (callobj->button), "clicked", G_CALLBACK
(startstop_thread), (gpointer) callobj);
gtk_box_pack_start (GTK_BOX (vbox), callobj->button, TRUE, TRUE, 0);
button = gtk_button_new_with_label ("Close");
g_signal_connect (button, "clicked", gtk_main_quit, NULL);
gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
/* Enter the main loop */
gtk_widget_show_all (callobj->win);
gtk_main ();
g_free (callobj);
return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]