Re: drawing graphics



On Thu, 19 Sep 2002 13:39:51 -0700
Steven Jenkins <steven jenkins ieee org> wrote:

> Ian Britten wrote:
> > In addition to using a background pixmap (as suggested), I also 'attach'
> > the pixmap to the window (using gdk_window_set_back_pixmap()).
> > This way, you never have to deal with expose events (unless you are
> > drawing stuff that isn't in your background pixmap).
> 
> Interesting. Please indulge some newbie questions. 

[ Disclaimer - As a former X programmer who ported to GTK, I knew what X
was capable of, and dug around for the equivalent GTK capabilities.  I
don't think this technique is the 'normal GTK way' of drawing, but I'm not
sure why... ]

> Is gdk_window_set_back_pixmap() documented? All I can find is the function 
> prototype.

Haven't a clue... :-/
It's just a thin wrapper around XSetWindowBackgroundPixmap(), which should
be well documented (Thanks to O'Reilly!)

> Where do I apply it (presumably in the configure_event 
> handler where the pixmap is created)?

We have Glade create a typical drawing area.  (Or, use any other technique)
The application passes the drawing area into our 'canvas', as a GtkWidget.
The widget must be realized by this point (but not necessarily mapped).
Make a background pixmap the same size/depth
      bgPixmap = gdk_pixmap_new(drawArea->window, drawArea->allocation.width,
                                drawArea->allocation.height, -1);
Set the background pixmap as the background of the drawing areas window
      gdk_window_set_back_pixmap(drawArea->window, bgPixmap, 0);


Note that if the window is recreated, you need to re-attach the existing
bgPixmap to the (new?) window.  To date, we've run into this for "realize"
and "style_set" signals - Just set up signal handlers to these signals, and
call gdk_window_set_back_pixmap() again.

Also note that (as normal) if the drawing area is resized, etc, the
bgPixmap must be recreated at the new size, and re-attached.

> If I use it, do I no longer need to use gtk_widget_draw() to generate
> expose events?

[ I'm unsure what gtk_widget_draw() does... ]
In your drawing code, you simply draw to the bgPixmap using whatever
drawing calls you need/want (gdk_draw_lines(), etc).  Since the bgPixmap
is a type of drawable (the same as a window is), either can be used.

Depending on how you want your app to present itself, you can draw all the
data to the bgPixmap, then show it all at once at the end (by simply copying
the bgPixmap to the window), or if you want a 'progressive'-type draw, you
can draw each piece of data to both the bgPixmap and the window (2 calls to
gdk_draw_lines()), which will make your data gradually appear.

(I use the second technique, with chunks of the data being drawn from inside
idle events, due to the volume of data we draw.  This allows the draw to
be stopped by the user)

Once the data is drawn, the X-server will take care of exposing it as
necessary, and the expose will simply be a pixmap copy (rather than a
slow redraw).  In fact, your app won't even have to hook up a signal
handler for expose events!  (Unless you have other needs...)

> What does the last argument (parent_relative) mean?

See XSetWindowBackgroundPixmap()  (I always just use zero).

> Right. My attempts to do better with pixmaps have also had problems. I 
> based my application loosely on the double-buffered clock application in 
>   Harlow's book. Instead of re-drawing the entire pixmap and calling 
> gtk_widget_draw to expose the entire drawing area, I've been trying to 
> change only part of the pixmap and expose only what's changed. I can 
> make the brute force version behave predictably but too slowly to be 
> useful. So far, I can't make the more optimized version work 
> predictably. It's probably my error, but I'd just as soon not have to 
> figure it out.

Ya, I've seen this (dreadfully-slow) brute-force approach being used by a
lot of new(er) apps.  Personally, I find it dreadful, and I'm not sure
why no one complains about it... :-/

(Hint - Fire up a bunch of applications.  Grab a small window (xclock),
and drag it around over the other windows (assuming your WM is configured
to do real-time moves).  Watch for your CPU to spike.  Basic pixmap
copies (which is all an app should be doing for an expose) should be
almost instant, and certainly shouldn't bury the CPU.  Lately, I'm finding
I have to minimize more and more apps, as simply moving a window buries
my CPU for 10-40 seconds!  Bletch!)

Ian



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