jgsedi
jgsedi

Reputation: 247

Stretch the widgets properly in a horizontal layout of pyqt5

I tried to setup a main window, with a central widget. This contains a general widget and a label for help messages.

I wanted a stretch of 4:1. The base widget should get 4 times the space of the help label. But it seems both get the half of the window.

Here's my code:

import sys
from PyQt5.QtWidgets import \
    QApplication, QMainWindow, QWidget, QStatusBar, QMenuBar, QMenu, \
    QAction, QHBoxLayout, QLabel

from PyQt5.QtCore import QRect, QMetaObject, QCoreApplication


class UISimple(QMainWindow):
    def __init__(self, title="stretch 4 parts to 1"):
        super().__init__()

        self.showMaximized()
        self.setWindowTitle(title)

        # FIXME: is that necessary?
        self.centralwidget = QWidget(self)
        self.setCentralWidget(self.centralwidget)

        self.hlayout = QHBoxLayout(self.centralwidget)

        # Widget as a container for further views
        self.widget_container = QWidget(self.centralwidget)
        self.hlayout.addWidget(self.widget_container)

        # label for show some help
        self.label_help = QLabel(self.centralwidget)
        self.label_help.setStyleSheet("background-color: #B9E9BE")
        self.hlayout.addWidget(self.label_help)

        # FIXME: label 1 and widget 4 parts of the window.
        self.hlayout.setStretch(4, 1)

        self.setLayout(self.hlayout)

    def setup(self):
        self._setup_main_window()

    def write_help(self, helptext):
        self.label_help.setText(helptext)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = UISimple()
    window.write_help("You need some help - so i'm in trouble!")
    sys.exit(app.exec_())

Upvotes: 2

Views: 11817

Answers (2)

musicamante
musicamante

Reputation: 48231

The setStretch arguments are wrong:

QBoxLayout::setStretch(int index, int stretch)

Sets the stretch factor at position index to stretch.

The correct function should be:

# set a stretch factor of 4 for the first widget (the container)
self.hlayout.setStretch(0, 4)
# set a stretch factor of 1 for the second (the label)
self.hlayout.setStretch(1, 1)

Alternatively, you can directly set the stretch (which is an optional argument) when adding the widget:

self.hlayout.addWidget(self.widget_container, stretch=4)
self.hlayout.addWidget(self.label_help, stretch=1)

Note that if the widget_container doesn't have an appropriate minimum size (or size hint), the stretch won't be respected if the window width couldn't fit both of them.

Also consider that you should not call showMaximized too early, especially before setting the central widget (which is mandatory for a QMainWindow) and its contents; it's considered good practice to show the widget after it's fully constructed (so, not in the __init__).

Finally, remove the following line:

self.setLayout(self.hlayout)

A QMainWindow has its own, internal layout, which cannot be accessed nor replaced. In any case, the layout is already set on the central widget (since it was used as argument in the layout constructor), so there's no need to call setLayout anyway.

Upvotes: 4

S. Nick
S. Nick

Reputation: 13651

void QBoxLayout::addWidget(QWidget *widget, int stretch = 0, Qt::Alignment alignment = Qt::Alignment())

Adds widget to the end of this box layout, with a stretch factor of stretch and alignment alignment.


wordWrap : bool

This property holds the label's word-wrapping policy

import sys
from PyQt5.QtWidgets import \
    QApplication, QMainWindow, QWidget, QStatusBar, QMenuBar, QMenu, \
    QAction, QHBoxLayout, QLabel
from PyQt5.QtCore import QRect, QMetaObject, QCoreApplication


class UISimple(QMainWindow):
    def __init__(self, title="stretch 4 parts to 1"):
        super().__init__()

        self.showMaximized()
        self.setWindowTitle(title)

        # FIXME: is that necessary?
        self.centralwidget = QWidget(self)
        self.setCentralWidget(self.centralwidget)

        self.hlayout = QHBoxLayout(self.centralwidget)

        # Widget as a container for further views
        self.widget_container = QWidget(self.centralwidget)
        self.hlayout.addWidget(self.widget_container, stretch=4)    # +

        # label for show some help
        self.label_help = QLabel(self.centralwidget)
        self.label_help.setStyleSheet("background-color: #B9E9BE")
        self.label_help.setWordWrap(True)                           # +
        self.hlayout.addWidget(self.label_help, stretch=1)          # +      

        # FIXME: label 1 and widget 4 parts of the window.
#        self.hlayout.setStretch(4, 1)
# ?        self.setLayout(self.hlayout)

    def setup(self):
        self._setup_main_window()

    def write_help(self, helptext):
        self.label_help.setText(helptext)


if __name__ == '__main__':

    app = QApplication(sys.argv)
    window = UISimple()
    window.write_help("You need some help - so i'm in trouble!")
    sys.exit(app.exec_())

enter image description here

Upvotes: 1

Related Questions