|
From: <pki...@us...> - 2008-07-28 07:26:49
|
Revision: 5907
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=5907&view=rev
Author: pkienzle
Date: 2008-07-28 07:26:47 +0000 (Mon, 28 Jul 2008)
Log Message:
-----------
Render Wx backends only when necessary
Modified Paths:
--------------
trunk/matplotlib/lib/matplotlib/backends/backend_wx.py
trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wx.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-07-27 20:42:13 UTC (rev 5906)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_wx.py 2008-07-28 07:26:47 UTC (rev 5907)
@@ -700,12 +700,11 @@
self.bitmap =wx.EmptyBitmap(w, h)
DEBUG_MSG("__init__() - bitmap w:%d h:%d" % (w,h), 2, self)
# TODO: Add support for 'point' inspection and plot navigation.
- self._isRealized = False
- self._isConfigured = False
- self._printQued = []
+ self._isDrawn = False
bind(self, wx.EVT_SIZE, self._onSize)
bind(self, wx.EVT_PAINT, self._onPaint)
+ bind(self, wx.EVT_ERASE_BACKGROUND, self._onEraseBackground)
bind(self, wx.EVT_KEY_DOWN, self._onKeyDown)
bind(self, wx.EVT_KEY_UP, self._onKeyUp)
bind(self, wx.EVT_RIGHT_DOWN, self._onRightButtonDown)
@@ -718,21 +717,12 @@
bind(self, wx.EVT_MOTION, self._onMotion)
bind(self, wx.EVT_LEAVE_WINDOW, self._onLeave)
bind(self, wx.EVT_IDLE, self._onIdle)
+ self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.macros = {} # dict from wx id to seq of macros
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)
- self.idletimer = wx.FutureCall(1,self._onDrawIdle)
- # FutureCall is a backwards-compatible alias;
- # CallLater became available in 2.7.1.1.
-
def Destroy(self, *args, **kwargs):
wx.Panel.Destroy(self, *args, **kwargs)
@@ -887,20 +877,35 @@
self.gui_repaint()
- def draw_idle(self, *args, **kwargs):
+ def draw_idle(self):
"""
Delay rendering until the GUI is idle.
"""
DEBUG_MSG("draw_idle()", 1, self)
- self.idletimer.Restart(50, *args, **kwargs) # Delay by 50 ms
+ self._isDrawn = False # Force redraw
+ # Create a 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.
+ if hasattr(self,'_idletimer'):
+ self._idletimer.Restart(50)
+ else:
+ self._idletimer = wx.FutureCall(50,self._onDrawIdle)
+ # FutureCall is a backwards-compatible alias;
+ # CallLater became available in 2.7.1.1.
def _onDrawIdle(self, *args, **kwargs):
- if False and wx.GetApp().Pending():
- self.idletimer.Restart(5, *args, **kwargs)
+ if wx.GetApp().Pending():
+ self._idletimer.Restart(50, *args, **kwargs)
else:
- self.draw(*args, **kwargs)
+ del self._idletimer
+ # GUI event or explicit draw call may already
+ # have caused the draw to take place
+ if not self._isDrawn:
+ self.draw(*args, **kwargs)
- def draw(self, repaint=True):
+ def draw(self, drawDC=None):
"""
Render the figure using RendererWx instance renderer, or using a
previously defined renderer if none is specified.
@@ -908,8 +913,8 @@
DEBUG_MSG("draw()", 1, self)
self.renderer = RendererWx(self.bitmap, self.figure.dpi)
self.figure.draw(self.renderer)
- if repaint:
- self.gui_repaint()
+ self._isDrawn = True
+ self.gui_repaint(drawDC=drawDC)
def flush_events(self):
wx.Yield()
@@ -988,7 +993,6 @@
"""
DEBUG_MSG("gui_repaint()", 1, self)
if self.IsShownOnScreen():
-
if drawDC is None:
drawDC=wx.ClientDC(self)
@@ -996,6 +1000,8 @@
drawDC.DrawBitmap(self.bitmap, 0, 0)
drawDC.EndDrawing()
#wx.GetApp().Yield()
+ else:
+ pass
filetypes = FigureCanvasBase.filetypes.copy()
filetypes['bmp'] = 'Windows bitmap'
@@ -1007,6 +1013,16 @@
filetypes['tiff'] = 'Tagged Image Format File'
filetypes['xpm'] = 'X pixmap'
+ def print_figure(self, filename, *args, **kwargs):
+ # Use pure Agg renderer to draw
+ FigureCanvasBase.print_figure(self, filename, *args, **kwargs)
+ # Restore the current view; this is needed because the
+ # artist contains methods rely on particular attributes
+ # of the rendered figure for determining things like
+ # bounding boxes.
+ if self._isDrawn:
+ self.draw()
+
def print_bmp(self, filename, *args, **kwargs):
return self._print_image(filename, wx.BITMAP_TYPE_BMP, *args, **kwargs)
@@ -1034,8 +1050,6 @@
width = int(math.ceil(width))
height = int(math.ceil(height))
- # Following performs the same function as realize(), but without
- # setting GUI attributes - so GUI draw() will render correctly
self.bitmap = wx.EmptyBitmap(width, height)
renderer = RendererWx(self.bitmap, self.figure.dpi)
@@ -1048,9 +1062,6 @@
if is_string_like(filename):
if not self.bitmap.SaveFile(filename, filetype):
DEBUG_MSG('print_figure() file save error', 4, self)
- # note the error must be displayed here because trapping
- # the error on a call or print_figure may not work because
- # printing can be qued and called from realize
raise RuntimeError('Could not save figure to %s\n' % (filename))
elif is_writable_file_like(filename):
if not self.bitmap.ConvertToImage().SaveStream(filename, filetype):
@@ -1063,40 +1074,35 @@
# 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()
+ # been cleaned up. The artist contains() methods will fail
+ # otherwise.
+ if self._isDrawn:
+ self.draw()
self.Refresh()
def get_default_filetype(self):
return 'png'
- def realize(self):
- """
- This method will be called when the system is ready to draw,
- eg when a GUI window is realized
- """
- DEBUG_MSG("realize()", 1, self)
- self._isRealized = True
- for fname, dpi, facecolor, edgecolor in self._printQued:
- self.print_figure(fname, dpi, facecolor, edgecolor)
- self._printQued = []
-
-
-
def _onPaint(self, evt):
"""
Called when wxPaintEvt is generated
"""
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))
+ drawDC = wx.PaintDC(self)
+ if not self._isDrawn:
+ self.draw(drawDC=drawDC)
+ else:
+ self.gui_repaint(drawDC=drawDC)
evt.Skip()
+ def _onEraseBackground(self, evt):
+ """
+ Called when window is redrawn; since we are blitting the entire
+ image, we can leave this blank to suppress flicker.
+ """
+ pass
+
def _onSize(self, evt):
"""
Called when wxEventSize is generated.
@@ -1109,21 +1115,19 @@
# Create a new, correctly sized bitmap
self._width, self._height = self.GetClientSize()
self.bitmap =wx.EmptyBitmap(self._width, self._height)
+ self._isDrawn = False
if self._width <= 1 or self._height <= 1: return # Empty figure
- # Scale the displayed image (but don't update self.figsize)
- if not self._isConfigured:
- self._isConfigured = True
-
dpival = self.figure.dpi
winch = self._width/dpival
hinch = self._height/dpival
self.figure.set_size_inches(winch, hinch)
- if self._isRealized:
- self.draw_idle()
- evt.Skip()
+ # Rendering will happen on the associated paint event
+ # so no need to do anything here except to make sure
+ # the whole background is repainted.
+ self.Refresh(eraseBackground=False)
def _get_key(self, evt):
@@ -1288,8 +1292,6 @@
for figwin in Gcf.get_all_fig_managers():
figwin.frame.Show()
- figwin.canvas.realize()
- figwin.canvas.draw()
if show._needmain and not matplotlib.is_interactive():
# start the wxPython gui event if there is not already one running
@@ -1316,7 +1318,6 @@
frame = FigureFrameWx(num, fig)
figmgr = frame.get_figure_manager()
if matplotlib.is_interactive():
- figmgr.canvas.realize()
figmgr.frame.Show()
return figmgr
@@ -1436,8 +1437,6 @@
def showfig(*args):
frame.Show()
- canvas.realize()
- canvas.draw()
# attach a show method to the figure
self.canvas.figure.show = showfig
@@ -1732,7 +1731,6 @@
except Exception, e:
error_msg_wx(str(e))
-
def set_cursor(self, cursor):
cursor =wx.StockCursor(cursord[cursor])
self.canvas.SetCursor( cursor )
@@ -1999,9 +1997,6 @@
direction = -1
self.button_fn(direction)
- def _onRedraw(self, evt):
- self.canvas.draw()
-
_onSave = NavigationToolbar2Wx.save
def _onClose(self, evt):
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py 2008-07-27 20:42:13 UTC (rev 5906)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_wxagg.py 2008-07-28 07:26:47 UTC (rev 5907)
@@ -52,7 +52,7 @@
size.
"""
- def draw(self, repaint=True):
+ def draw(self, drawDC=None):
"""
Render the figure using agg.
"""
@@ -60,8 +60,8 @@
FigureCanvasAgg.draw(self)
self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
- if repaint:
- self.gui_repaint()
+ self._isDrawn = True
+ self.gui_repaint(drawDC=drawDC)
def blit(self, bbox=None):
"""
@@ -97,8 +97,14 @@
filetypes = FigureCanvasAgg.filetypes
def print_figure(self, filename, *args, **kwargs):
+ # Use pure Agg renderer to draw
FigureCanvasAgg.print_figure(self, filename, *args, **kwargs)
- self.draw()
+ # Restore the current view; this is needed because the
+ # artist contains methods rely on particular attributes
+ # of the rendered figure for determining things like
+ # bounding boxes.
+ if self._isDrawn:
+ self.draw()
class NavigationToolbar2WxAgg(NavigationToolbar2Wx):
def get_canvas(self, frame, fig):
@@ -119,7 +125,6 @@
frame = FigureFrameWxAgg(num, fig)
figmgr = frame.get_figure_manager()
if matplotlib.is_interactive():
- figmgr.canvas.realize()
figmgr.frame.Show()
return figmgr
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|