pythonpyqt5qgridlayout

PyQt5 dynamically expand widget to two columns in QGridLayout?


The example below, which I've modified from the answer in Pyqt5 widget in grid expansion, starts like this:

example starting GUI

Then when you click the Column Cover button, the idea is that the first label "Row 0, Column 0" (outlined in red) expands on both columns of the QGridLayout - however, I get this:

example GUI after click

So, it seems that both grid columns' widths were taken into account, in order to center the outlined label, which is good - however, the outlined label did not expand to take up the combined width of both columns.

How can I have the label expand in width, and take up the space of both columns in grid layout, when "Column Cover" button is clicked? I.e. I'd want to obtain this after first button click after program start (edited in image editor, box is approx what I think the union of the bounding boxes of both labels below the outlined one are).

desired result GUI

Note that I am aware I could do probably that by manipulating .setFixedWidth of MainUi.label - however, I'm looking for some sort of a setup, where the label would automatically expand to fill available width, depending on whether its placed in one or two columns of the QGridLayout.

The code:

import sys
from PyQt5.QtCore import *
from PyQt5.QtGui import *
from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui, QtWidgets

#rom example import Ui_MainWindow
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(191, 136)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.gridLayout = QtWidgets.QGridLayout(self.centralwidget)
        self.gridLayout.setObjectName("gridLayout")
        self.pushButton = QtWidgets.QPushButton(self.centralwidget)
        self.pushButton.setObjectName("pushButton")
        self.gridLayout.addWidget(self.pushButton, 0, 0, 1, 2)
        self.label_3 = QtWidgets.QLabel(self.centralwidget)
        self.label_3.setObjectName("label_3")
        self.gridLayout.addWidget(self.label_3, 3, 0, 1, 1)
        self.label_4 = QtWidgets.QLabel(self.centralwidget)
        self.label_4.setObjectName("label_4")
        self.gridLayout.addWidget(self.label_4, 2, 1, 1, 1)
        self.label_5 = QtWidgets.QLabel(self.centralwidget)
        self.label_5.setObjectName("label_5")
        self.gridLayout.addWidget(self.label_5, 3, 1, 1, 1)
        self.label_6 = QtWidgets.QLabel(self.centralwidget)
        self.label_6.setObjectName("label_6")
        self.gridLayout.addWidget(self.label_6, 1, 1, 1, 1)
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setObjectName("label")
        self.gridLayout.addWidget(self.label, 1, 0, 1, 1)
        self.label.setStyleSheet("border: 1px solid; border-color:red;")

        self.label_2 = QtWidgets.QLabel(self.centralwidget)
        self.label_2.setObjectName("label_2")
        self.gridLayout.addWidget(self.label_2, 2, 0, 1, 1)
        MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

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

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
        self.pushButton.setText(_translate("MainWindow", "Column Cover"))
        self.label_3.setText(_translate("MainWindow", "Row 2, Column 0"))
        self.label_4.setText(_translate("MainWindow", "Row 1, Column 1"))
        self.label_5.setText(_translate("MainWindow", "Row 2, Column 1"))
        self.label_6.setText(_translate("MainWindow", "Row 0, Column 1"))
        self.label.setText(_translate("MainWindow", "Row 0, Column 0"))
        self.label_2.setText(_translate("MainWindow", "Row 1 ,Column 0 "))


class MainWindow(QMainWindow):
    def __init__(self, parent=None):
        super(MainWindow, self).__init__(parent)
        QWidget.__init__(self, parent)
        self.MainUi = Ui_MainWindow()
        self.MainUi.setupUi(self)

        self.MainUi.pushButton.setCheckable(True)                           # +++ True
        self.MainUi.pushButton.clicked.connect(self.expand_row)


    def expand_row(self, state):                                            # +++ state
        if state:
            self.MainUi.label_6.hide()
            self.MainUi.gridLayout.addWidget(self.MainUi.label, 1, 0, 1, 2, Qt.AlignHCenter) #  ...2, 1)
        else:
            self.MainUi.gridLayout.addWidget(self.MainUi.label, 1, 0, 1, 1) #  ...1, 1)
            self.MainUi.label_6.show()

#        self.MainUi.gridLayout.setRowStretch(0,1)


if __name__ == "__main__":
    app = QApplication(sys.argv)
    MainWindow = MainWindow()
    MainWindow.setWindowTitle('Example')
    MainWindow.show()
    sys.exit(app.exec_())

Solution

  • Set the alignment flag in QLabel.setAlignment instead of QLayout.addWidget.

    def expand_row(self, state):                                            # +++ state
        if state:
            self.MainUi.label_6.hide()
            self.MainUi.label.setAlignment(Qt.AlignCenter)
            self.MainUi.gridLayout.addWidget(self.MainUi.label, 1, 0, 1, 2) #  ...2, 1)
    
        else:
            self.MainUi.label.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)
            self.MainUi.gridLayout.addWidget(self.MainUi.label, 1, 0, 1, 1) #  ...1, 1)
            self.MainUi.label_6.show()