Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Widget class from pyside2-uic ui class not shown when adding to a tab widget



  • Hi! This is probably a dumb question. I am new to PySide2.

    I created a ui class with pyside2-uic after creating a ui file in the designer manually.
    Then, I created a widget class from the ui class like that:

    from PySide2.QtWidgets import QWidget
    
    from ui_main import Ui_main_widget
    
    
    class WUIMain(QWidget):
    
        def __init__(self):
            super(WUIMain, self).__init__()
            self.ui = Ui_main_widget()
            self.ui.setupUi(self)
    

    And I am using it in MainWindow:

    # ...
    class MainWindow(QMainWindow):
    
        def __init__(self):
            super(MainWindow, self).__init__()
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
            self.ui_main = WUIMain()
            self.ui.classes_tab_widget.setCurrentWidget(self.ui_main)
    
    

    The widget of the current tab stays blank. Any ideas, what I could have missed?
    Adding a new tab with it works. Recreating the tab would be possible but a bit bad design.

    EDIT
    The problem does not rely on the ui_main thing, it has to do with the tab widget itself. The following code does not show a button:

    from PySide2.QtWidgets import QMainWindow
    from PySide2.QtWidgets import QPushButton
    
    from ui_main_window import Ui_MainWindow
    
    
    class MainWindow(QMainWindow):
    
        def __init__(self):
            QMainWindow.__init__(self)
            self.ui = Ui_MainWindow()
            self.ui.setupUi(self)
    
            print(self.ui.classes_tab_widget.currentIndex()) # prints 0
            self.my_button = QPushButton('hi!')
            self.ui.classes_tab_widget.setCurrentWidget(self.my_button)
    

    Thank you!



  • @Niagarer said in Widget class from pyside2-uic ui class not shown when adding to a tab widget:

    self.my_button = QPushButton('hi!')
    self.ui.classes_tab_widget.setCurrentWidget(self.my_button)

    I don't understand what you think you are doing here?! I think you are misunderstanding how a QTabWidget works. https://doc.qt.io/qt-5/qtabwidget.html#setCurrentWidget:

    Makes widget the current widget. The widget used must be a page in this tab widget.

    But you are trying to set the QTabWidget's current widget to a QPushButton you have just created, which is most certainly not " a page in this tab widget"! :) Your current setCurrentWidget(self.my_button) is silently doing nothing.

    For a QTabWidget you want a number of plain QWidgets to be created as "pages" via https://doc.qt.io/qt-5/qtabwidget.html#addTab. It it is one of those QWidgets which you must pass to setCurrentWidget() to make that one be the current, visible one. You add widgets you create like a QPushButton onto one of those page widgets (and you will probably want to add a layout onto each of the page widgets to hold its child widgets).

    Not that this is not the way to do it long-term, but from where you are now so that you understand you should see your button somewhere on the current page widget (you say you have created one in the designer since self.ui.classes_tab_widget.currentIndex() == 0) if you try, say:

    self.my_button = QPushButton('hi!')
    
    page = self.ui.classes_tab_widget.currentWidget()
    
    if page is None:    # in your case you probably don't need this bit by the sound of it
        page = QWidget()
        self.ui.classes_tab_widget.addTab(page, "Label")
        self.ui.classes_tab_widget.setCurrentWidget(page)
    
    if page.layout() is None:    # and you may not need this
        page.setLayout(QVBoxLayout())
    
    page.layout().addWidget(self.my_button)
    

    Not that it matters, but your issue has nothing to do with PyQt/Python, or your use of Qt Designer.

    And there is absolutely nothing wrong with using plain super(), I and others do it all the time and it is recommended by the official https://docs.python.org/3/library/functions.html#super:

    In a class hierarchy with single inheritance, super can be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use closely parallels the use of super in other programming languages.

    The need to use ParentClass.__init__(self) instead of super().__init__() was in Python 2. Since you are using Python 3 not Python 2, and since you are only using it in a single-inheritance situation inside a method here, it is fine.


  • Banned

    First the absolutely only serious question that is a dumb question is the unasked one ;-)

    Next for the quickest help it is always best to provide an MRE (Minimal Reproducible Example) as then we can just copy/paste run it see what your issue is and help you fix it

    Next do you understand fully what super( ) does or are you just following the misguided in using it. I ask that because unless you are aware of the 3 issues you need to be aware of when using super( ) you are only hurting yourself by using it. Further not using super( ) only carries with a single rather rare issue which was the reason for the more dangerous super( ) to be created. How to fix it is shown below

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

    Lastly looking at the code snippets you provided means it is going to be like shooting in the dark because it kind of depends on what is housed within Ui_main_widget definition and especially the Ui_MainWindow definition



  • @Denni-0
    Sorry for the confusion, I didn't provide more because the problem does not rely on the ui_main thing. I will just update the question. I changed the super statements as you suggested, I can't tell where your notation shouldn't work anymore right now so I will stick to that. I didn't know that there were these problems with pythons super so far, now I know.

    I also tried it with a simple QPushButton which doesn't work as well. What is preventing the tab widget to show the widgets?
    print(self.ui.classes_tab_widget.currentIndex()) prints 0, so the tab should be created at this point - just before I set the widget.


  • Banned

    @Niagarer actually you cannot say where the problem resides because you are focused on a specific area which is never a good thing to do -- note btw unless you have to use that QtDesigner UI I would stop using it -- because (1) you most likely are not using it for what it was designed for so you are just being lazy ;-) and (2) what it produces is not proper Python-Qt code (3) Creating black-box untouchable modules in a program is never a good idea if it can be avoided (4) Creating a GUI properly in Python-Qt is actually surprisingly easy, straight forward and when you are done you have a much better understanding of what you have and can easily modify it later on.

    If you need help with learning how to do that I run a free python-qt class just shoot me a PM and I will give you the details -- or I can attempt to help you with that here either is fine by me the classroom-like thing is just faster generally.

    But back to your issue -- part of the problem may actually have to do with the Ui_MainWindow and how it was designed but I would have to see that to be sure. I will see if I can create a MUC (Minimal Usable Code) of potentially what you are doing and see if I can show how it ought to be done then you will need to figure out how to get that to work with your untouchable code or learn to code python-qt properly.



  • @Niagarer said in Widget class from pyside2-uic ui class not shown when adding to a tab widget:

    self.my_button = QPushButton('hi!')
    self.ui.classes_tab_widget.setCurrentWidget(self.my_button)

    I don't understand what you think you are doing here?! I think you are misunderstanding how a QTabWidget works. https://doc.qt.io/qt-5/qtabwidget.html#setCurrentWidget:

    Makes widget the current widget. The widget used must be a page in this tab widget.

    But you are trying to set the QTabWidget's current widget to a QPushButton you have just created, which is most certainly not " a page in this tab widget"! :) Your current setCurrentWidget(self.my_button) is silently doing nothing.

    For a QTabWidget you want a number of plain QWidgets to be created as "pages" via https://doc.qt.io/qt-5/qtabwidget.html#addTab. It it is one of those QWidgets which you must pass to setCurrentWidget() to make that one be the current, visible one. You add widgets you create like a QPushButton onto one of those page widgets (and you will probably want to add a layout onto each of the page widgets to hold its child widgets).

    Not that this is not the way to do it long-term, but from where you are now so that you understand you should see your button somewhere on the current page widget (you say you have created one in the designer since self.ui.classes_tab_widget.currentIndex() == 0) if you try, say:

    self.my_button = QPushButton('hi!')
    
    page = self.ui.classes_tab_widget.currentWidget()
    
    if page is None:    # in your case you probably don't need this bit by the sound of it
        page = QWidget()
        self.ui.classes_tab_widget.addTab(page, "Label")
        self.ui.classes_tab_widget.setCurrentWidget(page)
    
    if page.layout() is None:    # and you may not need this
        page.setLayout(QVBoxLayout())
    
    page.layout().addWidget(self.my_button)
    

    Not that it matters, but your issue has nothing to do with PyQt/Python, or your use of Qt Designer.

    And there is absolutely nothing wrong with using plain super(), I and others do it all the time and it is recommended by the official https://docs.python.org/3/library/functions.html#super:

    In a class hierarchy with single inheritance, super can be used to refer to parent classes without naming them explicitly, thus making the code more maintainable. This use closely parallels the use of super in other programming languages.

    The need to use ParentClass.__init__(self) instead of super().__init__() was in Python 2. Since you are using Python 3 not Python 2, and since you are only using it in a single-inheritance situation inside a method here, it is fine.



  • @JonB
    Oh really? I didn't quite get the page thing, that's the missing piece. I just misinterpreted this method, thank you! And once again Qt's doc rules. As long as you read the detailed class description too where this is explained in detail :) My bad. I'm sorry.
    https://doc.qt.io/qt-5/qtabwidget.html#details
    I used super() so far too since it's used also in Qt's documentation.
    @JonB said in Widget class from pyside2-uic ui class not shown when adding to a tab widget:

    The need to use ParentClass.__init__(self) instead of super().__init__() was in Python 2. Since you are using Python 3 not Python 2, and since you are only using it in a single-inheritance situation inside a method here, it is fine.

    Multi-inheritance should be fine too actually I guess, as long as you follow the __mro__ order correctly. This post could be useful

    @Denni-0 said in Widget class from pyside2-uic ui class not shown when adding to a tab widget:

    @Niagarer note btw unless you have to use that QtDesigner UI I would stop using it -- because (1) you most likely are not using it for what it was designed for so you are just being lazy ;-) and (2) what it produces is not proper Python-Qt code (3) Creating black-box untouchable modules in a program is never a good idea if it can be avoided (4) Creating a GUI properly in Python-Qt is actually surprisingly easy, straight forward and when you are done you have a much better understanding of what you have and can easily modify it later on.

    I just convert my UI files to python scripts with PySide2-uic. Is there something wrong with that? The code looks pretty efficient to me...



  • @Niagarer said in Widget class from pyside2-uic ui class not shown when adding to a tab widget:

    I just convert my UI files to python scripts with PySide2-uic. Is there something wrong with that? The code looks pretty efficient to me...

    I think it and using Qt Designer is fine, with about the same advantages & disadvantages as other GUI designers. @Denni-0 strongly objects to it. It basically boils down to whether you want a GUI designer or prefer to code your UI dynamically yourself, they both have pros & cons.


Log in to reply