Re: A problem about programming with Gtk+



Hello all:
Firstly, Thanks Richard for his valuable infomation and thanks all who
reply me.
I still follow the thread "A problem about programming with
Gtk+(gtk-list Digest, Vol 56, Issue 22)". Maybe I unintentionally
changed the subject in my code:)

I followed the step of Richard's guide, everything run well, but I can
not exit from the callback of g_idle_add correctly. Why?

Following is the code:
//gcc -o tbug t_bug3.c `pkg-config --cflags --libs gtk+-2.0`-lgthread-2.0 -g
//
#include <unistd.h>
#include <stdlib.h>
#include <gtk/gtk.h>
#include <pthread.h>
#include <glib.h>

GtkWidget *win;
static GtkWidget *xpm_label_box( gchar *xpm_filename,
gchar *label_text )
{
GtkWidget *box;
GtkWidget *label;
GtkWidget *image;

box = gtk_hbox_new (FALSE, 0);
gtk_container_set_border_width (GTK_CONTAINER (box), 2);
image = gtk_image_new_from_file (xpm_filename);
label = gtk_label_new (label_text);
gtk_box_pack_start (GTK_BOX (box), image, FALSE, FALSE, 3);
gtk_box_pack_start (GTK_BOX (box), label, FALSE, FALSE, 3);
gtk_widget_show (image);
gtk_widget_show (label);
return box;
}

static gboolean Result (gpointer data)
{
gint param = (gint)data;
GtkWidget* pDialog = gtk_message_dialog_new(GTK_WINDOW(win),
GTK_DIALOG_MODAL,
GTK_MESSAGE_INFO,
GTK_BUTTONS_OK,
"The thread result: %d ",
param);
gtk_dialog_run(GTK_DIALOG(pDialog));
gtk_widget_destroy(pDialog);
return FALSE;
}


static gpointer cursor_change(gpointer data)
{
//1) do your work
GtkWidget *window = (GtkWidget *) data;
win = window;
int i,j;
for(i=0;i<100;i++)
{
g_print ("Hello again - %s was pressed %d\n", (char *) data, i);
}

//2) call g_idle_add to render the result to user
g_idle_add( Result, (gpointer)i);

return NULL;
}


static void callback( GtkWidget *widget, gpointer data )
{
//1) modify the cursor as necessary
GtkWidget *window = (GtkWidget *) data;
GdkCursor *new_cursor;
new_cursor=gdk_cursor_new(GDK_WATCH);
g_print ("I make it!");
gdk_window_set_cursor(window->window, new_cursor);
gdk_cursor_destroy(new_cursor);

//2) create the thread to do the background work
g_thread_create ( cursor_change, data, TRUE, NULL);

//3) quit
return;
}


int main( int argc, char *argv[] )
{
GtkWidget *window;
GtkWidget *button;
GtkWidget *box;

gtk_init (&argc, &argv);
if (!g_thread_supported ())
{
g_thread_init(NULL);
gdk_threads_init();
}

window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "Pixmap'd Buttons!");
g_signal_connect (G_OBJECT (window), "destroy",
G_CALLBACK (gtk_main_quit), NULL);
g_signal_connect (G_OBJECT (window), "delete_event",
G_CALLBACK (gtk_main_quit), NULL);


gtk_container_set_border_width (GTK_CONTAINER (window), 10);

button = gtk_button_new ();
g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (callback),
(gpointer) window);

box = xpm_label_box ("info.xpm", "cool button");
gtk_widget_show (box);
gtk_container_add (GTK_CONTAINER (button), box);
gtk_widget_show (button);
gtk_container_add (GTK_CONTAINER (window), button);
gtk_widget_show (window);

gtk_main ();
return 0;
}





-----------------------------

Message: 4
Date: Sat, 20 Dec 2008 12:16:34 +0100 (CET)
From: "Richard Boaz" <riboaz xs4all nl>
Subject: A problem about programming with Gtk+
To: gtk-list gnome org
Message-ID: <8500 83 82 225 199 1229771794 squirrel webmail xs4all nl>
Content-Type: text/plain;charset=iso-8859-1

what exactly are you trying to do? cause your program's not gonna do much
as it is, and it's not obvious to me what exactly you're trying to achieve
here.

if it's related to modifying the cursor as a result of user interaction,
you should try another model.

that is, set up a different thread to do the background work, not change
the cursor. and you instantiate this thread from within the callback, not
as part of your main routine.

so, the sequence of events might be:

in your callback:
1) modify the cursor as necessary
2) create a thread to do the background work
3) quit

in your thread:
1) do your work
2) call g_idle_add() invoking a function that understands you are
returning from your background thread, i.e., render the results back to
the user

basic guidelines to follow:
1) have your callback do as little work as possible.
2) do any work requiring time in a separate thread, returning to the
mainloop via g_idle_add()

following this model, you will gain the following:
1) user interface will always be responsive since mainloop() will remain
free to process events
2) cursor will change in a timely fashion
3) multiple cpu's will be utilized to their best advantage

if this isn't what you want, then perhaps you could restate your goals?

cheers,

richard

-- 
=======================================================

Sincerely,
Alfred Young
R&D, Application Architectures
www.foxitsoftware.com


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