QT5 和 Matplotlib - 设置嵌入式图形的几何形状

QT5 and Matplotlib - set geometry of an embedded graph

我尝试使用带有一些按钮的小 GUI 并嵌入 space 以根据 GUI 中的数据绘制图表。 这是代码:

from PyQt5 import QtCore, QtGui, QtWidgets 
from PyQt5.QtWidgets import QMessageBox, QFileDialog, QMainWindow, QVBoxLayout

import sys
import os
import glob

import numpy as np

import matplotlib
matplotlib.use('Qt5Agg')

import matplotlib.pyplot as plt

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


class MplWidget(QtWidgets.QWidget):
    def __init__(self,parent = None, width = 5, height = 4, dpi = 100):
        

        self.fig = Figure(figsize=(width, height), dpi = dpi)
        super().__init__(parent)
        self.canvas = FigureCanvas(self.fig)
        self.toolbar = NavigationToolbar(self.canvas, self)
        
        layout = QtWidgets.QVBoxLayout(self)
        layout.setGeometry(QtCore.QRect(340, 50, 451, 411))
        layout.addWidget(self.toolbar)
        layout.addWidget(self.canvas)
        FigureCanvas.setSizePolicy(self, QtWidgets.QSizePolicy.Fixed, QtWidgets.QSizePolicy.Fixed)
                         
        self.ax = self.canvas.figure.add_subplot(111)
        
    def plot_basic_line(self, X, Y, label):
        self.ax.cla() # clears the axis
        self.ax.plot(X, Y, label=label)
        self.ax.grid(True)
        self.ax.legend()
        self.canvas.figure.tight_layout()
        self.canvas.draw()


class Ui_MainWindow(QMainWindow): 
    #def __init__(self):
    def setupUi(self, MainWindow):
        super().__init__()    
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(900, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.graphicsView = QtWidgets.QVBoxLayout(self.centralwidget)       
        self.mpl_canvas = MplWidget(self)
        self.graphicsView.setGeometry(QtCore.QRect(340, 50, 451, 411))
        self.graphicsView.addWidget(self.mpl_canvas)
        
        self.B_Plot = QtWidgets.QPushButton(self.centralwidget)
        self.B_Plot.setGeometry(QtCore.QRect(40, 280, 75, 23))
        self.B_Plot.setObjectName("B_Plot")

        MainWindow.setCentralWidget(self.centralwidget)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

        self.B_Plot.clicked.connect(self.plot)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.B_Plot.setText(_translate("MainWindow", "Plot"))

    def plot(self):
        x = np.linspace(0,10)
        y = np.linspace(0,10)
        self.mpl_canvas.plot_basic_line(x, y, label='plot1')

        

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    MainWindow = QtWidgets.QMainWindow()
    ui = Ui_MainWindow()
    ui.setupUi(MainWindow)
    MainWindow.show()
    sys.exit(app.exec_())

现在,情节假设整个 space 主要 window,我不知道如何将它正确地保存在 GUI。下图说明了这个问题(我在这里的例子中留下了大部分按钮)。 我想在 UI 上指定生成绘图的区域,但现在我必须将所有内容放在绘图周围...

Embedded plot takes whole window space

您只需要在网格中布置一些框架 (gridded_outer_frame)。在网格内放置另一个框架 (inner_frame)。 inner_frame 将自动适合 gridded_outer_frame

然后在代码中定义 canvas 处理程序,inner_frame 的 chart_layout 处理程序并将 canvas 放置在布局中:

chart = MplCanvas(self)
chart_layout = inner_frame # inner frame serves as a target for chart
chart_layout.addWidget(chart)