Jaime02
Jaime02

Reputation: 347

QDockWidget with widgets in titlebar can't be collapsed

I have a QDockWidget and I have put some widgets on it's titlebar like in this MRE:

from PySide6.QtCore import Qt
from PySide6.QtWidgets import (QWidget, QCheckBox, QMainWindow, QLabel, QDockWidget, QApplication, QHBoxLayout,
                               QSizePolicy)


class MainWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)

        central_widget = QLabel("Window stuff!")
        self.setCentralWidget(central_widget)

        self.dock = QDockWidget()

        self.docker_layout = QHBoxLayout()
        self.docker_layout.setContentsMargins(0, 0, 0, 0)
        self.docker_layout.setAlignment(Qt.AlignLeft)

        container = QWidget()
        container.setLayout(self.docker_layout)
        label = QLabel("Docker name")
        label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Minimum)
        self.dock.setTitleBarWidget(container)

        # Widgets creation:
        self.docker_layout.addWidget(label)
        self.check_1 = QCheckBox("Check 1")
        self.docker_layout.addWidget(self.check_1)
        self.check_2 = QCheckBox("Check 2", checked=True)
        self.docker_layout.addWidget(self.check_2)
        self.check_3 = QCheckBox("Check 3", checked=True)
        self.docker_layout.addWidget(self.check_3)
        self.check_4 = QCheckBox("You cant hide me haha!", checked=True)
        self.docker_layout.addWidget(self.check_4)

        self.dock.setTitleBarWidget(container)

        self.addDockWidget(Qt.RightDockWidgetArea, self.dock)

        self.dock_content = QLabel("Dock stuff!")
        self.dock.setWidget(self.dock_content)

        self.show()


if __name__ == "__main__":
    app = QApplication([])
    window = MainWindow()
    app.exec()

But as you can see in the following giph, the dock is not collapsable due to the widgets in the sidebar. How can I allow the widgets to get out of screen and resize the dock freely? enter image description here

Upvotes: 0

Views: 172

Answers (1)

musicamante
musicamante

Reputation: 48260

That depends by the fact that the dock widget sets the minimum width based on that of the title bar widget: if no explicit minimum width is set, then the width returned by minimumSizeHint() is used.

A possible solution is to subclass the layout and reimplement both minimumWidth() and setGeometry().

The first ensures that the title bar can be resized to a smaller width, while the second lays outs the items by ignoring the given geometry at all.

The result is, obviously, that part of the title bar will be hidden.

resized title bar with elements cropped

class IgnoreWidthLayout(QHBoxLayout):
    def minimumSize(self):
        return QSize(80, super().minimumSize().height())

    def setGeometry(self, geometry):
        geometry.setWidth(super().minimumSize().width())
        super().setGeometry(geometry)

class MainWindow(QMainWindow):
    def __init__(self):
        # ...
        self.docker_layout = IgnoreWidthLayout()

Note that:

  1. setting the Minimum size policy on the label is not required in this situation (and you probably should need Maximum instead, consider that QSizePolicy flags have names that are unintuitive at first);
  2. you're calling setTitleBarWidget twice;
  3. setting the alignment on the layout has usually little use (and is almost useless in this specific case): it doesn't tell the alignment of the child items, it specifies the alignment that layout manager will have once it's set on a parent widget or added to another layout;

Upvotes: 1

Related Questions