Search code examples
python-3.xpyqt6

Trying to get a QDialog to expand to its contents


I am trying to create a derived QWidget that I can reuse. I want to have a border around the widget. I have this working so far. My problem is that the parent QDialog is not completely expanding so I need to expand it manually after it launches. I would prefer not setting a specific size, but letting the dialog to grow as required.

from PyQt6.QtWidgets import QLineEdit, QRadioButton, QSizePolicy, QDialog

import sys
from PyQt6.QtWidgets import QApplication, QWidget, QFrame, QVBoxLayout, QHBoxLayout, QLabel


class MyNestedWidget(QWidget):
    def __init__(self):
        super().__init__()
        self.dollars_edit = None
        self.dollar_edit = None
        self.dollar_radio = None

        main_frame = QFrame(self)
        main_frame.setFrameShape(QFrame.Shape.Panel)
        main_frame.setLineWidth(2)

        label = QLabel("Choose one")
        v_layout = QVBoxLayout()
        v_layout.addWidget(label)

        layout = QHBoxLayout()
        self.dollar_radio = QRadioButton('Amount')
        layout.addWidget(self.dollar_radio)
        self.dollar_edit = QLineEdit()
        layout.addWidget(QLabel('$'))
        layout.addWidget(self.dollar_edit)
        layout.addStretch()
        v_layout.addLayout(layout)

        layout = QHBoxLayout()
        self.percent_radio = QRadioButton('Percent')
        layout.addWidget(self.percent_radio)
        self.percent_edit = QLineEdit()
        layout.addWidget(self.percent_edit)
        layout.addWidget(QLabel('%'))
        layout.addStretch()
        v_layout.addLayout(layout)
        v_layout.setContentsMargins(5, 0, 5, 5)

        main_frame.setLineWidth(2)
        main_frame.setLayout(v_layout)
        self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)


class MyDialog(QDialog):
    def __init__(self):
        super().__init__()
        self.widget = MyNestedWidget()
        top_layout = QVBoxLayout()
        top_layout.addWidget(self.widget)
        self.setLayout(top_layout)
        self.setSizePolicy(QSizePolicy.Policy.Expanding, QSizePolicy.Policy.Expanding)


if __name__ == '__main__':
    app = QApplication(sys.argv)

    test = False
    if test:
        widget = MyNestedWidget()
        widget.show()
    else:
        dialog = MyDialog()
        dialog.exec()
    sys.exit(app.exec())

This is what it looks like on running:

enter image description here

This is what I want it to look like:

enter image description here


Solution

  • You are setting the layout to a child widget, but not to the actual one. Doing that will prevent the parent to know anything about that layout.

    In fact, that main_frame is quite useless.
    Remove it, then just subclass QFrame instead of QWidget, apply those frame settings to self, and finally call self.setLayout(v_layout).

    Alternatively, use self as argument of the layout constructor instead of calling setLayout().

    Also, size policies only make sense for widgets that are added to a layout that also contains other widgets, so remove them as they are completely useless.