matplotlib + QGraphicsView + zoom =大丑像素

时间:2016-01-18 13:16:34

标签: python matplotlib pyqt

当我放大 FigureCanvasQTAgg (一个matplotlib QWidget)时,我得到了大的像素:

初始尺寸:

Initial size

缩放(大丑像素):

Zoom

红色圆圈也是QWidget,没有缩放问题

是否可以将FigureCanvasQTAgg显示为可缩放矢量小部件

完整源代码:

import sys
from PyQt4 import QtGui
from PyQt4.Qt import Qt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import numpy as np

class Circle(QtGui.QWidget):
    def __init__(self):
        super(Circle, self).__init__()
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.resize(500, 500)

    def paintEvent(self, event):
        p = QtGui.QPainter()
        p.begin(self)
        p.setPen(QtGui.QColor(255,0,0))
        p.drawEllipse(100, 100, 300, 300)
        p.end()

class MyView(QtGui.QGraphicsView):
    def __init__(self):
        QtGui.QGraphicsView.__init__(self)

        scene = QtGui.QGraphicsScene(self)
        self.scene = scene

        figure = Figure()
        axes = figure.gca()
        axes.set_title("Use the mouse wheel to zoom")
        axes.plot(np.random.rand(5))
        canvas = FigureCanvas(figure)
        canvas.setGeometry(0, 0, 500, 500)
        scene.addWidget(canvas)

        circle = Circle()
        self.circle = circle
        scene.addWidget(circle)

        self.setScene(scene)

    def wheelEvent(self, event):
        self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
        zoom_in = 1.15
        zoom_out = 1.0 / zoom_in
        if event.delta() > 0:
            self.scale(zoom_in, zoom_in)
        else:
            self.scale(zoom_out, zoom_out)

app = QtGui.QApplication(sys.argv)
view = MyView()
view.show()
sys.exit(app.exec_())

1 个答案:

答案 0 :(得分:2)

正如HYRY所说,我非常确定matplotlib画布呈现为位图,因此无法在没有像素化的情况下进行缩放。但是,您可以使用QSvgRenderer来渲染图形的svg表示。

这是一个基于原始代码的快速而肮脏的解决方案:

import sys
from PyQt4 import QtCore, QtGui, QtSvg
from PyQt4.Qt import Qt
from matplotlib.figure import Figure
from matplotlib.backends.backend_qt4agg import FigureCanvasQTAgg as FigureCanvas
import numpy as np
import StringIO

class Circle(QtGui.QWidget):
    def __init__(self):
        super(Circle, self).__init__()
        self.setAttribute(Qt.WA_TranslucentBackground)
        self.resize(500, 500)

    def paintEvent(self, event):
        p = QtGui.QPainter()
        p.begin(self)
        p.setPen(QtGui.QColor(255,0,0))
        p.drawEllipse(100, 100, 300, 300)
        p.end()

class MPLPlot(QtGui.QWidget):
    def __init__(self):
        super(MPLPlot, self).__init__()

        figure = Figure()
        axes = figure.gca()
        axes.set_title("Use the mouse wheel to zoom")
        axes.plot(np.random.rand(5))
        canvas = FigureCanvas(figure)
        canvas.setGeometry(0, 0, 500, 500)

        imgdata = StringIO.StringIO()
        figure.savefig(imgdata, format='svg')
        imgdata.seek(0)
        xmlreader = QtCore.QXmlStreamReader(imgdata.getvalue())
        self.renderer = QtSvg.QSvgRenderer(xmlreader)

    def paintEvent(self, event):
        p = QtGui.QPainter()
        p.begin(self)
        self.renderer.render(p)
        p.end()


class MyView(QtGui.QGraphicsView):
    def __init__(self):
        QtGui.QGraphicsView.__init__(self)

        scene = QtGui.QGraphicsScene(self)
        self.scene = scene

        plot = MPLPlot()
        scene.addWidget(plot)

        circle = Circle()
        self.circle = circle
        scene.addWidget(circle)

        self.setScene(scene)

    def wheelEvent(self, event):
        self.setTransformationAnchor(QtGui.QGraphicsView.AnchorUnderMouse)
        zoom_in = 1.15
        zoom_out = 1.0 / zoom_in
        if event.delta() > 0:
            self.scale(zoom_in, zoom_in)
        else:
            self.scale(zoom_out, zoom_out)

app = QtGui.QApplication(sys.argv)
view = MyView()
view.show()
sys.exit(app.exec_())