1

I'm building a layout in pyqt5 where you can dynamically add or delete widgets. Below you can see a simplified version of my problem: after the successful deleting of the nested layout "nested_hbox" and its widgets it won't build up again and just shows an empty window.

Edit: In my real application I have a grid layout where you can dynamically add diagrams in shape of a matrix to view multiple incoming values from an interface. For that you can quantify the number of rows and columns. So, the grid must be refreshed, when the user actuates a button.

import sys
from PyQt5.QtWidgets import *

class Window(QWidget):

    def __init__(self):
        super().__init__()
        self.layouts = []
        self.main_content_ui()
        self.init_ui()

    def main_content_ui(self):
        """Build up content for the main layout "vbox" """

        self.lbl_hello = QLabel()
        self.lbl_hello.setObjectName("lbl_hello")
        self.lbl_hello.setText("Hello StackOverflow")

        self.btn_reset_ui = QPushButton()
        self.btn_reset_ui = QPushButton()
        self.btn_reset_ui.setObjectName("btn_reset_ui")
        self.btn_reset_ui.clicked.connect(self.reset_ui)
        self.btn_reset_ui.setText("Reset UI")

        self.nested_hbox = QHBoxLayout()
        self.nested_hbox.setObjectName("nested_hbox")
        self.nested_hbox.addWidget(self.lbl_hello)
        self.nested_hbox.addWidget(self.btn_reset_ui)
        self.layouts.append(self.layouts)

        # main layout
        self.vbox = QVBoxLayout()
        self.vbox.setObjectName("vbox_main")
        self.layouts.append(self.vbox)
        self.vbox.addLayout(self.nested_hbox)

    def init_ui(self):
        """Set "vbox" as main layout
        """
        self.setLayout(self.vbox)
        self.show()

    def delete_layout(self, layout):
        """Delete all layouts from list "layouts"
        """
        try:
            while layout.count():
                item = layout.takeAt(0) 
                widget = item.widget() 
                if widget is not None: 
                    widget.deleteLater() 
                else: 
                    self.delete_layout(item.layout())
        except Exception as e:
            print(e)

    def reset_ui(self):
        """Clear and reinitalize main layouts content"""

        for lay in self.layouts:
            self.delete_layout(lay)
        print("Layout deleted rebuild layout")
        self.main_content_ui()
        self.vbox.update()
        QMainWindow.update(self)

app = QApplication(sys.argv)
ex = Window()
sys.exit(app.exec_())

I expect the same Window as before clicking the reset-button but the window doesn't show anything.

DasUrinal
  • 11
  • 1
  • 3
  • You are deleting your widgets from the layout why should they re-appear when you hit reset? – Isma Jun 12 '19 at 17:42
  • I thought they would re-appear if i call the `main_content_ui()` methode again. This function gets called by `reset_ui`. – DasUrinal Jun 12 '19 at 18:33
  • @DasUrinal From what I understand, the reset you want is just to delete all the widgets and color other widgets that are the same type. Why do not you simply set new properties to the widgets? – eyllanesc Jun 12 '19 at 21:18
  • In my real application I have a grid layout where you can dynamically add diagrams in shape of a matrix to view multiple incoming values from an interface. For that you can quantify the number of rows and columns. So, the grid must be refreshed, when the user actuates a button. – DasUrinal Jun 13 '19 at 13:47

1 Answers1

1

There's a nice way presented by Qt Wiki on how to make your application restartable https://wiki.qt.io

EXIT_CODE_REBOOT = -11231351

def main():
    exitCode = 0
    while True:
        try: app = QApplication(sys.argv)
        except RuntimeError: app = QApplication.instance()
        window = MainUI()
        window.show()
        exitCode = app.exec_()
        if exitCode != EXIT_CODE_REBOOT: break
    return exitCode
Isma
  • 14,604
  • 5
  • 37
  • 51
Larissa
  • 21
  • 1
  • Mhh thanks but I don't want to restart the whole application. Just rebuild the contents of vbox (ObjectName: vobox_main). – DasUrinal Jun 12 '19 at 14:01
  • Very nice way, but I noticed two errors: 1) the `try`/`except` block should be above the `while` block, otherwise the app will crash even at the first reboot signal. 2) after the `app.exec_()` method call, the previous form should be closed with a call to `window.close()`, otherwise you will create another instance of the form. At the second reboot, a third one will be created, and so on, and so forth. Hope I was helpful! – jinzo78 Nov 02 '21 at 23:00
  • This work for PySide2. however, for PyQt5, I think a `app=None` is needed, referring to [this answer](https://stackoverflow.com/a/34372471/9758790). And for PyQt5, I think perhaps this `try...except...` is unnecessary, just use `app = QApplication(sys.argv)` works fine. – hellohawaii Jul 12 '22 at 04:12