Search code examples
pythonpyqt6

QlistWidget won't show in a custom QFrame


I can't get ModMergeFrame frame to show the self.mod_list. I have tried reading the docs and examples, but failed to understand and fix the problem.

Below code in ModMergeFrame class works correcty. Displaying the self.mod_list.count() returns 2, as expected. So the list item is being created and populated. The two QPushButtons are visible as well, but the QListWidget is not.

Putting the same object in the centralwidget of MainWindow displayes it correctly though

class CommonFrame(QFrame):
    """ Common frame that will be used as a base for all other frames """
    def __init__(self, parent, settings, objectName):
        super().__init__(parent, objectName=objectName)
        layout = QGridLayout(self)
        self.setLayout(layout)
        self.hide()
        self.settings = settings

class ModMergeFrame(CommonFrame):
    """ Mod merge frame that will be displayed in the main application window """
    def __init__(self, parent, settings):
        super().__init__(parent, settings, objectName="Mod merge")
        test_button = QPushButton(self.objectName(), self)
        self.layout().addWidget(test_button)

        test_button = QPushButton("13", self)
        self.layout().addWidget(test_button)

        # Mod list for selection of mods to merge
        self.mod_list = QListWidget(self)
        self.mod_list.additems(["bla", "bla2"])
        self.layout().addWidget(self.mod_list)

class MainWindow(QMainWindow):
    """ Main application window """
    def __init__(self, settings):
        try:
            QMainWindow.__init__(self)
            self.settings = settings

            self.setMinimumSize(QSize(700, 700))
            self.setWindowTitle("Bla")

            toolbar = QToolBar("Main toolbar")
            self.addToolBar(toolbar)

            central_widget = QWidget(self)
            central_widget_layout = QVBoxLayout(central_widget)


            # Generate frames. Those come from custom QFrame-based classes
            # Can be toggled with toolbar and are displayed in the central widget
            self.generate_mod_merge_frame(central_widget_layout, toolbar)

            central_widget.setLayout(central_widget_layout)
            self.setCentralWidget(central_widget)

        except Exception as exc:
            traceback_formatted = traceback.format_exc()
            logger.info(traceback_formatted)
            raise RuntimeError(traceback_formatted) from exc

    def generate_mod_merge_frame(self, central_widget_layout, toolbar):
        """ Generates main window frame with a given name """
        frame_name = "Mod merge"
        frame = ModMergeFrame(self, self.settings)

        frame_action = QAction(frame_name, self)
        frame_action.setStatusTip(frame_name)
        frame_action.triggered.connect(
            lambda checked, frame_name=frame_name: self.show_frame_by_name(frame_name)
        )

        central_widget_layout.addWidget(frame)
        toolbar.addAction(frame_action)

Solution

  • Please explain better what's wrong?

    import sys
    from PyQt5 import QtCore, QtGui, QtWidgets
    from PyQt5.Qt import * 
    
    
    class CommonFrame(QFrame):
        """ Common frame that will be used as a base for all other frames """
        def __init__(self, parent, settings, objectName):
            super().__init__(parent, objectName=objectName)
            layout = QGridLayout(self)
            self.setLayout(layout)
    # ?        self.hide()                                                   # ???
            self.settings = settings                                         # ?
    
    
    class ModMergeFrame(CommonFrame):
        """ Mod merge frame that will be displayed in the main application window """
        def __init__(self, parent, settings):
            super().__init__(parent, settings, objectName="Mod merge")
            test_button = QPushButton(self.objectName(), self)
            self.layout().addWidget(test_button)
    
            test_button = QPushButton("13", self)
            self.layout().addWidget(test_button)
    
            # Mod list for selection of mods to merge
            self.mod_list = QListWidget(self)
            
    #        self.mod_list.additems(["bla", "bla2"])                          # - additems
            self.mod_list.addItems(["bla", "bla2"])                           # + addItems
            
            self.layout().addWidget(self.mod_list)
    
    
    class MainWindow(QMainWindow):
        """ Main application window """
        def __init__(self, settings=42):                                   # ??? settings
            try:
                QMainWindow.__init__(self)
                self.settings = settings
    
    # ?            self.setMinimumSize(QSize(600, 600))
                self.setWindowTitle("Bla")
    
                toolbar = QToolBar("Main toolbar")
                self.addToolBar(toolbar)
    
                central_widget = QWidget(self)
                central_widget_layout = QVBoxLayout(central_widget)
    
                # Generate frames. Those come from custom QFrame-based classes
                # Can be toggled with toolbar and are displayed in the central widget
                self.generate_mod_merge_frame(central_widget_layout, toolbar)
    
                central_widget.setLayout(central_widget_layout)
                self.setCentralWidget(central_widget)
    
            except Exception as exc:
                traceback_formatted = traceback.format_exc()
                logger.info(traceback_formatted)
                raise RuntimeError(traceback_formatted) from exc
    
        def generate_mod_merge_frame(self, central_widget_layout, toolbar):
            """ Generates main window frame with a given name """
            frame_name = "Mod merge"
            frame = ModMergeFrame(self, self.settings)
    
            frame_action = QAction(frame_name, self)
            frame_action.setStatusTip(frame_name)
            frame_action.triggered.connect(          # vvvvvvvvvvvvvvvvvvvvvvv ??? <----
                lambda checked, frame_name=frame_name: self.show_frame_by_name(frame_name)
            )
    
            central_widget_layout.addWidget(frame)
            toolbar.addAction(frame_action)
            
        def show_frame_by_name(self, frame_name):                              # +++
            print(f'{self}') 
            print(f'{frame_name}\n') #
            
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        window = MainWindow()
        window.show()
        sys.exit(app.exec())
    

    enter image description here