I’m trying to build a QGridLayout with stretchable-width columns but non-stretchable-height rows. The grid in inside a QScrollArea, and with the exception of the height, it’s almost working. You can see it in the following images:
As you can see, the rows are being vertically stretched. I would like all the rows to be equal and to not fit all the parent’s height if there are too few rows (first image). Should I touch the grid or the actual widgets?
Edit: reproducible example
import sys from PyQt5.QtWidgets import (QWidget, QGridLayout, QLabel, QRadioButton, QApplication, QScrollArea, QVBoxLayout) class ScrollableGrid(QWidget): def __init__(self, columnSpans, minimumColumnWidth): super().__init__() # Grid self.grid = QWidget() self.gridLayout = QGridLayout() for i in range(len(columnSpans)): self.gridLayout.setColumnStretch(i, columnSpans[i]) self.gridLayout.setColumnMinimumWidth(i, columnSpans[i] * minimumColumnWidth) self.grid.setLayout(self.gridLayout) # Scroll area self.scrollArea = QScrollArea() self.scrollArea.setWidget(self.grid) self.scrollArea.setWidgetResizable(True) # Compute the correct minimum width width = (self.grid.sizeHint().width() + self.scrollArea.verticalScrollBar().sizeHint().width() + self.scrollArea.frameWidth() * 2) self.scrollArea.setMinimumWidth(width) # Layout self.layout = QVBoxLayout() self.layout.addWidget(self.scrollArea) self.setLayout(self.layout) def addRow(self, row, elements): for column in range(len(elements)): self.gridLayout.addWidget(elements[column], row, column) class MainWindow(QWidget): def __init__(self): super().__init__() # ScrollableGrid self.grid = ScrollableGrid(columnSpans=[1,2,3], minimumColumnWidth=100) # Add rows for i in range(3): self.grid.addRow(i, [QLabel('A'), QLabel('B'), QRadioButton()]) # Window layout self.layout = QVBoxLayout() self.layout.addWidget(self.grid) self.setLayout(self.layout) if __name__ == '__main__': app = QApplication(sys.argv) windowExample = MainWindow() windowExample.show() sys.exit(app.exec_())
Advertisement
Answer
void QGridLayout::setRowStretch(int row, int stretch)
Sets the stretch factor of row row to stretch. The first row is number 0.
The stretch factor is relative to the other rows in this grid. Rows with a higher stretch factor take more of the available space.
Yes, is it because it must me called after all rows have been added.
import sys from PyQt5.QtWidgets import (QWidget, QGridLayout, QLabel, QRadioButton, QApplication, QScrollArea, QVBoxLayout) class ScrollableGrid(QWidget): def __init__(self, columnSpans, minimumColumnWidth): super().__init__() # Grid self.grid = QWidget() self.gridLayout = QGridLayout() for i in range(len(columnSpans)): self.gridLayout.setColumnStretch(i, columnSpans[i]) self.gridLayout.setColumnMinimumWidth(i, columnSpans[i] * minimumColumnWidth) self.grid.setLayout(self.gridLayout) # Scroll area self.scrollArea = QScrollArea() self.scrollArea.setWidget(self.grid) self.scrollArea.setWidgetResizable(True) # Compute the correct minimum width width = (self.grid.sizeHint().width() + self.scrollArea.verticalScrollBar().sizeHint().width() + self.scrollArea.frameWidth() * 2) self.scrollArea.setMinimumWidth(width) # Layout self.layout = QVBoxLayout() self.layout.addWidget(self.scrollArea) self.setLayout(self.layout) def addRow(self, row, elements): for column in range(len(elements)): self.gridLayout.addWidget(elements[column], row, column) class MainWindow(QWidget): def __init__(self): super().__init__() # ScrollableGrid self.grid = ScrollableGrid(columnSpans=[1,2,3], minimumColumnWidth=100) # Add rows for i in range(3): self.grid.addRow(i, [QLabel('A'), QLabel('B'), QRadioButton()]) self.grid.gridLayout.setRowStretch(111, 1) # !!! # Window layout self.layout = QVBoxLayout() self.layout.addWidget(self.grid) self.setLayout(self.layout) if __name__ == '__main__': app = QApplication(sys.argv) windowExample = MainWindow() windowExample.show() sys.exit(app.exec_())