Amin Mesbah Amin Mesbah - 26 days ago 17
Python Question

PyQt5 grid layout expands for big widgets, but doesn't contract for small widgets

Question: How can I make a PyQt grid layout shrink when the size of a widget decreases?

Desired Behavior



Display a long string in a label in a PyQt grid layout. The grid expands to accomodate the label. When the label is reset to a shorter string, the grid, no longer needing the extra space, contracts.

Actual Behavior



The grid expands to accomodate a long label, but doesn't contract when the
label becomes shorter. It remains at its expanded size.

Initial State



Initial state

Displaying the long label



Displaying the long label

Grid stays expanded after label is cleared



Grid stays expanded after the label is cleared

Minimal example using PyQt5 (5.7) in Python 3.5



The example below includes two buttons and a label. One button sets the label to 400 character long string of asterisks. The other sets the label to the empty string.

import sys
from PyQt5.QtCore import Qt
from PyQt5.QtWidgets import (
QApplication,
QGridLayout,
QLabel,
QPushButton,
QWidget,
)


class TestUI(QWidget):

def __init__(self):
super().__init__()
self.lbl_feedback = QLabel('Long string goes here', self)

btn_long_string = QPushButton('Display a long string', self)
btn_long_string.clicked.connect(self._show_feedback_label)

btn_clear = QPushButton('Clear the long string', self)
btn_clear.clicked.connect(self._hide_feedback_label)

grid = QGridLayout()
grid.setSpacing(5)

# assemble grid
grid.addWidget(self.lbl_feedback, 0, 1, Qt.AlignCenter)
grid.addWidget(btn_long_string, 1, 1, Qt.AlignCenter)
grid.addWidget(btn_clear, 2, 1, Qt.AlignCenter)

# resize weights
grid.setColumnStretch(0, 10)
grid.setColumnStretch(1, 10)
grid.setColumnStretch(2, 10)

self.setLayout(grid)
self.show()

def _show_feedback_label(self):
long_string = '*' * 400
self.lbl_feedback.setText(long_string)

def _hide_feedback_label(self):
self.lbl_feedback.setText('')


if __name__ == '__main__':
app = QApplication(sys.argv)
test_ui = TestUI()
sys.exit(app.exec_())

ADR ADR
Answer

I think it is impossible for main window because i can't find it in Qt Designer. But you can call mainwindow.adjustSize() on label.changed signal.

Update: Sorry, I was wrong. QLabel has no "changed" signal. Other way:

def _hide_feedback_label(self):
    self.lbl_feedback.setText('')

    self.adjustSize() # <--
Comments