Hi,
The attached patch has a couple of changes to the wx backend that I
want people to test before I commit.
1) implement draw_idle. Rather than using the wx IdleEvent which seemed
to be triggered too often I used a timer which is delayed and possibly
reset if a new draw request comes within a certain time period (5 ms),
or if there are pending wx events. The scheme isn't perfect since wx
doesn't see all the native events, but it seems to work well enough.
2) Don't draw bitmap on the screen if the graph isn't shown. Otherwise
a plot inside of a wx aui notebook bleeds through even if the graph
notebook is not on top.
3) Don't regenerate entire plot for each PaintEvent. Instead, only
draw the graph if this is the first time the window is exposed, otherwise
work from the bitmap. I've only tested this for wxagg on the mac. I don't
know if it breaks wx, or if anyone cares about wx anymore.
Let me know if it works for you.
- Paul
Index: backend_wx.py
===================================================================
--- backend_wx.py (revision 4696)
+++ backend_wx.py (working copy)
@@ -753,6 +753,10 @@
self._isConfigured = False
self._printQued = []
+ # Need to render the window properly if this is the first time
+ # it is being shown since it has changed.
+ self._isRendered = False
+
if wx.VERSION_STRING >= '2.5':
# Event handlers 2.5
self.Bind(wx.EVT_SIZE, self._onSize)
@@ -789,6 +793,13 @@
self.Printer_Init()
+ # Create an timer for handling draw_idle requests
+ # If there are events pending when the timer is
+ # complete, reset the timer and continue. The
+ # alternative approach, binding to wx.EVT_IDLE,
+ # doesn't behave as nicely.
+ self.idletimer = wx.CallLater(1,self._onDrawIdle)
+
def Destroy(self, *args, **kwargs):
wx.Panel.Destroy(self, *args, **kwargs)
@@ -943,17 +954,36 @@
self.gui_repaint()
- def draw(self, repaint=True):
+ def draw_idle(self, *args, **kwargs):
"""
+ Render after a delay if no other render requests have been made.
+ """
+ DEBUG_MSG("draw_idle()", 1, self)
+ self.idletimer.Restart(5, *args, **kwargs) # Delay by 5 ms
+
+ def _onDrawIdle(self, *args, **kwargs):
+ if False and wx.GetApp().Pending():
+ self.idletimer.Restart(5, *args, **kwargs)
+ else:
+ self.draw(*args, **kwargs)
+
+ def draw(self, drawDC=None):
+ """
Render the figure using RendererWx instance renderer, or using a
previously defined renderer if none is specified.
"""
DEBUG_MSG("draw()", 1, self)
- self.renderer = RendererWx(self.bitmap, self.figure.dpi)
- self.figure.draw(self.renderer)
- if repaint:
- self.gui_repaint()
+ # Only draw if window is shown, otherwise graph will bleed through
+ # on the notebook style AUI widgets.
+ if self.IsShownOnScreen():
+ self._isRendered = True
+ self.renderer = RendererWx(self.bitmap, self.figure.dpi)
+ self.figure.draw(self.renderer)
+ self.gui_repaint(drawDC=drawDC)
+ else:
+ self._isRendered = False
+
def _get_imagesave_wildcards(self):
'return the wildcard string for the filesave dialog'
default_filetype = self.get_default_filetype()
@@ -1050,6 +1080,10 @@
# Restore everything to normal
self.bitmap = origBitmap
+ # Note: draw is required here since bits of state about the
+ # last renderer are strewn about the artist draw methods. Do
+ # not remove the draw without first verifying that these have
+ # been cleaned up.
self.draw()
self.Refresh()
@@ -1077,10 +1111,15 @@
DEBUG_MSG("_onPaint()", 1, self)
if not self._isRealized:
self.realize()
- # Render to the bitmap
- self.draw(repaint=False)
- # Update the display using a PaintDC
- self.gui_repaint(drawDC=wx.PaintDC(self))
+
+ # Need to draw the graph the first time it is shown otherwise
+ # it is a black canvas. After that we can use the rendered
+ # bitmap for updates.
+ if self._isRendered:
+ self.gui_repaint(drawDC=wx.PaintDC(self))
+ else:
+ self.draw(drawDC=wx.PaintDC(self))
+
evt.Skip()
def _onSize(self, evt):
Index: backend_wxagg.py
===================================================================
--- backend_wxagg.py (revision 4696)
+++ backend_wxagg.py (working copy)
@@ -53,16 +53,21 @@
size.
"""
- def draw(self, repaint=True):
+ def draw(self, drawDC=None):
"""
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.gui_repaint()
+ # Only draw if window is shown, otherwise graph will bleed through
+ # on the notebook style AUI widgets.
+ if self.IsShownOnScreen():
+ self._isRendered = True
+ FigureCanvasAgg.draw(self)
+ self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
+ self.gui_repaint(drawDC=drawDC)
+ else:
+ self._isRendered = False
def blit(self, bbox=None):
"""
-------------------------------------------------------------------------
SF.Net email is sponsored by:
Check out the new SourceForge.net Marketplace.
It's the best place to buy or sell services for
just about anything Open Source.
http://sourceforge.net/services/buy/index.php
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel