Re: GUI signals from a thread (GTK+-3.10)



Here is an example that shows two threads which take a long time to
complete, but gracefully coordinate progress data to the gui.
http://www.simsoup.info/SimSoup/GUI_With_Worker_Threads.html

The best part of this example is that it's in c++ and it demonstrates
that your variables holding thread pointers and thread data don't have
to be global.  They can be held within classes in order to maintain some
namespace organisation and reduce naming conflicts with variables and
functions.

Cheers :)
David Marceau



On 02/14/2014 09:51 PM, Valentin But wrote:
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;
}
_______________________________________________
gtk-app-devel-list mailing list
gtk-app-devel-list gnome org
https://mail.gnome.org/mailman/listinfo/gtk-app-devel-list




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]