MatPlotLib PyQt5 布局问题

Posted

技术标签:

【中文标题】MatPlotLib PyQt5 布局问题【英文标题】:MatPlotLib PyQt5 Layout Problems 【发布时间】:2017-06-11 11:53:11 【问题描述】:

使用水平和垂直布局,似乎很难将小部件放在我想要的位置。也许还有另一种方法,例如:

    如果可以将画布和工具栏放在容器或某种小部件中。然后,您可以调整大小并将其放在您想要的位置。 如果可以限制绘图的大小以使背景中的 UI 可见。但这似乎是不可能的。 使用 QGridLayout 怎么样?

我尝试了很多东西,但很困惑,似乎没有任何效果。

我遇到的问题(使用当前的水平和垂直布局)是:

    标签漂移并且未与小部件对齐。 按钮框太宽。按钮可以在最后两列之间拆分吗?

这是一些代码。抱歉格式化。 (这4个空格很难搞定):

import sys
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import matplotlib.pyplot as plt
import random
from PyQt5.QtWidgets import QPushButton, QVBoxLayout, QHBoxLayout, QApplication, QDialog, QGridLayout, QLayout
from PyQt5 import QtCore, QtGui, QtWidgets


class Ui_Dialog(QDialog):
def __init__(self, parent=None):
    super(Ui_Dialog, self).__init__(parent)
    self.setupUi(self)
    self.setupPlot()

def setupUi(self, Dialog):
    Dialog.setObjectName("Dialog")
    Dialog.resize(719, 353)
    Dialog.setWindowTitle("Task")
    self.buttonBox = QtWidgets.QDialogButtonBox(Dialog)
    self.buttonBox.setGeometry(QtCore.QRect(590, 310, 121, 32))
    self.buttonBox.setOrientation(QtCore.Qt.Horizontal)
    self.buttonBox.setStandardButtons(QtWidgets.QDialogButtonBox.Cancel|QtWidgets.QDialogButtonBox.Ok)
    self.buttonBox.setObjectName("buttonBox")
    self.label1 = QtWidgets.QLabel(Dialog)
    self.label1.setGeometry(QtCore.QRect(590, 40, 51, 16))
    self.label1.setText("label1:")
    self.label1.setObjectName("label1")
    self.label2 = QtWidgets.QLabel(Dialog)
    self.label2.setGeometry(QtCore.QRect(590, 70, 41, 16))
    self.label2.setText("label2:")
    self.label2.setObjectName("label2")
    self.cBox1 = QtWidgets.QComboBox(Dialog)
    self.cBox1.setGeometry(QtCore.QRect(650, 40, 61, 22))
    self.cBox1.setLayoutDirection(QtCore.Qt.LeftToRight)
    self.cBox1.setEditable(False)
    self.cBox1.setCurrentText("Option0")
    self.cBox1.setMaxVisibleItems(2)
    self.cBox1.setObjectName("cBox1")
    self.cBox1.addItem("")
    self.cBox1.setItemText(0, "Option0")
    self.cBox1.addItem("")
    self.cBox1.setItemText(1, "Option1")
    self.label5 = QtWidgets.QLabel(Dialog)
    self.label5.setGeometry(QtCore.QRect(590, 160, 51, 16))
    self.label5.setText("label5:")
    self.label5.setObjectName("label5")
    self.dSpinBox5 = QtWidgets.QDoubleSpinBox(Dialog)
    self.dSpinBox5.setGeometry(QtCore.QRect(650, 160, 62, 22))
    self.dSpinBox5.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.dSpinBox5.setMaximum(1999.99)
    self.dSpinBox5.setObjectName("dSpinBox5")
    self.dSpinBox4 = QtWidgets.QDoubleSpinBox(Dialog)
    self.dSpinBox4.setGeometry(QtCore.QRect(650, 130, 62, 22))
    self.dSpinBox4.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.dSpinBox4.setMaximum(1999.99)
    self.dSpinBox4.setObjectName("dSpinBox4")
    self.label0 = QtWidgets.QLabel(Dialog)
    self.label0.setGeometry(QtCore.QRect(590, 10, 41, 16))
    self.label0.setText("label0:")
    self.label0.setObjectName("label0")
    self.dSpinBox3 = QtWidgets.QDoubleSpinBox(Dialog)
    self.dSpinBox3.setGeometry(QtCore.QRect(650, 100, 62, 22))
    self.dSpinBox3.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.dSpinBox3.setMaximum(1999.99)
    self.dSpinBox3.setObjectName("dSpinBox3")
    self.label3 = QtWidgets.QLabel(Dialog)
    self.label3.setGeometry(QtCore.QRect(590, 100, 61, 16))
    self.label3.setText("label3:")
    self.label3.setObjectName("label3")
    self.lineEdit0 = QtWidgets.QLineEdit(Dialog)
    self.lineEdit0.setGeometry(QtCore.QRect(650, 10, 61, 20))
    self.lineEdit0.setInputMask("")
    self.lineEdit0.setText("")
    self.lineEdit0.setObjectName("lineEdit0")
    self.label4 = QtWidgets.QLabel(Dialog)
    self.label4.setGeometry(QtCore.QRect(590, 130, 41, 16))
    self.label4.setText("label4:")
    self.label4.setObjectName("label4")
    self.spinBox2 = QtWidgets.QSpinBox(Dialog)
    self.spinBox2.setGeometry(QtCore.QRect(650, 70, 61, 22))
    self.spinBox2.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.spinBox2.setMaximum(999)
    self.spinBox2.setSingleStep(10)
    self.spinBox2.setProperty("value", 50)
    self.spinBox2.setObjectName("spinBox2")
    self.label6 = QtWidgets.QLabel(Dialog)
    self.label6.setGeometry(QtCore.QRect(590, 190, 41, 16))
    self.label6.setText("label6:")
    self.label6.setObjectName("label6")
    self.dSpinBox6 = QtWidgets.QDoubleSpinBox(Dialog)
    self.dSpinBox6.setGeometry(QtCore.QRect(650, 190, 62, 22))
    self.dSpinBox6.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.dSpinBox6.setReadOnly(True)
    self.dSpinBox6.setButtonSymbols(QtWidgets.QAbstractSpinBox.NoButtons)
    self.dSpinBox6.setObjectName("dSpinBox6")
    self.label7 = QtWidgets.QLabel(Dialog)
    self.label7.setGeometry(QtCore.QRect(590, 220, 47, 16))
    self.label7.setText("label7:")
    self.label7.setObjectName("label7")
    self.spinBox7 = QtWidgets.QSpinBox(Dialog)
    self.spinBox7.setGeometry(QtCore.QRect(650, 220, 61, 22))
    self.spinBox7.setAlignment(QtCore.Qt.AlignRight|QtCore.Qt.AlignTrailing|QtCore.Qt.AlignVCenter)
    self.spinBox7.setMaximum(999)
    self.spinBox7.setProperty("value", 50)
    self.spinBox7.setObjectName("spinBox7")
    self.checkBox8 = QtWidgets.QCheckBox(Dialog)
    self.checkBox8.setGeometry(QtCore.QRect(650, 250, 61, 20))
    self.checkBox8.setLayoutDirection(QtCore.Qt.RightToLeft)
    self.checkBox8.setText("")
    self.checkBox8.setCheckable(False)
    self.checkBox8.setObjectName("checkBox8")
    self.checkBox9 = QtWidgets.QCheckBox(Dialog)
    self.checkBox9.setGeometry(QtCore.QRect(650, 280, 61, 20))
    self.checkBox9.setLayoutDirection(QtCore.Qt.RightToLeft)
    self.checkBox9.setText("")
    self.checkBox9.setCheckable(False)
    self.checkBox9.setObjectName("checkBox9")
    self.label8 = QtWidgets.QLabel(Dialog)
    self.label8.setGeometry(QtCore.QRect(590, 250, 51, 16))
    self.label8.setText("label8")
    self.label8.setObjectName("label8")
    self.label9 = QtWidgets.QLabel(Dialog)
    self.label9.setGeometry(QtCore.QRect(590, 276, 47, 16))
    self.label9.setText("label9")
    self.label9.setObjectName("label9")

    self.buttonBox.accepted.connect(Dialog.accept)
    self.buttonBox.rejected.connect(Dialog.reject)
    QtCore.QMetaObject.connectSlotsByName(Dialog)

def setupPlot(self):
    self.setLayout(QHBoxLayout())
    self.layout().setContentsMargins(0, 0, 0, 0)
    self.figure = plt.figure()
    self.figure.set_facecolor("none")
    self.canvas = FigureCanvas(self.figure)

    self.toolbar = NavigationToolbar(self.canvas, self)

    self.widget = QtWidgets.QWidget()
    layout = QVBoxLayout()
    self.widget.setLayout(layout)
    layout.addWidget(self.toolbar)
    layout.addWidget(self.canvas)
    self.layout().addWidget(self.widget)

    self.widget = QtWidgets.QWidget()
    layout = QVBoxLayout()
    self.widget.setLayout(layout)
    layout.addWidget(self.label0)
    layout.addWidget(self.label1)
    layout.addWidget(self.label2)
    layout.addWidget(self.label3)
    layout.addWidget(self.label4)
    layout.addWidget(self.label5)
    layout.addWidget(self.label6)
    layout.addWidget(self.label7)
    layout.addWidget(self.label8)
    layout.addWidget(self.label9)
    self.layout().addWidget(self.widget)

    self.widget = QtWidgets.QWidget()
    layout = QVBoxLayout()
    self.widget.setLayout(layout)
    layout.addWidget(self.lineEdit0)
    layout.addWidget(self.cBox1)
    layout.addWidget(self.spinBox2)
    layout.addWidget(self.dSpinBox3)
    layout.addWidget(self.dSpinBox4)
    layout.addWidget(self.dSpinBox5)
    layout.addWidget(self.dSpinBox6)
    layout.addWidget(self.spinBox7)
    layout.addWidget(self.checkBox8)
    layout.addWidget(self.checkBox9)
    layout.addWidget(self.buttonBox)
    self.layout().addWidget(self.widget)

    self.plot()

def plot(self):
    data = [random.random() for i in range(10)]
    self.figure.clear()
    ax = self.figure.add_subplot(111)
    ax.plot(data, '*-')
    self.canvas.draw()


if __name__ == '__main__':
    app = QApplication(sys.argv)
    main = Ui_Dialog()
    main.show()
    sys.exit(app.exec_())

【问题讨论】:

要在 PyQt 中对齐小部件,请使用布局!删除所有 setGeometry 调用并将小部件添加到布局中。除此之外,Point1,“将画布和工具栏放入容器中”是我在the answer to the previous question 中展示的内容。我不明白Point2。 Point3 中提到的QGridLayout 是一个不错的选择,是的。我想您应该为您遇到的每个问题创建一个minimal reproducible example(不要将所有内容都放在同一个代码中,并且可能将 matplotlib 排除在外,因为它看起来不相关)。 【参考方案1】:

@ImportanceOfBeingErnest 您的评论解决了这个问题。赞赏:

    删除了所有 setGeometry 调用。 创建了一个 QGridLayout 。 向 gridLayout 添加小部件,如下所示: self.layout().addWidget(self.checkBoxDone, 3, 4, 1, 1)

注意:注意不要混淆参数:

    小部件 起始行(从顶部的 0 开始) 开始列(从左侧的 0 开始) 要跨越的行数(向下) 要跨越的列数(向右)

【讨论】:

以上是关于MatPlotLib PyQt5 布局问题的主要内容,如果未能解决你的问题,请参考以下文章

急急急 pyqt5 matplotlib 多线程问题,求大佬指点啊

使用 PyQt5 和 Matplotlib 制作动态图

在 PyQt5 中使用 Matplotlib 绘制 CSV 文件

在 pyqt5 中绘制 Matplotlib 图

Matplotlib 和 PyQt5 绘图图

pyinstaller 不适用于 pyqt5 和 matplotlib