matplotlib事件侦听器在PyQT Widg中不起作用

2024-10-03 06:26:56 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个可拖动的matplotlib对象库,我正试图在pyqt5gui中使用这些对象。对象的event listeners在独立的matplotlib图形窗口中正常工作,但当图形嵌入QT小部件中时不起作用。当我试图在QT小部件中拖动补丁时,这两个图都能正确呈现,并且没有错误消息。在

对象MCVE:

import matplotlib.patches as patches

class _DragObj:
    def __init__(self, ax):
        self.parentcanvas = ax.figure.canvas
        self.parentax = ax

        self.clickpress = self.parentcanvas.mpl_connect('button_press_event', self.on_click)
        self.clicked = False

    def on_click(self, event):
        if event.inaxes != self.parentax: return

        self.mousemotion = self.parentcanvas.mpl_connect('motion_notify_event', self.on_motion)
        self.clickrelease = self.parentcanvas.mpl_connect('button_release_event', self.on_release)

        self.clickx = event.xdata  
        self.clicky = event.ydata

        self.clicked = True

    def on_release(self, event):
        self.clicked = False
        self.disconnect()

    def disconnect(self):
        self.parentcanvas.mpl_disconnect(self.mousemotion)
        self.parentcanvas.mpl_disconnect(self.clickrelease)
        self.parentcanvas.draw()

    def stopdrag(self):
        self.myobj.set_url('')
        self.parentcanvas.mpl_disconnect(self.clickpress)

class _DragPatch(_DragObj):
    def __init__(self, ax, xy):
        super().__init__(ax)

        self.oldxy = xy

    def on_motion(self, event):
        if not self.clicked: return
        if event.inaxes != self.parentax: return

        oldx, oldy = self.oldxy
        dx = event.xdata - self.clickx
        dy = event.ydata - self.clicky
        newxy = [oldx + dx, oldy + dy]
        self.myobj.xy = newxy

        self.parentcanvas.draw()

    def on_release(self, event):
        self.clicked = False
        self.oldxy = self.myobj.xy

        self.disconnect()

class DragRectangle(_DragPatch):
    def __init__(self, ax, xy, width, height, angle=0.0, **kwargs):
        self.myobj = patches.Rectangle(xy, width, height, angle, **kwargs)
        ax.add_artist(self.myobj)

        super().__init__(ax, xy)

matplotlib功能示例:

^{pr2}$

非功能PyQT示例:

import sys
from PyQt5 import QtWidgets as QtW
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
from matplotlib.figure import Figure
import minidrag

class windowGUI(QtW.QDialog):
    def __init__(self):
        super().__init__()

        # Set up figure
        width_px = 800
        height_px = 600

        rect = QtW.QDesktopWidget().availableGeometry()
        screenrez = (rect.width(), rect.height())
        left_px = (screenrez[0] - width_px)/2
        top_px = (screenrez[1] - height_px)/2
        self.setGeometry(left_px, top_px, width_px, height_px)
        self.canvas = PlotCanvas()

        layout = QtW.QVBoxLayout()
        layout.addWidget(NavigationToolbar(self.canvas, self))
        layout.addWidget(self.canvas)
        self.setLayout(layout)

class PlotCanvas(FigureCanvas):
    def __init__(self):
        fig = Figure(frameon=False)
        super().__init__(fig)
        super().setSizePolicy(QtW.QSizePolicy.Expanding, QtW.QSizePolicy.Expanding)
        super().updateGeometry()

        ax = fig.add_subplot(111)
        rect = minidrag.DragRectangle(ax, (0, 0), 2, 1)

        ax.set_xlim(-5, 5)
        ax.set_ylim(-5, 5)

app = QtW.QApplication(sys.argv)
window = windowGUI()
window.show()
sys.exit(app.exec_())

我使用的是python3.6.0、matplotlib(2.0.0)和PyQt5(5.8)

我错过了什么?在


Tags: importselfeventmatplotlibinitondefax
1条回答
网友
1楼 · 发布于 2024-10-03 06:26:56

结果发现问题不是拖动事件,而是你的minidrag.DragRectangle实例正在被垃圾回收(而画布仍显示矩形在其原始位置)。在

作为解决方案,可以将矩形设置为实例变量:

self.rect = minidrag.DragRectangle(ax, (0, 0), 2, 1)

(用Python2.7和PyQt4测试。)

相关问题 更多 >