Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
139 views
in Technique[技术] by (71.8m points)

python - how to track the mouse over the matplot's canvas in QWidget?

I want to track the mouse's position over a matplot's canvas in real-time.

For now, I built a MplWidget that inherits the Qwidget (act like a container), then built a canvas over it to show the plot. However, the problem is that I can only track the mouse's position in the padding area except for the canvas area.

Since my canvas inherits the matplotlib.figure that is not a QWidget, thus it doesn't have the setMouseTracking() attribute. In this way, how to resolve this issue?

I found a quite useful link How to return mouse coordinates in realtime?. However, it also suffers the same issue. When the mouse is over the label (text area), the tracking function seems to be interrupted.

my code for this class shown here:

from PyQt5.QtWidgets import *

from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas

from matplotlib.figure import Figure


class MplWidget(QWidget):

    def __init__(self, parent=None):
        # QWidget.__init__(self, parent)
        super(QWidget, self).__init__(parent)

        self.canvas = FigureCanvas(Figure())

        vertical_layout = QVBoxLayout()
        vertical_layout.addWidget(self.canvas)

        self.canvas.axes = self.canvas.figure.add_subplot(111)
        self.setLayout(vertical_layout)

        self.setMouseTracking(True)

    def mouseMoveEvent(self, e):
        text = "x: {0},  y: {1}".format(e.x(), e.y())
        print(text)
        super(MplWidget, self).mouseMoveEvent(e)

    def mousePressEvent(self, e):
        print('click!')
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As you have noticed the canvas is not handled by Qt but by matplotlib so the solution is to use the events provided by that library, if you review the docs you see that there are the following events:

Event name Class and description

'button_press_event'  MouseEvent - mouse button is pressed
'button_release_event'    MouseEvent - mouse button is released
'draw_event'  DrawEvent - canvas draw (but before screen update)
'key_press_event' KeyEvent - key is pressed
'key_release_event'   KeyEvent - key is released
'motion_notify_event' MouseEvent - mouse motion
'pick_event'  PickEvent - an object in the canvas is selected
'resize_event'    ResizeEvent - figure canvas is resized
'scroll_event'    MouseEvent - mouse scroll wheel is rolled
'figure_enter_event'  LocationEvent - mouse enters a new figure
'figure_leave_event'  LocationEvent - mouse leaves a figure
'axes_enter_event'    LocationEvent - mouse enters a new axes
'axes_leave_event'    LocationEvent - mouse leaves an axes

In your case you should use the events:

  • button_press_event
  • button_release_event
  • motion_notify_event

Example:

from PyQt5 import QtWidgets

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


class MplWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(MplWidget, self).__init__(parent)
        self.canvas = FigureCanvas(Figure())

        vertical_layout = QtWidgets.QVBoxLayout(self)
        vertical_layout.addWidget(self.canvas)

        self.canvas.axes = self.canvas.figure.add_subplot(111)

        self.canvas.mpl_connect("button_press_event", self.on_press)
        self.canvas.mpl_connect("button_release_event", self.on_release)
        self.canvas.mpl_connect("motion_notify_event", self.on_move)

    def on_press(self, event):
        print("press")
        print("event.xdata", event.xdata)
        print("event.ydata", event.ydata)
        print("event.inaxes", event.inaxes)
        print("x", event.x)
        print("y", event.y)

    def on_release(self, event):
        print("release:")
        print("event.xdata", event.xdata)
        print("event.ydata", event.ydata)
        print("event.inaxes", event.inaxes)
        print("x", event.x)
        print("y", event.y)

    def on_move(self, event):
        print("move")
        print("event.xdata", event.xdata)
        print("event.ydata", event.ydata)
        print("event.inaxes", event.inaxes)
        print("x", event.x)
        print("y", event.y)


if __name__ == "__main__":
    import sys

    app = QtWidgets.QApplication(sys.argv)
    w = MplWidget()
    w.show()
    sys.exit(app.exec_())

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...