A Qui, 2004-03-04 �s 09:26, Andrew P. Lentvorski, Jr. escreveu:
> On Tue, 2 Mar 2004, Gustavo J. A. M. Carneiro wrote:
>
> > That is a sign of bad design. This only happens if you do this:
> > def expose_event_cb(widget, event):
> > # .... start some drawing
> > while more_work:
> > # do some heavy work to obtain results
> > # draw some more stuff based on results
> > # end drawing and return
> >
> > But this kind of algorithm is completely incorrect in pygtk.
>
> No heavy work is required, just a boatload of objects.
>
> The use case is a VLSI polygon editor. Several million objects have to be
> drawn in multiple layers at top level. Note that this may be more objects
> than the number of pixels in the DrawingArea! Those objects absolutely
> must appear on screen to let the user know that drawing is going on, that
> the action is abortable/has aborted, as well as give feedback so that the
> user can make a choice of zoom even before all the objects appear.
>
> Since PyGtk has no way of providing a guaranteed time callback timer, the
> only way to ensure a user interface which feels responsive is to render to
> both the screen and the backing buffer simultaneously while checking the
> event queue. Causing a flush on every object slows the entire system down
> by factors of 10-100 (unacceptable as the drawing is already taking
> minutes) as well as increases the tearing artifacts which occur when not
> synchronized with the vertical refresh.
pygtk does have gobject.timer_add, you know... it is not strictly
guaranteed timer, but close enough. Your scenario could be implemented
in pygtk with the following structure:
def expose_event(widget, event):
global offscreen_pixmap
# render exposed area of offscreen pixmap to widget.window
def timeout_cb():
widget.queue_draw()
if more_objects_to_draw:
return True
else:
return False
def idle_handler():
global offscreen_pixmap
# draw one object to offscreen_pixmap
if more_objects_to_draw:
return True
else:
widget.queue_draw()
return False
def start_drawing(): # called when you want to redraw the whole thing
# clear offscreen_pixmap
gobject.idle_add(idle_handler)
gobject.timeout_add(50, timeout_cb)
However, this is not much better than your solution, I admit. Also,
this is one case when _automatic_ double buffering by gtk is not
desired, since we do our own double buffering.
>
> > > Most GtkDrawingArea folks with complex drawing needs probably want
> > > set_double_buffered(False).
> >
> > I disagree. "Having an application pause a long time with a blank
> > DrawingArea and then suddenly having all the drawing miraculously
> > appear" => that is exactly the purpose of double buffering. The user
> > should _not_ see the application redrawing.
>
> This is only correct in the case of UI primitives (buttons, scrollbars,
> ruler, etc.). UI primitives have lightweight atomic drawing tasks easily
> finished within user perception limits.
>
> For data displays, this is absolutely *wrong*. A data display UI that
> pauses or fails to give feedback within .1 seconds violates most accepted
> principles of UI design. In many cases, continuous update of the
> displayed data is not just okay but is often expected (waterfall FFT
> analysis, polar mapping of radar images, finite element modeling data from
> electromagnetic analysis, etc.).
Correct. But, your use case is so extreme that there is no good
solution except getting faster hardware ;)
An alternative to make it work with slower hardware is simplify the
drawing during user interaction, and then revert to the full precision
drawing when the user stops interacting. Another option is draw
everything with full precision, but during user interaction only draw
the parts that change. XOR line drawing is usually very good for this.
>
> I would, in fact, make the argument that if the double buffering that a
> DrawingArea does is good enough, then you should probably being using a
> Canvas instead.
Well, a Canvas-like drawing model for all gtk+ widgets has been
discussed in the past and may be on the horizon for gtk+ 3.0 ;-)
But we are deviating from topic. I think that putting all this in the
FAQ is a bit overkill. A FAQ is supposed to have simple question and
simple answers.
Regards.
--
Gustavo Jo�o Alves Marques Carneiro
<[EMAIL PROTECTED]> <[EMAIL PROTECTED]>
The universe is always one step beyond logic.
_______________________________________________
pygtk mailing list [EMAIL PROTECTED]
http://www.daa.com.au/mailman/listinfo/pygtk
Read the PyGTK FAQ: http://www.async.com.br/faq/pygtk/