【问题标题】:Transformation of coordinates between PyQt and matplotlibPyQt 和 matplotlib 之间的坐标转换
【发布时间】:2020-11-27 21:15:39
【问题描述】:

我想在鼠标点击的位置显示一个上下文菜单,然后在图表中的该位置创建一条新线。

为此,我需要 PyQt 位置和图形数据位置。我以为我可以使用 matplotlib 转换函数,但不知何故,当单击图形的左下角和右上角时,我得到打印值 [-0.34, 30.73], [3.02, -1.49] 而不是 ~[-0.3 , -0.9], ~[4.3, 42]。

谁能修正我在代码中犯的错误?

附:我知道我可以连接一个 matplotlib 信号并获得正确的数据位置。但是我需要将这些位置转换为 PyQt 位置才能正确放置小部件,从而导致同样的问题。

遵循简化的代码:

import sys
import matplotlib
matplotlib.use('Qt5Agg')

from PyQt5 import QtCore, QtWidgets

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure

class MplCanvas(FigureCanvasQTAgg):
    def __init__(self, parent=None, width=5, height=4, dpi=100):
        fig = Figure(figsize=(width, height), dpi=dpi)
        self.axes = fig.add_subplot(111)
        super(MplCanvas, self).__init__(fig)

        self._menuPoint = None
        self.canvasMenu = QtWidgets.QMenu(self)
        ca = QtWidgets.QAction('Add line', self)
        ca.triggered.connect(self.onAddLineClicked)
        self.canvasMenu.addAction(ca)

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        self._menuPoint = event.pos()
        print(self.axes.transData.inverted().transform((self._menuPoint.x(), self._menuPoint.y())))
        if event.button() == QtCore.Qt.RightButton:
            self.canvasMenu.exec_(self.mapToGlobal(self._menuPoint))

    def onAddLineClicked(self):
        pass


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self, *args, **kwargs):
        super(MainWindow, self).__init__(*args, **kwargs)
        sc = MplCanvas(self)
        sc.axes.plot([0, 1, 2, 3, 4], [10, 1, 20, 3, 40])
        self.setCentralWidget(sc)
        self.show()


app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
app.exec_()

谢谢。

【问题讨论】:

    标签: python matplotlib pyqt5


    【解决方案1】:

    QMouseEvent.pos()返回的坐标在[0 – widget width][0 - widget height]之间,而图形坐标在[0-1]之间。因此,您需要将鼠标 pos() 除以小部件的宽度和高度。还有一个微妙之处是Qt坐标是从左上角开始的,而matplotlib坐标是从左下角开始的。

    在图形坐标中确定位置后,将它们转换为数据坐标相对简单。您还可以将它们转换为 Axes 坐标以测试点击是否在轴内。

    def mouseReleaseEvent(self, event):
        super().mouseReleaseEvent(event)
        self._menuPoint = event.pos()
        w, h = self.get_width_height()
        xfig = event.x()/w
        yfig = 1-(event.y()/h)  # necessary because Qt coordinates are from upper left, while matplotlib's are from
                                # lower left
        x, y = self.axes.transData.inverted().transform(self.fig.transFigure.transform([xfig, yfig]))
        print(event.pos(), x, y)
        if event.button() == QtCore.Qt.RightButton:
            self.canvasMenu.exec_(self.mapToGlobal(self._menuPoint))
    

    【讨论】:

      猜你喜欢
      • 2019-10-08
      • 1970-01-01
      • 1970-01-01
      • 2014-01-22
      • 1970-01-01
      • 1970-01-01
      • 2015-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多