Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Forum Updated on Feb 6th

    Solved Qt Creator and Pyside2 - Blank Window

    Qt for Python
    5
    18
    2647
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • M
      Marcus Adamski last edited by

      Hello there,

      Just started experimenting with Pyside2 for use with a new Python project. Initially I was looking at using Qt Creator and loading the ".ui" file (no conversion) - but I simply cannot get the resulting window to display any widgets?

      Using the Qt Creator I created a project, which automatically added a QDialogue ui file and included the code to load and run the window. I simply added a PushButton - then run the project. Just see a blank window.

      I can successfully create gui's "manually" using Pyside2, so I know the framework is working. I just cannot load a UI file and show it? Tried multiple different projects.

      For completeness, I've added the code loading the UI file - I guess this is a common issue, can you please let me know what I'm doing wrong:

      # This Python file uses the following encoding: utf-8
      import sys
      import os
      
      from PySide2 import QtWidgets
      from PySide2.QtCore import QFile
      from PySide2.QtUiTools import QUiLoader
      
      
      class main(QtWidgets.QDialog):
          def __init__(self):
              super(main, self).__init__()
              self.load_ui()
      
          def load_ui(self):
              loader = QUiLoader()
              path = os.path.join(os.path.dirname(__file__), "form.ui")
              ui_file = QFile(path)
              ui_file.open(QFile.ReadOnly)
              loader.load(ui_file, self)
              ui_file.close()
      
      
      if __name__ == "__main__":
          app = QtWidgets.QApplication([])
          widget = main()
          widget.show()
          sys.exit(app.exec_())
      

      Thanks for your help.

      JonB 1 Reply Last reply Reply Quote 0
      • JonB
        JonB @Marcus Adamski last edited by JonB

        @Marcus-Adamski
        Now going all the way back to your original Designer UI files, and why your code works with a QWidget but not with a QMainWindow.

        In your QMainWindow .ui file you have:

          <widget class="QWidget" name="centralwidget">
           <widget class="QPushButton" name="pushButton">
        

        This is not right, and Designer will be showing you a warning "no-entry" marker on centralwidget in the pane where it shows your widget hierarchy. You ignore this at your peril! Layout will "go wrong" if you make a QWidget a direct child on another (non-container) QWidget such as QMainWindow.centralWidget without you putting in a layout. The same would happen if you did this in your own code, though you wouldn't get any warning.

        Go back into Designer and give your central widget a layout: in the widget hierarchy pane, right-click on main_window, pick Lay out, pick Lay Out Horizontally.

        Now, to make it work in the QMainWindow case: I originally told you:

        @Marcus-Adamski
        PySide 2 QUiLoader().load() returns a widget you need to show().
        https://stackoverflow.com/questions/50128293/pyside2-quiloader-returns-an-empty-window

        but you did not act on this. You need to change two lines:

        loader.load(ui_file, self).show()
        # widget.show()
        

        So, I have made the return result from loader.load(ui_file, self) be the widget to call show() on, and got rid of your show() on the object constructed via main_window(). Once you see that works you can tidy the code to do this in a better way.

        You should get the push button visible as you do in the plain QWidget-non-QMainWindow case. You can then continue to use the Designer for your application if you wish to, as many do.

        1 Reply Last reply Reply Quote 0
        • JonB
          JonB @Marcus Adamski last edited by JonB

          @Marcus-Adamski
          PySide 2 QUiLoader().load() returns a widget you need to show().
          https://stackoverflow.com/questions/50128293/pyside2-quiloader-returns-an-empty-window

          1 Reply Last reply Reply Quote 1
          • M
            Marcus Adamski last edited by

            Thanks very much - I'll try tomorrow morning. The code I supplied was directly generated by Qt Creator ... strange it doesn't work?

            I'll reply back once I've tested your suggestion.

            JonB 1 Reply Last reply Reply Quote 0
            • JonB
              JonB @Marcus Adamski last edited by JonB

              @Marcus-Adamski
              It's only a suggestion :) If it was generated by Creator I agree it would be odd. Compare your generated code to what they are saying in that post. Now that I look at it, maybe you/it are doing the show(), have a play with your loader.load(ui_file, self) line.

              1 Reply Last reply Reply Quote 0
              • M
                Marcus Adamski last edited by

                OK - this is the currently situation. Using the latest QT Creator and just PySide2 installed,

                1. when creating a new project, and selecting "Qt for Python - Window (UI) file and "QMainWindow" as the base class, the following code is autogenerated (I've not modified it):
                # This Python file uses the following encoding: utf-8
                import sys
                import os
                
                
                from PySide2.QtWidgets import QApplication, QMainWindow
                from PySide2.QtCore import QFile
                from PySide2.QtUiTools import QUiLoader
                
                
                class main_window(QMainWindow):
                    def __init__(self):
                        super(main_window, self).__init__()
                        self.load_ui()
                
                    def load_ui(self):
                        loader = QUiLoader()
                        path = os.path.join(os.path.dirname(__file__), "form.ui")
                        ui_file = QFile(path)
                        ui_file.open(QFile.ReadOnly)
                        loader.load(ui_file, self)
                        ui_file.close()
                
                if __name__ == "__main__":
                    app = QApplication([])
                    widget = main_window()
                    widget.show()
                    sys.exit(app.exec_())
                

                When run, I only get a blank window. To me, it appears the UI file is not being loaded and associated to QMainWindow. Experimenting, in the designer, I've changed the window title and added one button, but when run, neither change is shown on the resulting blank window.

                1. However, instead, if I select "QWidget" as my base class, apart from the imports, the same code is geneated, but this works. (Again this code has not be altered):
                # This Python file uses the following encoding: utf-8
                import sys
                import os
                
                
                from PySide2.QtWidgets import QApplication, QWidget
                from PySide2.QtCore import QFile
                from PySide2.QtUiTools import QUiLoader
                
                
                class main_window(QWidget):
                    def __init__(self):
                        super(main_window, self).__init__()
                        self.load_ui()
                
                    def load_ui(self):
                        loader = QUiLoader()
                        path = os.path.join(os.path.dirname(__file__), "form.ui")
                        ui_file = QFile(path)
                        ui_file.open(QFile.ReadOnly)
                        loader.load(ui_file, self)
                        ui_file.close()
                
                if __name__ == "__main__":
                    app = QApplication([])
                    widget = main_window()
                    widget.show()
                    sys.exit(app.exec_())
                
                

                Could someone please explain why the QMainWindow based autogenerated code doesn't work, but the QWidget code does?

                Many thanks

                1 Reply Last reply Reply Quote 0
                • SGaist
                  SGaist Lifetime Qt Champion last edited by

                  Hi,

                  Can you share the UI code as well ?

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  1 Reply Last reply Reply Quote 0
                  • M
                    Marcus Adamski last edited by

                    Sure, the following is the UI for QWidget.

                    <?xml version="1.0" encoding="UTF-8"?>
                    <ui version="4.0">
                     <class>main_window</class>
                     <widget class="QWidget" name="main_window">
                      <property name="geometry">
                       <rect>
                        <x>0</x>
                        <y>0</y>
                        <width>800</width>
                        <height>600</height>
                       </rect>
                      </property>
                      <property name="windowTitle">
                       <string>main_window</string>
                      </property>
                      <widget class="QPushButton" name="pushButton">
                       <property name="geometry">
                        <rect>
                         <x>40</x>
                         <y>40</y>
                         <width>75</width>
                         <height>23</height>
                        </rect>
                       </property>
                       <property name="text">
                        <string>PushButton</string>
                       </property>
                      </widget>
                     </widget>
                     <resources/>
                     <connections/>
                    </ui>
                    

                    ... and for the QMainApplication:

                    <?xml version="1.0" encoding="UTF-8"?>
                    <ui version="4.0">
                     <class>main_window</class>
                     <widget class="QMainWindow" name="main_window">
                      <property name="geometry">
                       <rect>
                        <x>0</x>
                        <y>0</y>
                        <width>800</width>
                        <height>600</height>
                       </rect>
                      </property>
                      <property name="windowTitle">
                       <string>main_window</string>
                      </property>
                      <widget class="QWidget" name="centralwidget">
                       <widget class="QPushButton" name="pushButton">
                        <property name="geometry">
                         <rect>
                          <x>70</x>
                          <y>80</y>
                          <width>75</width>
                          <height>23</height>
                         </rect>
                        </property>
                        <property name="text">
                         <string>PushButton</string>
                        </property>
                       </widget>
                      </widget>
                      <widget class="QMenuBar" name="menubar">
                       <property name="geometry">
                        <rect>
                         <x>0</x>
                         <y>0</y>
                         <width>800</width>
                         <height>21</height>
                        </rect>
                       </property>
                      </widget>
                      <widget class="QStatusBar" name="statusbar"/>
                     </widget>
                     <resources/>
                     <connections/>
                    </ui>
                    

                    On both projects, in the above UIs the only change is the addition of a single pushbutton to identify the window

                    JonB 1 Reply Last reply Reply Quote 0
                    • M
                      Marcus Adamski last edited by Marcus Adamski

                      Actually, for QMainWindow, I don't think PySide2 allows the UI file to be loaded from within the constructor.

                      1 Reply Last reply Reply Quote 0
                      • Denni 0
                        Denni 0 Banned last edited by Denni 0

                        Note using the Creator or Designer produces XML code which does not play nicely with Python-Qt and unless you really need XML code for you GUI I would strongly suggest you learn to use Python-Qt the way it was meant to be used by coding it straight up. It is really easy and when you are done you will understand what you have and how to tweak it to make it do more things where as that XML code is just going to be an unnecessary (unless you do need that XML code for some reason) and constant pain (regardless) for you. I got your code to display your UI and found that it is just a simple button so I have created 2 versions of that button window -- one that uses the QMainWindow (which has a status bar) and a QWidget (that does not have that status bar) but in I have designed in a collaborative manner which you cannot do with the Creator/Designer as it does not allow for that nor a lot of other things you might want to do with your code.

                        from PySide2.QtWidgets import QApplication, QMainWindow, QWidget
                        from PySide2.QtWidgets import QHBoxLayout, QVBoxLayout, QPushButton
                        
                        # Always declare all other imports after Qt imports to prevent the 
                        # issue of miss association that sometimes occurs with Qt
                        from sys import exit as sysExit
                        
                        class MainUI(QWidget):
                            def __init__(self, parent=None):
                                QWidget.__init__(self)
                                self.Parent = parent
                                if self.Parent == None:
                                    self.setWindowTitle('Da Pusher')
                                    WinLeft = 550; WinTop = 350; WinWidth = 800; WinHigh = 600
                                    self.setGeometry(WinLeft, WinTop, WinWidth, WinHigh)
                        
                                self.btnPusher = QPushButton('Push')
                                self.btnPusher.clicked.connect(self.Pushed)
                                BtnWdth = 75; BtnHght = 23
                                self.btnPusher.setFixedSize(BtnWdth, BtnHght)
                                
                                HBox = QHBoxLayout()
                                HBox.addStretch(1)
                                HBox.addWidget(self.btnPusher)
                                HBox.addStretch(1)
                        
                                VBox = QVBoxLayout()
                                VBox .addStretch(1)
                                VBox .addLayout(HBox)
                                VBox .addStretch(1)
                                
                                self.setLayout(VBox)
                                
                            def Pushed(self):
                                if self.Parent == None:
                                    print('Stop pushing me.')
                                else:
                                    self.Parent.SetStatus('Stop Pushing Me')
                        
                        class MainWindow(QMainWindow):
                            def __init__(self):
                              # One should not use super( ) in Python as it introduces 4 known issues that
                              # must be handled properly. Further there were still actual bugs within the
                              # usage of super( ) when used in Python. Yes while super( ) works fine within
                              # C++ it does not work as seamlessly within Python due to the major differences 
                              # between these 2 languages. Next the reason it was created was to handle a 
                              # rather rare issue and unless you are doing some complicated inheritance you
                              # will most likely never run into this extremely rare issue. However the 4 
                              # major issues that get included by using super( ) you are much more likely 
                              # to occur than that rare issue its meant for to solve. Of course using the 
                              # basic explicit method, as follows, does not cause these issues and is as just 
                              # just as simple as using `super( )` further you do not actually gain anything 
                              # useful by using `super( )` in Python that could not be done in a much safer 
                              # manner
                                QMainWindow.__init__(self)
                                self.setWindowTitle('Da Pusher')
                                WinLeft = 550; WinTop = 350; WinWidth = 800; WinHigh = 600
                                self.setGeometry(WinLeft, WinTop, WinWidth, WinHigh)
                        
                                self.CenterPane = MainUI(self)
                                self.setCentralWidget(self.CenterPane)
                                
                                self.StatBar = self.statusBar()
                                self.SetStatus('Ready')
                                
                            def SetStatus(self, StatusMsg):
                                if len(StatusMsg) > 0:
                                    self.StatBar.showMessage(StatusMsg)
                        
                        if __name__ == "__main__":
                            MainEvntThred = QApplication([])
                        
                          # You comment out either line they work together or independently
                          # However the QWidget I do not think comes with a StatusBar
                        #    MainApp = MainUI()
                            MainApp = MainWindow()
                            MainApp.show()
                        
                            sysExit(MainEvntThred.exec_())
                        
                        1 Reply Last reply Reply Quote 0
                        • M
                          Marcus Adamski last edited by

                          Thanks @Denni-0 for the valuable input. It's really helpful to have a solid template from which to explore the rest of Qt. I planned to use Qt Designer to get the feel of how the Qt framework behaves, then start coding the UI by hand. Right - next step, become more familiar with the Qt layouts

                          Thanks again

                          1 Reply Last reply Reply Quote 0
                          • M
                            Marcus Adamski last edited by

                            Just ran your code - initially got the error "'MainWindow' object has no attribute 'SetStatusBar'".
                            However, after commenting out the following lines:

                                 #self.StatBar = self.statusBar()
                                 #self.SetStatusBar('Ready')
                            

                            and running the code, unfortunately a single window is displayed with the title "Da Pusher" .... but there's no button, just a blank window.

                            window.jpg

                            Have to pop out now - will take another look at the code this evening.

                            Just out of interested, why does QWidget check:

                            if self.Parent == None:
                            

                            is this so the QWidget can also run as an individual window if needed?

                            Thanks

                            JonB 1 Reply Last reply Reply Quote 0
                            • JonB
                              JonB @Marcus Adamski last edited by JonB

                              @Marcus-Adamski
                              In the code you have been given there are a couple of mistakes.

                              Apart from the self.SetStatusBar you noted, the problem you see stems from:

                                      VBox = QVBoxLayout()
                                      HBox.addStretch(1)
                                      HBox.addLayout(HBox)
                                      HBox.addStretch(1)
                              

                              This gives a warning "QLayout: Cannot add layout QHBoxLayout/ to itself", and under Linux dumps core on exit from the app.

                              If you correct this to:

                                      VBox = QVBoxLayout()
                                      VBox.addStretch(1)
                                      VBox.addLayout(HBox)
                                      VBox.addStretch(1)
                              

                              the problems go away, and you will see the push button.

                              1 Reply Last reply Reply Quote 1
                              • JonB
                                JonB @Marcus Adamski last edited by JonB

                                @Marcus-Adamski
                                Now going all the way back to your original Designer UI files, and why your code works with a QWidget but not with a QMainWindow.

                                In your QMainWindow .ui file you have:

                                  <widget class="QWidget" name="centralwidget">
                                   <widget class="QPushButton" name="pushButton">
                                

                                This is not right, and Designer will be showing you a warning "no-entry" marker on centralwidget in the pane where it shows your widget hierarchy. You ignore this at your peril! Layout will "go wrong" if you make a QWidget a direct child on another (non-container) QWidget such as QMainWindow.centralWidget without you putting in a layout. The same would happen if you did this in your own code, though you wouldn't get any warning.

                                Go back into Designer and give your central widget a layout: in the widget hierarchy pane, right-click on main_window, pick Lay out, pick Lay Out Horizontally.

                                Now, to make it work in the QMainWindow case: I originally told you:

                                @Marcus-Adamski
                                PySide 2 QUiLoader().load() returns a widget you need to show().
                                https://stackoverflow.com/questions/50128293/pyside2-quiloader-returns-an-empty-window

                                but you did not act on this. You need to change two lines:

                                loader.load(ui_file, self).show()
                                # widget.show()
                                

                                So, I have made the return result from loader.load(ui_file, self) be the widget to call show() on, and got rid of your show() on the object constructed via main_window(). Once you see that works you can tidy the code to do this in a better way.

                                You should get the push button visible as you do in the plain QWidget-non-QMainWindow case. You can then continue to use the Designer for your application if you wish to, as many do.

                                1 Reply Last reply Reply Quote 0
                                • Denni 0
                                  Denni 0 Banned last edited by Denni 0

                                  Sorry for the errors I cannot run PySide2 and I am guessing I forgot to test this before posting

                                  1. Fixed the SetStatusBar( ) mistake
                                  2. Fixed the HBox calling HBox mistake

                                  The reason it checks if self.Parent == None is because you have 2 choices in this template you can either start it by calling MainApp = MainWindow() which then calls the MainUI class or you can start it by calling MainApp = MainUI() by uncommenting that line out and commenting out the line that follows

                                  Okay I ran it after making the above changes using one then the other method of calling it and both work -- again my apologies for the errors must have gotten rushed

                                  1 Reply Last reply Reply Quote 0
                                  • M
                                    Marcus Adamski last edited by

                                    Thanks to both @JonB and @Denni-0 , I now have a solid template (and better understanding) to explore QT further. Much appreciated.

                                    1 Reply Last reply Reply Quote 0
                                    • Erriez
                                      Erriez last edited by Erriez

                                      I had the same problem with PySide6 on Ubuntu 22.04 and Windows 10: Creating a new project with QMainWindow does not work. See my question on StackOverflow.

                                      Complete fixed example:

                                      # This Python file uses the following encoding: utf-8
                                      import os
                                      from pathlib import Path
                                      import sys
                                      
                                      from PySide6.QtWidgets import QApplication, QMainWindow
                                      from PySide6.QtCore import QFile
                                      from PySide6.QtUiTools import QUiLoader
                                      
                                      
                                      class MainWindow(QMainWindow):
                                          def __init__(self, parent=None):
                                              super().__init__(parent)
                                              self.load_ui()
                                      
                                          def load_ui(self):
                                              loader = QUiLoader()
                                              path = Path(__file__).resolve().parent / "form.ui"
                                              ui_file = QFile(path)
                                              ui_file.open(QFile.ReadOnly)
                                      
                                      -        loader.load(ui_file, self)
                                      +        widget = loader.load(ui_file, self)
                                      
                                              ui_file.close()
                                      
                                      +        widget.show()
                                      
                                      
                                      if __name__ == "__main__":
                                          app = QApplication(sys.argv)
                                          widget = MainWindow()
                                      -    # widget.show()
                                          sys.exit(app.exec())
                                      

                                      As beginner I spent a lot of time to figure out why. Can someone please make the generated code functional in Qt Creator when creating a new project?

                                      JonB 1 Reply Last reply Reply Quote 0
                                      • JonB
                                        JonB @Erriez last edited by

                                        @Erriez said in Qt Creator and Pyside2 - Blank Window:

                                        Can you please fix this issue when creating a new project?

                                        Hi. What does this mean? If you mean can somebody here fix what Python code Designer generates you would have to report an issue to Qt developers, we are just a forum of users like yourself!

                                        Erriez 1 Reply Last reply Reply Quote 1
                                        • Erriez
                                          Erriez @JonB last edited by Erriez

                                          @JonB Yes, my question is for the Qt developers to fix the generated code in Qt Creator. I had a bad start when creating a new project which does not work out of the box.
                                          You're right, https://bugreports.qt.io is used to report bugs and not this forum. I'll follow-up here. Thanks!

                                          1 Reply Last reply Reply Quote 1
                                          • First post
                                            Last post