Skip to content

Commit 5f48b14

Browse files
committed
applied wx blit patch # 1275002
svn path=/trunk/matplotlib/; revision=1680
1 parent 76822d9 commit 5f48b14

File tree

9 files changed

+766
-60
lines changed

9 files changed

+766
-60
lines changed

CHANGELOG

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
New entries should be added at the top
22

3+
4+
2005-08-29 Committed Ken's wx blit patch #1275002
5+
36
2005-08-26 colorbar modifications - now uses contourf instead of imshow
47
so that colors used by contourf are displayed correctly.
58
Added two new keyword args (cspacing and clabels) that are

examples/animation_blit_wx.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# For detailed comments on animation and the techniqes used here, see
2+
# the wiki entry
3+
# http://www.scipy.org/wikis/topical_software/MatplotlibAnimation
4+
import matplotlib
5+
matplotlib.use('WXAgg')
6+
matplotlib.rcParams['toolbar'] = None
7+
8+
import wx
9+
import sys
10+
import pylab as p
11+
import matplotlib.numerix as nx
12+
import time
13+
14+
15+
# allow the user to disable the WXAgg accelerator from the command line
16+
if '--no-accel' in sys.argv:
17+
import matplotlib.backends.backend_wxagg
18+
matplotlib.backends.backend_wxagg._use_accelerator(False)
19+
20+
21+
ax = p.subplot(111)
22+
canvas = ax.figure.canvas
23+
24+
25+
# create the initial line
26+
x = nx.arange(0,2*nx.pi,0.01)
27+
line, = p.plot(x, nx.sin(x), animated=True, lw=2)
28+
29+
# for profiling
30+
tstart = time.time()
31+
blit_time = 0.0
32+
33+
def update_line(*args):
34+
global blit_time
35+
36+
if update_line.background is None:
37+
update_line.background = canvas.copy_from_bbox(ax.bbox)
38+
39+
# restore the clean slate background
40+
canvas.restore_region(update_line.background)
41+
# update the data
42+
line.set_ydata(nx.sin(x+update_line.cnt/10.0))
43+
# just draw the animated artist
44+
ax.draw_artist(line)
45+
# just redraw the axes rectangle
46+
47+
t = time.time()
48+
canvas.blit(ax.bbox)
49+
blit_time += time.time() - t
50+
51+
if update_line.cnt==200:
52+
# print the timing info and quit
53+
frame_time = time.time() - tstart
54+
print '200 frames: %.2f seconds' % frame_time
55+
print '200 blits: %.2f seconds' % blit_time
56+
print
57+
print 'FPS: %.2f' % (200/frame_time)
58+
print 'BPS: %.2f' % (200/blit_time)
59+
sys.exit()
60+
61+
update_line.cnt += 1
62+
wx.WakeUpIdle()
63+
64+
update_line.cnt = 0
65+
update_line.background = None
66+
wx.EVT_IDLE(wx.GetApp(), update_line)
67+
p.show()

lib/matplotlib/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@
143143
from __future__ import generators
144144

145145

146-
__version__ = '0.84cvs1'
146+
__version__ = '0.84.cvs.2'
147147
__revision__ = '$Revision$'
148148
__date__ = '$Date$'
149149

@@ -928,7 +928,7 @@ def rcdefaults():
928928
_knownBackends = {
929929
'Agg2':1, 'Agg':1, 'Cairo':1, 'CocoaAgg':1, 'FltkAgg':1, 'GD':1, 'GDK':1,
930930
'GTK':1, 'GTKAgg':1, 'GTKCairo':1, 'Paint':1, 'PS':1, 'LaTeX':1, 'QtAgg':1,
931-
'SVG':1, 'Template':1, 'TkAgg':1, 'WX':1, 'WXAgg':1, }
931+
'SVG':1, 'Template':1, 'TkAgg':1, 'WX':1, 'WXAgg':1, 'WXGLAgg':1,}
932932

933933

934934
known = _knownBackends.keys()

lib/matplotlib/backends/backend_wx.py

Lines changed: 13 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -890,15 +890,16 @@ def Printer_Print(self, event=None):
890890
self.gui_repaint()
891891

892892

893-
def draw(self):
893+
def draw(self, repaint=True):
894894
"""
895895
Render the figure using RendererWx instance renderer, or using a
896896
previously defined renderer if none is specified.
897897
"""
898898
DEBUG_MSG("draw()", 1, self)
899899
self.renderer = RendererWx(self.bitmap, self.figure.dpi)
900900
self.figure.draw(self.renderer)
901-
self.gui_repaint()
901+
if repaint:
902+
self.gui_repaint()
902903

903904
def _get_imagesave_wildcards(self):
904905
'return the wildcard string for the filesave dialog'
@@ -911,16 +912,17 @@ def _get_imagesave_wildcards(self):
911912
"PNG (*.png)|*.png|" \
912913
"XPM (*.xpm)|*.xpm"
913914

914-
def gui_repaint(self):
915+
def gui_repaint(self, drawDC=None):
915916
"""
916-
Performs update of the displayed image on the GUI canvas
917-
918-
MUST NOT be called during a Paint event
917+
Performs update of the displayed image on the GUI canvas, using the
918+
supplied device context. If drawDC is None, a ClientDC will be used to
919+
redraw the image.
919920
"""
920921
DEBUG_MSG("gui_repaint()", 1, self)
921-
drawDC=wx.ClientDC(self)
922+
if drawDC is None:
923+
drawDC=wx.ClientDC(self)
924+
922925
drawDC.BeginDrawing()
923-
#drawDC.Clear()
924926
drawDC.DrawBitmap(self.bitmap, 0, 0)
925927
drawDC.EndDrawing()
926928

@@ -1043,27 +1045,9 @@ def _onPaint(self, evt):
10431045
if not self._isRealized:
10441046
self.realize()
10451047
# Render to the bitmap
1046-
self.draw()
1047-
# Must use wxPaintDC during paint event
1048-
1049-
l,b,w,h = self.figure.bbox.get_bounds()
1050-
w = int(math.ceil(w))
1051-
h = int(math.ceil(h))
1052-
1053-
1054-
# I decoupled this from GraphicsContextWx so it would play
1055-
# nice with wxagg
1056-
memDC =wx.MemoryDC()
1057-
memDC.SelectObject(self.bitmap)
1058-
memDC.SetPen(wx.Pen('BLACK', 1, wx.SOLID))
1059-
1060-
drawDC=wx.PaintDC(self)
1061-
1062-
drawDC.BeginDrawing()
1063-
drawDC.Clear()
1064-
drawDC.Blit(0, 0, w, h, memDC, 0, 0)
1065-
#drawDC.DrawBitmap(self.bitmap, 0, 0)
1066-
drawDC.EndDrawing()
1048+
self.draw(repaint=False)
1049+
# Update the display using a PaintDC
1050+
self.gui_repaint(drawDC=wx.PaintDC(self))
10671051
evt.Skip()
10681052

10691053
def _onSize(self, evt):

lib/matplotlib/backends/backend_wxagg.py

Lines changed: 142 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,33 @@
11
from __future__ import division
22
"""
33
4-
backend_wx.py
4+
backend_wxagg.py
55
66
A wxPython backend for Agg. This uses the GUI widgets written by
77
Jeremy O'Donoghue (jeremy@o-donoghue.com) and the Agg backend by John
88
Hunter (jdhunter@ace.bsd.uchicago.edu)
99
10-
Copyright (C) Jeremy O'Donoghue & John Hunter, 2003-4
10+
Copyright (C) 2003-4 Jeremy O'Donoghue & John Hunter
11+
Copyright (C) 2005 Illinois Institute of Technology
1112
1213
License: This work is licensed under the matplotlib license( PSF
1314
compatible). A copy should be included with this source code.
1415
1516
"""
1617

17-
import sys, os, os.path, math, StringIO
18-
from backend_agg import FigureCanvasAgg
19-
20-
from backend_wx import FigureManager
21-
from backend_wx import FigureManagerWx, FigureCanvasWx, FigureFrameWx, \
22-
DEBUG_MSG, NavigationToolbar2Wx
23-
from backend_wx import error_msg_wx, draw_if_interactive, show, Toolbar, \
24-
backend_version
25-
import backend_wx
26-
27-
from matplotlib.figure import Figure
28-
from matplotlib import rcParams
29-
import matplotlib
3018
import wx
19+
import matplotlib
20+
from matplotlib.figure import Figure
21+
from matplotlib.transforms import Bbox, Point, Value
3122

23+
from backend_agg import FigureCanvasAgg
24+
import backend_wx
25+
from backend_wx import FigureManager, FigureManagerWx, FigureCanvasWx, \
26+
FigureFrameWx, DEBUG_MSG, NavigationToolbar2Wx, error_msg_wx, \
27+
draw_if_interactive, show, Toolbar, backend_version
3228

3329

3430
class FigureFrameWxAgg(FigureFrameWx):
35-
3631
def get_canvas(self, fig):
3732
return FigureCanvasWxAgg(self, -1, fig)
3833

@@ -45,7 +40,7 @@ def _get_toolbar(self, statbar):
4540
else:
4641
toolbar = None
4742
return toolbar
48-
43+
4944
class FigureCanvasWxAgg(FigureCanvasWx,FigureCanvasAgg):
5045
"""
5146
The FigureCanvas contains the figure and does event handling.
@@ -57,21 +52,47 @@ class FigureCanvasWxAgg(FigureCanvasWx,FigureCanvasAgg):
5752
size.
5853
"""
5954

60-
61-
def draw(self):
55+
def draw(self, repaint=True):
6256
"""
63-
Render the figure using agg
57+
Render the figure using agg.
6458
"""
6559
DEBUG_MSG("draw()", 1, self)
6660
FigureCanvasAgg.draw(self)
67-
s = self.tostring_rgb()
68-
w = int(self.renderer.width)
69-
h = int(self.renderer.height)
70-
image = wx.EmptyImage(w,h)
71-
image.SetData(s)
72-
self.bitmap = image.ConvertToBitmap()
61+
62+
self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
63+
if repaint:
64+
self.gui_repaint()
65+
66+
def blit(self, bbox=None):
67+
"""
68+
Transfer the region of the agg buffer defined by bbox to the display.
69+
If bbox is None, the entire buffer is transferred.
70+
"""
71+
if bbox is None:
72+
self.bitmap = _convert_agg_to_wx_bitmap(self.get_renderer(), None)
73+
self.gui_repaint()
74+
return
75+
76+
l, b, w, h = bbox.get_bounds()
77+
r = l + w
78+
t = b + h
79+
x = int(l)
80+
y = int(self.bitmap.GetHeight() - t)
81+
82+
srcBmp = _convert_agg_to_wx_bitmap(self.get_renderer(), bbox)
83+
srcDC = wx.MemoryDC()
84+
srcDC.SelectObject(srcBmp)
85+
86+
destDC = wx.MemoryDC()
87+
destDC.SelectObject(self.bitmap)
88+
89+
destDC.BeginDrawing()
90+
destDC.Blit(x, y, w, h, srcDC, 0, 0)
91+
destDC.EndDrawing()
92+
93+
destDC.SelectObject(wx.NullBitmap)
94+
srcDC.SelectObject(wx.NullBitmap)
7395
self.gui_repaint()
74-
7596

7697
def print_figure(self, filename, dpi=150, facecolor='w',
7798
edgecolor='w', orientation='portrait'):
@@ -96,6 +117,7 @@ class NavigationToolbar2WxAgg(NavigationToolbar2Wx):
96117
def get_canvas(self, frame, fig):
97118
return FigureCanvasWxAgg(frame, -1, fig)
98119

120+
99121
def new_figure_manager(num, *args, **kwargs):
100122
"""
101123
Create a new figure manager instance
@@ -119,3 +141,96 @@ def new_figure_manager(num, *args, **kwargs):
119141
return figmgr
120142

121143

144+
#
145+
# agg/wxPython image conversion functions
146+
#
147+
148+
def _py_convert_agg_to_wx_image(agg, bbox):
149+
"""
150+
Convert the region of the agg buffer bounded by bbox to a wx.Image. If
151+
bbox is None, the entire buffer is converted.
152+
153+
Note: agg must be a backend_agg.RendererAgg instance.
154+
"""
155+
wPx = agg.width
156+
hPx = agg.height
157+
image = wx.EmptyImage(wPx, hPx)
158+
image.SetData(agg.tostring_rgb())
159+
160+
if bbox is None:
161+
# agg => rgb -> image
162+
return image
163+
else:
164+
# agg => rgb -> image => bitmap => clipped bitmap => image
165+
return wx.ImageFromBitmap(_clipped_image_as_bitmap(image, bbox))
166+
167+
168+
def _py_convert_agg_to_wx_bitmap(agg, bbox):
169+
"""
170+
Convert the region of the agg buffer bounded by bbox to a wx.Bitmap. If
171+
bbox is None, the entire buffer is converted.
172+
173+
Note: agg must be a backend_agg.RendererAgg instance.
174+
"""
175+
if bbox is None:
176+
# agg => rgb -> image => bitmap
177+
return wx.BitmapFromImage(_py_convert_agg_to_wx_image(agg, None))
178+
else:
179+
# agg => rgb -> image => bitmap => clipped bitmap
180+
return _clipped_image_as_bitmap(
181+
_py_convert_agg_to_wx_image(agg, None),
182+
bbox)
183+
184+
185+
def _clipped_image_as_bitmap(image, bbox):
186+
"""
187+
Convert the region of a wx.Image described by bbox to a wx.Bitmap.
188+
"""
189+
l, b, width, height = bbox.get_bounds()
190+
r = l + width
191+
t = b + height
192+
193+
srcBmp = wx.BitmapFromImage(image)
194+
srcDC = wx.MemoryDC()
195+
srcDC.SelectObject(srcBmp)
196+
197+
destBmp = wx.EmptyBitmap(width, height)
198+
destDC = wx.MemoryDC()
199+
destDC.SelectObject(destBmp)
200+
201+
destDC.BeginDrawing()
202+
x = int(l)
203+
y = int(image.GetHeight() - t)
204+
destDC.Blit(0, 0, width, height, srcDC, x, y)
205+
destDC.EndDrawing()
206+
207+
srcDC.SelectObject(wx.NullBitmap)
208+
destDC.SelectObject(wx.NullBitmap)
209+
210+
return destBmp
211+
212+
213+
def _use_accelerator(state):
214+
"""
215+
Enable or disable the WXAgg accelerator, if it is present.
216+
"""
217+
global _convert_agg_to_wx_image
218+
global _convert_agg_to_wx_bitmap
219+
220+
if state and _wxagg is not None:
221+
_convert_agg_to_wx_image = _wxagg.convert_agg_to_wx_image
222+
_convert_agg_to_wx_bitmap = _wxagg.convert_agg_to_wx_bitmap
223+
else:
224+
_convert_agg_to_wx_image = _py_convert_agg_to_wx_image
225+
_convert_agg_to_wx_bitmap = _py_convert_agg_to_wx_bitmap
226+
227+
228+
# try to load the WXAgg accelerator
229+
try:
230+
import _wxagg
231+
except ImportError:
232+
_wxagg = None
233+
234+
# if it's present, use it
235+
_use_accelerator(True)
236+

0 commit comments

Comments
 (0)