Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6f27cd6

Browse files
author
Steve Chaplin
committed
*** empty log message ***
svn path=/trunk/matplotlib/; revision=898
1 parent 13459e4 commit 6f27cd6

1 file changed

Lines changed: 341 additions & 0 deletions

File tree

Lines changed: 341 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,341 @@
1+
"""
2+
backend_qtagg.py version 0.0.1
3+
http://www.tjora.no/python/matplotlib/qtaggbackend
4+
5+
This is a not very tested matplotlib qt-backend that uses the
6+
Agg-backend for rendering etc.
7+
8+
Tested on Windows with
9+
python 2.3.4
10+
matplotlib 0.70.1
11+
PyQt-3.11-040518-Python23
12+
13+
It does not work in IPython interactive mode, and will therefore raise
14+
an Exception if that is tried. I suppose that IPython must be changed
15+
to support a Qt main loop in a thread for this to work ok.
16+
17+
Problems:
18+
Should FigureManagerQtAgg.destroy do anything?
19+
20+
REQUIREMENTS
21+
22+
PyQt of some unknown version. Does not require anything but a basic Qt,
23+
that is no Enterprise version etc. (Uses QWidget, and not QCanvas)
24+
25+
Copyright (C) Sigve Tjora, 2005
26+
27+
License: This work is licensed under the matplotlib license( PSF
28+
compatible). A copy should be included with this source code.
29+
30+
"""
31+
32+
from __future__ import division
33+
34+
import sys
35+
from matplotlib import verbose
36+
from matplotlib._pylab_helpers import Gcf
37+
from matplotlib.backend_bases import RendererBase, GraphicsContextBase,\
38+
FigureManagerBase, FigureCanvasBase, error_msg, NavigationToolbar2
39+
40+
from matplotlib.cbook import enumerate
41+
from matplotlib.figure import Figure
42+
from matplotlib.transforms import Bbox
43+
import matplotlib
44+
from backend_agg import RendererAgg, FigureCanvasAgg
45+
import qt
46+
import os.path
47+
48+
def error_msg_qtagg(msg, *args):
49+
"""
50+
Signal an error condition.
51+
- in a GUI backend, popup a error dialog.
52+
- in a non-GUI backend delete this function and use
53+
'from matplotlib.backend_bases import error_msg'
54+
"""
55+
makeSureWeHaveAQApp()
56+
qt.QMessageBox.warning(None, "Matplotlib", msg, qt.QMessageBox.Ok)
57+
raise SystemExit
58+
59+
60+
61+
########################################################################
62+
#
63+
# The following functions and classes are for pylab and implement
64+
# window/figure managers, etc...
65+
#
66+
########################################################################
67+
68+
def draw_if_interactive():
69+
"""
70+
For image backends - is not required
71+
For GUI backends - this should be overriden if drawing should be done in
72+
interactive python mode
73+
"""
74+
if matplotlib.is_interactive():
75+
raise NotImplementedError("Interactive drawing not supported on Qt-backend.")
76+
#figManager = Gcf.get_active()
77+
#if figManager != None:
78+
#figManager.canvas.draw()
79+
80+
def show(mainloop = True):
81+
"""
82+
For image backends - is not required
83+
For GUI backends - show() is usually the last line of a pylab script and
84+
tells the backend that it is time to draw. In interactive mode, this may
85+
be a do nothing func. See the GTK backend for an example of how to handle
86+
interactive versus batch mode
87+
"""
88+
for manager in Gcf.get_all_fig_managers():
89+
# do something to display the GUI
90+
manager.window.show()
91+
if mainloop:
92+
qt.qApp.connect(qt.qApp, qt.SIGNAL("lastWindowClosed()")
93+
, qt.qApp
94+
, qt.SLOT("quit()")
95+
)
96+
qt.qApp.exec_loop()
97+
98+
def new_figure_manager(num, *args, **kwargs):
99+
"""
100+
Create a new figure manager instance
101+
"""
102+
makeSureWeHaveAQApp()
103+
thisFig = Figure(*args, **kwargs)
104+
window = qt.QMainWindow()
105+
canvas = FigureCanvasQtAgg(thisFig, window)
106+
if matplotlib.rcParams['toolbar']=='toolbar2':
107+
toolbar = NavigationToolbar2QtAgg(canvas, window)
108+
else:
109+
toolbar = None
110+
manager = FigureManagerQtAgg(canvas, num, window, toolbar)
111+
window.resize(qt.QSize(600,483).expandedTo(window.minimumSizeHint()))
112+
window.clearWState(qt.Qt.WState_Polished)
113+
return manager
114+
115+
116+
class FigureCanvasQtAgg(qt.QWidget, FigureCanvasAgg):
117+
"""
118+
The canvas the figure renders into. Calls the draw and print fig
119+
methods, creates the renderers, etc...
120+
121+
Public attribute
122+
123+
figure - A Figure instance
124+
125+
Note GUI templates will want to connect events for button presses,
126+
mouse movements and key presses to functions that call the base
127+
class methods button_press_event, button_release_event,
128+
motion_notify_event, key_press_event, and key_release_event. See,
129+
eg backend_gtk.py, backend_wx.py and backend_tkagg.py
130+
"""
131+
def __init__(self, figure, window):
132+
qt.QWidget.__init__(self, window)
133+
FigureCanvasAgg.__init__(self, figure)
134+
self.buffer = qt.QPixmap()
135+
136+
#Coordinates of the select rectangle if it is needed.
137+
self.rect = None
138+
139+
def draw(self):
140+
"""
141+
Draw the figure using the renderer
142+
"""
143+
FigureCanvasAgg.draw(self)
144+
self.stringBuffer = str(self.buffer_rgba())
145+
self.qimage = qt.QImage(self.stringBuffer,
146+
self.renderer.width,
147+
self.renderer.height,
148+
32,
149+
None,
150+
0,
151+
qt.QImage.IgnoreEndian)
152+
self.update()
153+
154+
def paintEvent(self, ev):
155+
self.buffer.convertFromImage(self.qimage, qt.Qt.OrderedAlphaDither)
156+
if self.rect:
157+
self.p = qt.QPainter()
158+
self.p.pen().setStyle(qt.QPen.DotLine)
159+
self.p.begin(self.buffer)
160+
x0,y0, x1,y1 = self.rect
161+
self.p.drawRect(x0,y0, x1-x0, y1-y0)
162+
self.p.flush()
163+
self.p.end()
164+
# blit the pixmap to the widget
165+
qt.bitBlt(self, 0, 0, self.buffer)
166+
167+
def resizeEvent(self, ev):
168+
width, height = ev.size().width(), ev.size().height()
169+
170+
# compute desired figure size in inches
171+
dpival = self.figure.dpi.get()
172+
winch = width/dpival
173+
hinch = height/dpival
174+
self.figure.set_figsize_inches(winch, hinch)
175+
176+
self.draw()
177+
178+
#Events to pass on to matplotlib
179+
def keyPressEvent(self, ev):
180+
self.keyPressEvent(ev.text())
181+
def keyReleaseEvent(self, ev):
182+
self.keyReleaseEvent(ev.text())
183+
def mouseMoveEvent(self, ev):
184+
x, y = self.getMatplotlibCoord(ev)
185+
self.motion_notify_event(x, y)
186+
def mousePressEvent(self, ev):
187+
x, y = self.getMatplotlibCoord(ev)
188+
self.button_press_event(x, y, self.get_matlab_button(ev))
189+
def mouseReleaseEvent(self, ev):
190+
x, y = self.getMatplotlibCoord(ev)
191+
self.button_release_event(x, y, self.get_matlab_button(ev))
192+
def get_matlab_button(self, ev):
193+
b = ev.button()
194+
if b == qt.QMouseEvent.NoButton:
195+
return None
196+
elif b == qt.QMouseEvent.LeftButton:
197+
return 1
198+
elif b == qt.QMouseEvent.MidButton:
199+
return 2
200+
elif b == qt.QMouseEvent.RightButton:
201+
return 3
202+
else:
203+
return None
204+
def getMatplotlibCoord(self, ev):
205+
x = ev.x()
206+
y = self.height() - ev.y()
207+
return x,y
208+
def print_figure(self, filename, dpi=150,
209+
facecolor='w', edgecolor='w',
210+
orientation='portrait'):
211+
212+
agg = self.switch_backends(FigureCanvasAgg)
213+
agg.print_figure(filename, dpi, facecolor, edgecolor, orientation)
214+
215+
class NavigationToolbar2QtAgg(NavigationToolbar2, qt.QToolBar):
216+
"""
217+
Public attriubutes
218+
219+
canvas - the FigureCanvas (qt.QWidget)
220+
window - the qt.QMainWindow
221+
"""
222+
def __init__(self, canvas, window):
223+
qt.QToolBar.__init__(self, qt.QString(""), window, qt.Qt.DockTop)
224+
self.canvas = canvas
225+
self.window = window
226+
NavigationToolbar2.__init__(self, canvas)
227+
228+
def _init_toolbar(self):
229+
self.window.statusBar()
230+
231+
basedir = matplotlib.rcParams['datapath']
232+
233+
self.imageHome = qt.QPixmap(os.path.join(basedir, "home.png"))
234+
self.imageBack = qt.QPixmap(os.path.join(basedir, "back.png"))
235+
self.imageForward = qt.QPixmap(os.path.join(basedir, "forward.png"))
236+
self.imageMove = qt.QPixmap(os.path.join(basedir, "move.png"))
237+
self.imageSave = qt.QPixmap(os.path.join(basedir, "filesave.png"))
238+
self.imageZoom = qt.QPixmap(os.path.join(basedir, "zoom_to_rect.png"))
239+
240+
self.homeAction = qt.QAction(self,"homeAction")
241+
self.homeAction.setIconSet(qt.QIconSet(self.imageHome))
242+
self.backAction = qt.QAction(self,"backAction")
243+
self.backAction.setIconSet(qt.QIconSet(self.imageBack))
244+
self.forwardAction = qt.QAction(self,"forwardAction")
245+
self.forwardAction.setIconSet(qt.QIconSet(self.imageForward))
246+
self.moveAction = qt.QAction(self,"moveAction")
247+
self.moveAction.setIconSet(qt.QIconSet(self.imageMove))
248+
self.zoomAction = qt.QAction(self,"zoomAction")
249+
self.zoomAction.setIconSet(qt.QIconSet(self.imageZoom))
250+
self.fileSaveAction = qt.QAction(self,"fileSaveAction")
251+
self.fileSaveAction.setIconSet(qt.QIconSet(self.imageSave))
252+
253+
self.homeAction.addTo(self)
254+
self.backAction.addTo(self)
255+
self.forwardAction.addTo(self)
256+
self.moveAction.addTo(self)
257+
self.zoomAction.addTo(self)
258+
self.fileSaveAction.addTo(self)
259+
260+
self.connect(self.fileSaveAction,qt.SIGNAL("activated()"),self.save_figure)
261+
self.connect(self.backAction,qt.SIGNAL("activated()"),self.back)
262+
self.connect(self.forwardAction,qt.SIGNAL("activated()"),self.forward)
263+
self.connect(self.homeAction,qt.SIGNAL("activated()"),self.home)
264+
self.connect(self.moveAction,qt.SIGNAL("activated()"),self.pan)
265+
self.connect(self.zoomAction,qt.SIGNAL("activated()"),self.zoom)
266+
267+
self.setCaption("Navigation toolbar")
268+
self.homeAction.setText("Home")
269+
self.homeAction.setMenuText("Home")
270+
self.backAction.setText("Back")
271+
self.backAction.setMenuText("Back")
272+
self.forwardAction.setText("Forward")
273+
self.forwardAction.setMenuText("Forward")
274+
self.moveAction.setText("Move / pan")
275+
self.moveAction.setMenuText("Move / pan")
276+
self.zoomAction.setText("Zoom")
277+
self.zoomAction.setMenuText("Zoom")
278+
self.fileSaveAction.setText("Save figure")
279+
self.fileSaveAction.setMenuText("Save figure")
280+
281+
def set_message(self, s):
282+
self.window.statusBar().message(s)
283+
284+
def save_figure(self):
285+
s = qt.QFileDialog.getSaveFileName("",
286+
"Images (*.png *.xpm *.jpg)",
287+
self.window,
288+
"save file dialog"
289+
"Choose a filename to save figure under" )
290+
if s:
291+
self.canvas.print_figure(str(s))
292+
293+
def draw_rubberband(self, event, x0, y0, x1, y1):
294+
height = self.canvas.figure.bbox.height()
295+
y0 = height-y0
296+
y1 = height-y1
297+
self.canvas.rect = (x0, y0, x1, y1)
298+
self.canvas.update()
299+
300+
def release(self, event):
301+
self.canvas.rect = None
302+
303+
304+
class FigureManagerQtAgg(FigureManagerBase):
305+
"""
306+
Wrap everything up into a window for the pylab interface
307+
308+
For non interactive backends, the base class does all the work
309+
"""
310+
def __init__(self, canvas, num, window, toolbar):
311+
FigureManagerBase.__init__(self, canvas, num)
312+
self.window = window
313+
self.window.setCaption("Figure %d" % num)
314+
self.window.setCentralWidget(self.canvas)
315+
self.toolbar = toolbar
316+
317+
# def destroy(self, *args):
318+
# print "destroy figure manager"
319+
# self.window.hide()
320+
321+
########################################################################
322+
#
323+
# Now just provide the standard names that backend.__init__ is expecting
324+
#
325+
########################################################################
326+
327+
def makeSureWeHaveAQApp():
328+
"""This have to be seperated, so if the classes are used in
329+
in a program with another QApplication instance, we use that
330+
one instead.
331+
"""
332+
global myQtApp
333+
try:
334+
#Detect if a qApp exists.
335+
n = qt.qApp.name()
336+
except RuntimeError:
337+
myQtApp = qt.QApplication([])
338+
339+
FigureManager = FigureManagerQtAgg
340+
error_msg = error_msg_qtagg
341+

0 commit comments

Comments
 (0)