亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何在 pyqt5 中使 matplotlib 繪圖具有交互性

如何在 pyqt5 中使 matplotlib 繪圖具有交互性

慕田峪9158850 2023-03-08 15:14:21
背景我目前正在從事一個項目,我想將 matplotlib 圖嵌入到 pyqt5 GUI 中。該圖是交互式的,允許繪制陰影矩形。問題問題是當它嵌入到 pyqt 窗口中時,繪圖不是交互式的。當我運行該程序時,下面代碼中的第 147 行(mplWidget 類中的 plt.show())顯示了 matplotlib 圖,然后我可以繪制一個矩形,如您在此處所見:然而,當這個窗口關閉并且繪圖嵌入到 pyqt 窗口中時,它就變得不可編輯了我希望 GUI 圖能夠像 matplotlib 圖一樣運行。建議的解決方案/問題我知道這與我必須通過語句提供 pyqt 功能這一事實有關connect(),但我不知道這些語句去哪里/它們將如何適合該程序。我不知道如何連接到 matplotlib。我是否只對connect()mplWidget 類函數使用語句?任何幫助表示贊賞?。ㄎ乙庾R到我需要去掉第 147 行(plt.show()),這樣圖框就不會在 gui 之前彈出,但我只是暫時用它來顯示 mpl 類仍然按預期運行,并且問題是它在嵌入時變成“靜態”)
查看完整描述

1 回答

?
偶然的你

TA貢獻1841條經驗 獲得超3個贊

在你的代碼中有很多所以我只列出它們:

  • 如果您打算使用 FigureCanvasQTAgg,那么您不應該再使用 pyplot。

  • “mplWidget”是一個唯一任務是重繪畫布的類,那么它必須是一個 QWidget 嗎?。

  • 例如,如果您要比較布爾值,請不要使用“is”,我if self.plotSnap is False:if not self.plotSnap:認為認為“plotSnap”為 False 是不合邏輯的,如果您想禁用,則設置一個不可能的值,例如 0 或負數。

考慮到上面我已經讓 MplWidget 繼承自 FigureCanvasQTAgg,我已經消除了 pyplot 的使用:

import numpy as np

from PyQt5 import QtCore, QtGui, QtWidgets

from matplotlib.backends.backend_qt5agg import (

    FigureCanvasQTAgg,

    NavigationToolbar2QT as NavigationToolbar,

)

from matplotlib.figure import Figure



class MplWidget(FigureCanvasQTAgg):

    def __init__(self, parent=None):

        fig = Figure()

        super(MplWidget, self).__init__(fig)

        self.setParent(parent)

        # Set default colors array

        self.defaultColors = np.array(

            [

                [0, 0.4470, 0.7410],

                [0.8500, 0.3250, 0.0980],

                [0.9290, 0.6940, 0.1250],

                [0.4660, 0.6740, 0.1880],

                [0.6350, 0.0780, 0.1840],

                [0.4940, 0.1840, 0.5560],

                [0.3010, 0.7450, 0.9330],

            ]

        )


        # Create a figure with axes


        self.ax = self.figure.add_subplot(111)


        # Form the plot and shading

        self.bottomLeftX = 0

        self.bottomLeftY = 0

        self.topRightX = 0

        self.topRightY = 0

        self.x = np.array(

            [

                self.bottomLeftX,

                self.bottomLeftX,

                self.topRightX,

                self.topRightX,

                self.bottomLeftX,

            ]

        )

        self.y = np.array(

            [

                self.bottomLeftY,

                self.topRightY,

                self.topRightY,

                self.bottomLeftY,

                self.bottomLeftY,

            ]

        )


        (self.myPlot,) = self.ax.plot(self.x, self.y, color=self.defaultColors[0, :])

        self.aspan = self.ax.axvspan(

            self.bottomLeftX, self.topRightX, color=self.defaultColors[0, :], alpha=0

        )

        self.ax.set_xlim((-100, 100))

        self.ax.set_ylim((-100, 100))


        # Set moving flag false (determines if mouse is being clicked and dragged inside plot). Set graph snap

        self.moving = False

        self.plotSnap = 5


        # Set up connectivity

        self.cid1 = self.mpl_connect("button_press_event", self.onclick)

        self.cid2 = self.mpl_connect("button_release_event", self.onrelease)

        self.cid3 = self.mpl_connect("motion_notify_event", self.onmotion)


    def setSnapBase(self, base):

        return lambda value: int(base * round(float(value) / base))


    def onclick(self, event):

        if self.plotSnap <= 0:

            self.bottomLeftX = event.xdata

            self.bottomLeftY = event.ydata

        else:

            self.calculateSnapCoordinates = self.setSnapBase(self.plotSnap)

            self.bottomLeftX = self.calculateSnapCoordinates(event.xdata)

            self.bottomLeftY = self.calculateSnapCoordinates(event.ydata)


        try:

            self.aspan.remove()

        except:

            pass


        self.moving = True


    def onrelease(self, event):

        if self.plotSnap <= 0:

            self.topRightX = event.xdata

            self.topRightY = event.ydata

        else:

            try:

                calculateSnapCoordinates = self.setSnapBase(self.plotSnap)

                self.topRightX = calculateSnapCoordinates(event.xdata)

                self.topRightY = calculateSnapCoordinates(event.ydata)

            except:

                pass


        self.x = np.array(

            [

                self.bottomLeftX,

                self.bottomLeftX,

                self.topRightX,

                self.topRightX,

                self.bottomLeftX,

            ]

        )

        self.y = np.array(

            [

                self.bottomLeftY,

                self.topRightY,

                self.topRightY,

                self.bottomLeftY,

                self.bottomLeftY,

            ]

        )


        self.myPlot.set_xdata(self.x)

        self.myPlot.set_ydata(self.y)

        # ax.fill_between(x, y, color=defaultColors[0, :], alpha=.25)

        ylimDiff = self.ax.get_ylim()[1] - self.ax.get_ylim()[0]

        self.aspan = self.ax.axvspan(

            self.bottomLeftX,

            self.topRightX,

            (self.bottomLeftY - self.ax.get_ylim()[0]) / ylimDiff,

            (self.topRightY - self.ax.get_ylim()[0]) / ylimDiff,

            color=self.defaultColors[0, :],

            alpha=0.25,

        )


        self.moving = False

        self.draw()


    def onmotion(self, event):

        if not self.moving:

            return

        if event.inaxes is None:

            return

        if event.button != 1:

            return


        if self.plotSnap <= 0:

            self.topRightX = event.xdata

            self.topRightY = event.ydata

        else:

            self.calculateSnapCoordinates = self.setSnapBase(self.plotSnap)

            self.topRightX = self.calculateSnapCoordinates(event.xdata)

            self.topRightY = self.calculateSnapCoordinates(event.ydata)


        self.x = np.array(

            [

                self.bottomLeftX,

                self.bottomLeftX,

                self.topRightX,

                self.topRightX,

                self.bottomLeftX,

            ]

        )

        self.y = np.array(

            [

                self.bottomLeftY,

                self.topRightY,

                self.topRightY,

                self.bottomLeftY,

                self.bottomLeftY,

            ]

        )

        self.myPlot.set_xdata(self.x)

        self.myPlot.set_ydata(self.y)


        self.draw()



class TopLevelWindow(QtWidgets.QMainWindow):

    def __init__(self):

        super().__init__()

        self.canvas = MplWidget()

        self.setCentralWidget(self.canvas)



if __name__ == "__main__":

    import sys


    app = QtWidgets.QApplication(sys.argv)


    w = TopLevelWindow()

    w.show()


    sys.exit(app.exec_())



查看完整回答
反對 回復 2023-03-08
  • 1 回答
  • 0 關注
  • 117 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號