Python Forum
[PyQt] Dinamically adding widgets to layout [PySide6] - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: GUI (https://python-forum.io/forum-10.html)
+--- Thread: [PyQt] Dinamically adding widgets to layout [PySide6] (/thread-40206.html)



Dinamically adding widgets to layout [PySide6] - carecavoador - Jun-19-2023

Hello!

I'm following this thread on SO to dinamically create widgets. I managed to translate this example to PySide6 and it works.

But, for some (probably dumb) reason, it's not working on my code. The program starts with no errors, but the widgets are not showing... Any advice?

import sys
from PySide6 import QtWidgets, QtCore


def new_timer(description: str, hour: int, minutes: int) -> QtWidgets.QWidget:

    def remove_timer(layout: QtWidgets.QLayout, widget: QtWidgets.QWidget) -> None:
        layout.removeWidget(widget)
        widget.deleteLater()

    widget = QtWidgets.QWidget()
    layout = QtWidgets.QGridLayout(widget)

    label = QtWidgets.QLabel(description)
    edit_timer = QtWidgets.QTimeEdit(time=QtCore.QTime(hour, minutes))
    btn_remove = QtWidgets.QPushButton(text="Remove Timer")
    btn_remove.clicked.connect(lambda: remove_timer(layout, widget))

    layout.addWidget(label, 0, 0)
    layout.addWidget(edit_timer, 1, 0)
    layout.addWidget(btn_remove, 2, 0)

    return widget


class TimerWindow(QtWidgets.QMainWindow):
    def __init__(self) -> None:
        super().__init__()

        self.grid = QtWidgets.QGridLayout()
        self.grid.setSpacing(10)
        self.widget = QtWidgets.QWidget()
        self.layout = QtWidgets.QGridLayout(self.widget)

        # Mockup data
        self.timers = [
            new_timer("Alarme 1", 9, 15),
            new_timer("Alarme 2", 4, 15),
            new_timer("Alarme 3", 16, 20)
        ]
        for i, timer in enumerate(self.timers):
            self.layout.addWidget(timer, i, 0)

        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(self.widget)
        self.grid.addWidget(self.scroll, 3, 0)
        self.setLayout(self.grid)


if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    dialog = TimerWindow()
    dialog.show()
    sys.exit(app.exec())



RE: Dinamically adding widgets to layout [PySide6] - deanhystad - Jun-19-2023

You are using the same layout widget to position the scrolled area and things inside the scrolled area. You need two layout widgets. One to put the timers inside the widget that gets scrolled, and another to place the scrolled area. widget in the window.

QMainWindow provides a layout widget for you. You get to add 1 widget to this layout.
class TimerWindow(QtWidgets.QMainWindow):
    def __init__(self) -> None:
        super().__init__()
 
        self.grid = QtWidgets.QGridLayout()
        self.grid.setSpacing(10)
        self.widget = QtWidgets.QWidget()
        self.layout = QtWidgets.QGridLayout(self.widget)
 
        # Mockup data
        self.timers = [
            new_timer("Alarme 1", 9, 15),
            new_timer("Alarme 2", 4, 15),
            new_timer("Alarme 3", 16, 20)
        ]
        for i, timer in enumerate(self.timers):
            self.layout.addWidget(timer, i, 0)
 
        self.scroll = QtWidgets.QScrollArea()
        self.scroll.setWidgetResizable(True)
        self.scroll.setWidget(self.widget)
        self.setCentralWidget(self.scroll)   # Add scroll area widget to the main window.



RE: Dinamically adding widgets to layout [PySide6] - carecavoador - Jun-19-2023

Wonderful! That was precisely the solution to the problem. Thank you very much! Big Grin