Skip to content

Commit 4347da0

Browse files
author
Martin Fitzpatrick
committed
Implement backend for PyQt5 + modify Qt4 backend to Qt5 structure.
A backend for PyQt5 based on intial work by @badders, modified to fix Qt5 mouse event handling, then re-structured to implement as a wrapper over the existing Qt4 code. Following discussions on this pull request: matplotlib#2471 The code has been restructured to implement PyQt5 backend as a first-class implementation, with other Qt backends (PyQt4, PyQt4v2, PySide (Qt v4)) wrapping it and modifying as required. The issues of objects being moved around in the Qt namespace (many QtGui objects now in QtWidgets) QtWidgets is simply assigned as a copy of QtGui if not available. This achieves the intended outcome with the minimum code. PySide required re-ordering of import on FigureCanvasQTAgg or paintEvent function would not being called on FigureCanvasQTAggBase resulting in black window. A number of indentation, import and other fixes.
1 parent 24bc071 commit 4347da0

16 files changed

+1405
-991
lines changed

lib/matplotlib/backends/backend_qt4.py

Lines changed: 13 additions & 764 deletions
Large diffs are not rendered by default.

lib/matplotlib/backends/backend_qt4agg.py

Lines changed: 5 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414
import matplotlib
1515
from matplotlib.figure import Figure
1616

17+
from .backend_qt5agg import new_figure_manager, NavigationToolbar2QTAgg
18+
from .backend_qt5agg import FigureCanvasQTAggBase
19+
1720
from .backend_agg import FigureCanvasAgg
1821
from .backend_qt4 import QtCore
19-
from .backend_qt4 import QtGui
2022
from .backend_qt4 import FigureManagerQT
2123
from .backend_qt4 import FigureCanvasQT
2224
from .backend_qt4 import NavigationToolbar2QT
@@ -39,21 +41,19 @@ def new_figure_manager(num, *args, **kwargs):
3941
Create a new figure manager instance
4042
"""
4143
if DEBUG:
42-
print('backend_qtagg.new_figure_manager')
44+
print('backend_qt4agg.new_figure_manager')
4345
FigureClass = kwargs.pop('FigureClass', Figure)
4446
thisFig = FigureClass(*args, **kwargs)
4547
return new_figure_manager_given_figure(num, thisFig)
4648

47-
4849
def new_figure_manager_given_figure(num, figure):
4950
"""
5051
Create a new figure manager instance for the given figure.
5152
"""
5253
canvas = FigureCanvasQTAgg(figure)
5354
return FigureManagerQT(canvas, num)
5455

55-
56-
class FigureCanvasQTAgg(FigureCanvasQT, FigureCanvasAgg):
56+
class FigureCanvasQTAgg(FigureCanvasQTAggBase, FigureCanvasQT, FigureCanvasAgg):
5757
"""
5858
The canvas the figure renders into. Calls the draw and print fig
5959
methods, creates the renderers, etc...
@@ -88,110 +88,6 @@ def __init__(self, figure):
8888
else:
8989
self._priv_update = self.update
9090

91-
def drawRectangle(self, rect):
92-
self._drawRect = rect
93-
self.repaint()
94-
95-
def paintEvent(self, e):
96-
"""
97-
Copy the image from the Agg canvas to the qt.drawable.
98-
In Qt, all drawing should be done inside of here when a widget is
99-
shown onscreen.
100-
"""
101-
102-
#FigureCanvasQT.paintEvent(self, e)
103-
if DEBUG:
104-
print('FigureCanvasQtAgg.paintEvent: ', self,
105-
self.get_width_height())
106-
107-
if self.blitbox is None:
108-
# matplotlib is in rgba byte order. QImage wants to put the bytes
109-
# into argb format and is in a 4 byte unsigned int. Little endian
110-
# system is LSB first and expects the bytes in reverse order
111-
# (bgra).
112-
if QtCore.QSysInfo.ByteOrder == QtCore.QSysInfo.LittleEndian:
113-
stringBuffer = self.renderer._renderer.tostring_bgra()
114-
else:
115-
stringBuffer = self.renderer._renderer.tostring_argb()
116-
117-
refcnt = sys.getrefcount(stringBuffer)
118-
119-
# convert the Agg rendered image -> qImage
120-
qImage = QtGui.QImage(stringBuffer, self.renderer.width,
121-
self.renderer.height,
122-
QtGui.QImage.Format_ARGB32)
123-
# get the rectangle for the image
124-
rect = qImage.rect()
125-
p = QtGui.QPainter(self)
126-
# reset the image area of the canvas to be the back-ground color
127-
p.eraseRect(rect)
128-
# draw the rendered image on to the canvas
129-
p.drawPixmap(QtCore.QPoint(0, 0), QtGui.QPixmap.fromImage(qImage))
130-
131-
# draw the zoom rectangle to the QPainter
132-
if self._drawRect is not None:
133-
p.setPen(QtGui.QPen(QtCore.Qt.black, 1, QtCore.Qt.DotLine))
134-
x, y, w, h = self._drawRect
135-
p.drawRect(x, y, w, h)
136-
p.end()
137-
138-
# This works around a bug in PySide 1.1.2 on Python 3.x,
139-
# where the reference count of stringBuffer is incremented
140-
# but never decremented by QImage.
141-
# TODO: revert PR #1323 once the issue is fixed in PySide.
142-
del qImage
143-
if refcnt != sys.getrefcount(stringBuffer):
144-
_decref(stringBuffer)
145-
else:
146-
bbox = self.blitbox
147-
l, b, r, t = bbox.extents
148-
w = int(r) - int(l)
149-
h = int(t) - int(b)
150-
t = int(b) + h
151-
reg = self.copy_from_bbox(bbox)
152-
stringBuffer = reg.to_string_argb()
153-
qImage = QtGui.QImage(stringBuffer, w, h,
154-
QtGui.QImage.Format_ARGB32)
155-
pixmap = QtGui.QPixmap.fromImage(qImage)
156-
p = QtGui.QPainter(self)
157-
p.drawPixmap(QtCore.QPoint(l, self.renderer.height-t), pixmap)
158-
p.end()
159-
self.blitbox = None
160-
self._drawRect = None
161-
162-
def draw(self):
163-
"""
164-
Draw the figure with Agg, and queue a request
165-
for a Qt draw.
166-
"""
167-
# The Agg draw is done here; delaying it until the paintEvent
168-
# causes problems with code that uses the result of the
169-
# draw() to update plot elements.
170-
FigureCanvasAgg.draw(self)
171-
self._priv_update()
172-
173-
def blit(self, bbox=None):
174-
"""
175-
Blit the region in bbox
176-
"""
177-
self.blitbox = bbox
178-
l, b, w, h = bbox.bounds
179-
t = b + h
180-
self.repaint(l, self.renderer.height-t, w, h)
181-
182-
def print_figure(self, *args, **kwargs):
183-
FigureCanvasAgg.print_figure(self, *args, **kwargs)
184-
self.draw()
185-
186-
187-
class NavigationToolbar2QTAgg(NavigationToolbar2QT):
188-
def __init__(*args, **kwargs):
189-
warnings.warn('This class has been deprecated in 1.4 ' +
190-
'as it has no additional functionality over ' +
191-
'`NavigationToolbar2QT`. Please change your code to '
192-
'use `NavigationToolbar2QT` instead',
193-
mplDeprecation)
194-
NavigationToolbar2QT.__init__(*args, **kwargs)
19591

19692

19793
FigureCanvas = FigureCanvasQTAgg

0 commit comments

Comments
 (0)