Gregor,
Thanks for working on this.
backend_qtagg.py seems to contain a proper (more or
less, see other postings of Ted Drain) implementation of double buffered drawing that avoids unnecessary rerendering of the bitmap.
It still feels a bit kludgy to me -- a paint event should simply copy
the bitmap to the screen, any re-rendering should be triggered by other
events -- either a re-size, or explicitly by figure.canvas.draw() or
something. Anyway, given the current structure, this looks like the way
to go.
self._need_rerender = True
Where does this get set to True again? On a Figure.canvas.draw() call?
changed _onPaint(...) to following (note: removed evt.Skip() at end!)
def _onPaint(self, evt):
#repaint only damaged parts of window
I don't know that this is needed, bitting the whole Window is blazingly
fast anyway -- but if it works, why not?
dc = wx.PaintDC(self)
source = wx.MemoryDC(self.bitmap)
box = self.UpdateRegion.Box
dc.Blit(box.X, box.Y, box.Width, box.Height,
source,
box.X, box.Y)
source.SelectObject(wx.NullBitmap) #needed?
no, it goes away at the end of the method, anyway.
By these change in onPaint a rerendering of the bitmap is done only if
needed (in fact, this is needed only once after the figure is shown
for the first time).
Well, it's needed whenever the figure changes -- on each
figure.canvas.draw() call, I guess.
I moved code from gui_repaint() into
_onPaint. Calls to gui_repaint() in other methods (e.g., draw) might now be
replaced by
self.Refresh()
self.Update() #this is optional, leeds to an immediate repaint
Maybe -- I've found (at least on OS-X) that using a ClientDC is still
required sometimes to get instant response. This is key if you're doing
anything like animation.
def draw(self, repaint=True):
"""
Render the figure using agg.
"""
DEBUG_MSG("draw()", 1, self)
FigureCanvasAgg.draw(self)
self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
if repaint:
self.Refresh(eraseBackground = False)
self.Update()
I think maybe these should be calls to gui_repaint, which will get you
to a ClientDC instead of waiting for a paint event -- Update is not
always instant.
self.Update() #needed?
Same as above.
I had to add some calls to figure.canvas.draw in my mpl-embedded-in-wx
application, e.g., after changing a colormap range, to give a
immediate change on screen. Before due to the frequent rerendering I
didn't notice that these statements were missing.
I agree -- I think I'm going to need to add a few of those too. The
problem is that this is a change, and other folks' code is going to
break too.
As Chris Barker noticed, Figure.draw() does not lead to a repainting
of the window on screen. This seems to be intended. Instead one should
use pylab.draw() or Figure.canvas.draw().
I think you're right -- I should have looked at the pylab.draw code to
see what it did. Though I think Figure should have a method that does do
an instant update...DrawNow??
I thought about a more substantial rewrite of the Wx/WxAgg backend,
similar to the QtAgg backend,
I think it does kind of need it.
Anyhow, the Wx backend seems to be in some
aspects outdated (uses old style wx methods, e.g. ToolBar.AddTool) and
is even not fully functional (image support missing). What are the
plans for the future?
Well, I think most folks use wxAgg, rather than the straight wx
back-end. As for other updating -- it's not a matter of plans so much as
someone needing to step up and do it!
What about the politics of supporting older versions of wxWidgets?
I wouldn't bother, but I'm a bleeding-edge kind of guy. It seems that we
could at least make sure not to break anything by keeping the old code
around for older versions, and go all 2.8 for new code, with one big 'ol
version test at the top of the modules.
Thanks for working on this,
-Chris
···
--
Christopher Barker, Ph.D.
Oceanographer
Emergency Response Division
NOAA/NOS/OR&R (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception
Chris.Barker@...236...