Re: Drawing the drawingarea whith another thread...



hi,

you are connecting the expose and configure events after you have created
and shown the widgets.  meaning that your expose and configure events will
not get called until you, the user, do something to make these events get
called.  (or programmatically: if you were to gtk_widget_queue_resize()
the drawing area widget after connecting the signals, you would
automatically generate a configure event.)

but in the meantime, you have executed your drawing thread.  since the
configure event hasn't been called, your drawing code has no pixmap to
draw on and gtk balks (rightly so).

try setting the expose and configure events before you
gtk_widget_show_all() the app.  and then what you'll find is that your
expose event may get called sooner than you want during startup, and then
this will fail too.  i have dealt with startup timing issues by checking
for the pixmap in the expose handler before attempting to draw it, thus:

if (!draw_code_cache_pixmap)
  return TRUE;

simply preventing the code from executing if there's no pixmap yet to draw.

and, i don't see it, but i assume your drawing area widget is actually
created in the code somewhere?  because i don't see where it would be
made, i.e., no routine is called to make it in your main program either? 
since your signal connections seem to work, i assume this is not a
problem.

but even if you connect the events before the widget_show_all() call,
there's another potential problem in that you don't enter the main loop
until after the thread has executed.  the configure and expose events
occur as part of the main loop itself (i.e., after the thread has
started), and so you still will not have a pixmap ready for drawing on
when the thread is called.

since i'm assuming that you will ultimately want to call the drawing
thread as part of normal app behaviour, i.e., more than just at startup, i
would suggest you rework the logic to make the thread called automatically
when you want something drawn.  try instantiating the thread from inside
the configure event.  this way, as well, you get around your original
problem by guaranteeing that the thread won't ever be called until after a
pixmap exists.  (as well, inside the drawing thread, you will need to
programmatically force the expose event by calling
gtk_widget_queue_draw_area() on the drawing area widget.)

this gives you the following logical program flow for your drawing area
widget:

EE1 ->
       ->CE3 -> DT4 -> EX5
IE2 ->

where:
EE1 - any external user event causing a redraw
IE2 - any internal application event causing a redraw, force the configure
event to be called with gtk_widget_queue_resize()
CE3 - your configure event
DT4 - your drawing thread
EX5 - your expose event to finally render to the screen

don't know what your intent is with making the drawing functionality a
separate thread, but be very careful if you wish to be creating more than
one of these to work at the same time; X is old and not so multi-thread
aware as it should be, executing drawing commands simultaneously from
multiple threads will definitely get you into trouble without due care.

good luck,

richard


> Hi all:
>        My env. is GTK+2.0 with Glade-2.
>        I'm trying to draw a drawingarea with a background gthread...I have
> connected the signal expose and configure with the correspond event
> handler
> in callbacks.c
>        My main.c looks like...
> ....
>   1 /*
>   2  * Initial main.c file generated by Glade. Edit as required.
>   3  * Glade will not overwrite this file.
>   4  */
>   5
>   6 #ifdef HAVE_CONFIG_H
>   7 #  include <config.h>
>   8 #endif
>   9
>  10 #include <gtk/gtk.h>
>  11
>  12 #include <glib.h>
>  13
>  14 #include "interface.h"
>  15 #include "support.h"
>  16 #include " callbacks.h"
>  17 #include "my_draw.h"
>  18
>  19 gpointer drawing_thread(gpointer data);
>  20
>  21 int
>  22 main (int argc, char *argv[])
>  23 {
>  24   GtkWidget *window1;
>  25   GtkWidget *aboutdialog1;
>  26
>  27   gtk_set_locale ();
>  28
>  29   if(!g_thread_supported()) g_thread_init(NULL);
>  30         gdk_threads_init();
>  31
>  32 GtkWidget *drawingarea1 = lookup_widget(window1,"drawingarea1");
>  33
>  34   gtk_init (&argc, &argv);
>  35
>  36   add_pixmap_directory (PACKAGE_DATA_DIR "/" PACKAGE "/pixmaps");
>  37
>  38   /*
>  39    * The following code was added by Glade to create one of each
> component
>  40    * (except popup menus), just so that you see something after
> building
>  41    * the project. Delete any components that you don't want shown
> initially.
>  42    */
>  43   window1 = create_window1 ();
>  44   gtk_widget_show (window1);
>  45   aboutdialog1 = create_aboutdialog1 ();
>  46   gtk_widget_show (aboutdialog1);
>  47
>  48 g_signal_connect(G_OBJECT(drawingarea1),
> "expose-event",G_CALLBACK(on_drawingarea1_expose_event), NULL);
>  49 g_signal_connect(G_OBJECT(drawingarea1),
> "configure-event",G_CALLBACK(on_drawingarea1_configure_event), NULL);
>  50
>  51 //  drawing_thread
>  52 g_thread_create(drawing_thread, window1 , TRUE, NULL);
>  53
>  54 gdk_threads_enter();
>  55   gtk_main ();
>  56 gdk_threads_leave();
>  57   return 0;
>  58 }
>  59
>
>
> and in the callbacks.c
>  92 gboolean
>  93 on_drawingarea1_expose_event           (GtkWidget       *widget,
>  94                                         GdkEventExpose  *event,
>  95                                         gpointer         user_data)
>  96 {
>  97
>  98    gdk_draw_drawable(widget->window,
>  99                     widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
> 100                     draw_code_cache_pixmap,
> 101                     event->area.x, event->area.y,
> 102                     event->area.x, event->area.y,
> 103                     event->area.width , event->area.height);
> 104   return FALSE;
> 105 }
> 106
>
> 140 gboolean
> 141 on_drawingarea1_configure_event        (GtkWidget       *widget,
> 142                                         GdkEventConfigure *event,
> 143                                         gpointer         user_data)
> 144 {
> 145  if(draw_code_cache_pixmap)
> 146         g_object_unref(draw_code_cache_pixmap);
> 147
> 148   draw_code_cache_pixmap = gdk_pixmap_new(widget->window,
> 149                           widget->allocation.width,
> 150                           widget->allocation.height,
> 151                           -1);
> 152
> 153   return FALSE;
> 154 }
>
> and my draeing thread is
>   6 gpointer drawing_thread(gpointer data){
>   7         gint x_aix;
>   8         gint y_aix;
>   9         gint trace_len=0;
>  10         GtkWidget* sim_drawing_area = (GtkWidget*)data;
>  11
>  12         for(;;){
>  13         if(trace_len >= 50)
>  14                 trace_len = 0;
>  15
>  16         gdk_threads_enter();
>  17
>  18
> //gdk_draw_rectangle(_sim_drawing_data->sim_drawing_area->window,
>  19         gdk_draw_rectangle(draw_code_cache_pixmap,
>  20
> sim_drawing_area->style->fg_gc[GTK_WIDGET_STATE (sim_drawing_area)],
>  21                            TRUE,
>  22                            0,
>  23                            0,
>  24                            trace_len,
>  25                            20);
>  26         gdk_flush();
>  27         gdk_threads_leave();
>  28
>  29         trace_len++;
>  30         }
>  31 }
>
> I'm created a pixmap in the on_drawingarea1_configure_event function, and
> connect this envnt handler with the corresponded signal.
> But, as I execute the program, I got the following error msg...
>
> (gui2:27742): Gdk-CRITICAL **: gdk_draw_rectangle: assertion
> `GDK_IS_DRAWABLE (drawable)' failed
>
> (gui2:27742): Gdk-CRITICAL **: gdk_draw_rectangle: assertion
> `GDK_IS_DRAWABLE (drawable)' failed
>
> (gui2:27742): Gdk-CRITICAL **: gdk_draw_rectangle: assertion
> `GDK_IS_DRAWABLE (drawable)' failed
>
>
> Does any idea?
>
> ThankX!!!!
>
> Dave.
>
>
>
> --
> System  on Chip Design  Lab.
> Dept. of Computer Science and Information Engineering,
> National Chung Cheng University
> E-mail : s88 tw acm org
> _______________________________________________
> gtk-list mailing list
> gtk-list gnome org
> http://mail.gnome.org/mailman/listinfo/gtk-list
>





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