MatPlotLib PyQt5 Layout Problems

2019-08-18 01:37发布

问题:

MatPlotLib PyQt5 Layout Problems:

Using horizontal and vertical layouts, it seems to be very difficult to get the widgets where I want them. Maybe there is another way of doing it, for instance:

  1. If one can put the canvas and toolbar in a container or some kind of widget. Then you can size it and put it where you want.
  2. If one can limit the size of the plot so that the UI in the background is visible. This seems impossible though.
  3. What about using QGridLayout?

I have tried many things, but am very confused and nothing seems to work.

The problems I have (using the current horizontal and vertical layouts) are:

  1. The labels drift and are not aligned with the widgets.
  2. The buttonbox is too wide. Can the buttons be split between the last two columns?

Here is some code. Sorry for the formatting. (It's hard to get the 4 spaces right):

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_())

回答1:

@ImportanceOfBeingErnest Your comment is what solved the question. Appreciated:

  1. Removed all the setGeometry calls.
  2. Created a QGridLayout .
  3. Added widgets to the gridLayout like this: self.layout().addWidget(self.checkBoxDone, 3, 4, 1, 1)

NB: Be careful not to confuse the parameters:

  1. widget
  2. start row (from 0 at the top)
  3. start column (from 0 on the left)
  4. number of rows to span (downwards)
  5. number of columns to span (to the right)