0

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?

Layout Problems

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_())
Yster
  • 3,147
  • 5
  • 32
  • 48
  • 1
    To align widgets in PyQt use Layouts! Remove all the `setGeometry` calls and add the widgets to a layout. Apart from that, Point1, "put the canvas and toolbar in a container" is what I've shown in [the answer to the previous question](https://stackoverflow.com/a/44472836/4124317). I don't understand Point2. A `QGridLayout` as mentionned in Point3 is a great option, yes. I guess you should create a [mcve] for each issue you have (not putting everything in the same code, and possibly leave matplotlib out, since it seems unrelated). – ImportanceOfBeingErnest Jun 11 '17 at 12:13

1 Answers1

-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)
Yster
  • 3,147
  • 5
  • 32
  • 48