如何在 matplotlib 小部件的嵌入式图形上使用跨度选择器?

Posted

技术标签:

【中文标题】如何在 matplotlib 小部件的嵌入式图形上使用跨度选择器?【英文标题】:How to use the Span Selector on a embedded figure of matplotlib widget? 【发布时间】:2020-06-29 21:52:45 【问题描述】:

我正在开发带有图形的系统的 GUI。

我想在我可视化的图表中使用 spanselector。

我已经搜索过了,但我不明白如何在调用 matplotlib 小部件时使用跨度选择器。

这是我要绘制的示例。它有 3 个部分(main、mplwidget、ui 文件)

主代码文件

# ------------------------------------------------------
# ---------------------- main.py -----------------------
# ------------------------------------------------------
from PyQt5.QtWidgets import*
from PyQt5.uic import loadUi

from matplotlib.backends.backend_qt5agg import (NavigationToolbar2QT as NavigationToolbar)

import numpy as np
import random

#from matplotlib.widgets import SpanSelector

class MatplotlibWidget(QMainWindow):

    def __init__(self):

        QMainWindow.__init__(self)

        loadUi("qt_designer.ui",self)

        self.setWindowTitle("PyQt5 & Matplotlib Example GUI")

        self.pushButton_generate_random_signal.clicked.connect(self.update_graph)

        self.addToolBar(NavigationToolbar(self.MplWidget.canvas, self))


    def update_graph(self):

        fs = 500
        f = random.randint(1, 100)
        ts = 1/fs
        length_of_signal = 100
        t = np.linspace(0,1,length_of_signal)

        cosinus_signal = np.cos(2*np.pi*f*t)
        sinus_signal = np.sin(2*np.pi*f*t)

        self.MplWidget.canvas.axes.clear()
        self.MplWidget.canvas.axes.plot(t, cosinus_signal)
        self.MplWidget.canvas.axes.plot(t, sinus_signal)
        self.MplWidget.canvas.axes.legend(('cosinus', 'sinus'),loc='upper right')
        self.MplWidget.canvas.axes.set_title('Cosinus - Sinus Signal')
        self.MplWidget.canvas.draw()
        #span = self.MplWidget.canvas.axes.SpanSelector(ax1, onselect, 'horizontal', useblit=True,rectprops=dict(alpha=0.5, facecolor='red'))            


    def onselect(min_value, max_value):
        print(min_value, max_value)
        return min_value, max_value         



app = QApplication([])
window = MatplotlibWidget()
window.show()
app.exec_()

mplwidget 文件

# ------------------------------------------------------
# -------------------- mplwidget.py --------------------
# ------------------------------------------------------
from PyQt5.QtWidgets import*

from matplotlib.backends.backend_qt5agg import FigureCanvas

from matplotlib.figure import Figure


class MplWidget(QWidget):

    def __init__(self, parent = None):

        QWidget.__init__(self, 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)

ui 文件附在此链接上,其中包含所有代码: here

另一方面,这是使用跨度选择器的示例代码:

import matplotlib.pyplot as plt
import matplotlib.widgets as mwidgets
fig, ax = plt.subplots()
ax.plot([1, 2, 3], [10, 50, 100])
def onselect(vmin, vmax):
     print(vmin, vmax)
rectprops = dict(facecolor='blue', alpha=0.5)
span = mwidgets.SpanSelector(ax, onselect, 'horizontal',span_stays=True,button=1,,rectprops=rectprops)
fig.show()

/////////////////////////////////////// ///////////////////////////

我尝试了很多方法来评估跨度选择器,但我对它的工作方式以及我应该如何连接代码结构有点困惑?

如果我运行 whithin 注释行: span = self.MplWidget.canvas.axes.SpanSelector(ax1, onselect, 'horizontal', useblit=True,rectprops=dict(alpha=0.5, facecolor='red'))

它显示以下错误: 属性错误:'AxesSubplot' object has no attribute 'SpanSelector'

最后,这就是想要的结果

【问题讨论】:

【参考方案1】:

您必须将self.MplWidget.canvas.axes 作为斧头传递:

    # ...
    self.MplWidget.canvas.draw()
    self.span = SpanSelector(
        self.MplWidget.canvas.axes,
        self.onselect,
        "horizontal",
        useblit=True,
        rectprops=dict(alpha=0.5, facecolor="red"),
    )

def onselect(self, min_value, max_value):
    print(min_value, max_value)

注意:由于select是类的方法,所以必须以self作为第一个参数,并且必须以self.select调用。

【讨论】:

我可以提供一个推荐的参考资料,在那里我可以找到有关如何处理方法和类以阐明结构的更多信息?它很有用,因为我要开发一个更高级的 GUI,这将有助于预测新的错误。

以上是关于如何在 matplotlib 小部件的嵌入式图形上使用跨度选择器?的主要内容,如果未能解决你的问题,请参考以下文章

如何使 FigureCanvas 在嵌入 pyqt GUI 的 matplotlib 小部件中填充整个 Figure?

Matplotlib 将图形嵌入到 UI PyQt5

如何在 PyQt4 小部件中嵌入的 Axes3D (matplotlib) 中启用旋转?

Python Tkinter 在 GUI 中嵌入 Matplotlib

Matplotlib 小部件用于由另一个 matplotlib 小部件生成的绘图

将 NetworkX 图嵌入 PyQT 小部件