QT: stretch factor in QSplitter does not work

Viewed 756

I am using QSplitter in my project, and I want to set the stretch factor for two widget. The following code is recommanded:

    splitter.setStretchFactor(0, 1)
    splitter.setStretchFactor(1, 5)

And I need to firstly hide one widget, then show it after I click a button. I find the stretch factor does not work. The whole code is:

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

class MainWindow(QWidget):

    def __init__(self):
        super().__init__()

        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)
        self.btn = QPushButton('show')
        self.btn.clicked.connect(self.btnSlot)
        mainLayout.addWidget(self.btn)
        layout = QHBoxLayout()
        mainLayout.addLayout(layout)
        self.w1 = QWidget()
        self.w1.setStyleSheet('border: 2px solid #777;')
        self.w1.hide()
        self.lay1 = QVBoxLayout()
        self.lay1.addWidget(QLabel('label 1'))
        self.w1.setLayout(self.lay1)

        w2 = QWidget()
        w2.setStyleSheet('border: 2px solid red;')
        self.lay2 = QVBoxLayout()
        w2.setLayout(self.lay2)

        splitter = QSplitter()
        splitter.addWidget(self.w1)
        splitter.addWidget(w2)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 5)
        layout.addWidget(splitter)

    def btnSlot(self, check=False):
        self.w1.show()
        self.lay2.addWidget(QLabel('label 2'))

if __name__ == '__main__':

    app = QApplication(sys.argv)
    w = MainWindow()
    w.show()
    app.exec_()

After clicked the 'show' button, the result is:

enter image description here

From the above figure, we can see the stretch factor for widget 1/2 is not 1:5. How can I make the strech factor to be 1:5?

Any suggestion is appreciated!

1 Answers

void QSplitter::setStretchFactor(int index, int stretch)

Updates the size policy of the widget at position index to have a stretch factor of stretch.

stretch is not the effective stretch factor; the effective stretch factor is calculated by taking the initial size of the widget and multiplying it with stretch.


void QSplitter::setSizes(const QList &list)

Sets the child widgets' respective sizes to the values given in the list.

If the splitter is horizontal, the values set the width of each widget in pixels, from left to right. If the splitter is vertical, the height of each widget is set, from top to bottom.

Extra values in the list are ignored. If list contains too few values, the result is undefined, but the program will still be well-behaved.

The overall size of the splitter widget is not affected. Instead, any additional/missing space is distributed amongst the widgets according to the relative weight of the sizes.

If you specify a size of 0, the widget will be invisible. The size policies of the widgets are preserved. That is, a value smaller than the minimal size hint of the respective widget will be replaced by the value of the hint.

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


class MainWindow(QWidget):
    def __init__(self):
        super().__init__()
        mainLayout = QVBoxLayout()
        self.setLayout(mainLayout)
        
        self.btn = QPushButton('show')
        self.btn.clicked.connect(self.btnSlot)
        mainLayout.addWidget(self.btn)
        layout = QHBoxLayout()
        mainLayout.addLayout(layout)
        
        self.w1 = QWidget()
        self.w1.setStyleSheet('border: 2px solid #777;')
        self.w1.hide()
        self.lay1 = QVBoxLayout()
        self.lay1.addWidget(QLabel('label 1'))
        self.w1.setLayout(self.lay1)

        self.w2 = QWidget()
        self.w2.setStyleSheet('border: 2px solid red;')
        self.lay2 = QVBoxLayout()
        self.w2.setLayout(self.lay2)

        splitter = QSplitter(Qt.Horizontal)
        splitter.addWidget(self.w1)
        splitter.addWidget(self.w2)
        splitter.setStretchFactor(0, 1)
        splitter.setStretchFactor(1, 5)
        
        splitter.setSizes([100,500])                                 # +++ 
        
        layout.addWidget(splitter)

    def btnSlot(self, check=False):
        self.w1.show()
        self.lay2.addWidget(QLabel('label 2'))
        
        QTimer.singleShot(0, self._print)
        
    def _print(self):
        print(f'{self.size()}')
        print(f'{self.w1.size()}')
        print(f'{self.w2.size()}')
        

if __name__ == '__main__':

    app = QApplication(sys.argv)
    w = MainWindow()
    w.resize(628, 280)                                                # +++ 
    w.show()
    app.exec_()

enter image description here

Related