Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt for Python
  4. Make complete python script from Qt Designer
Forum Updated to NodeBB v4.3 + New Features

Make complete python script from Qt Designer

Scheduled Pinned Locked Moved Unsolved Qt for Python
4 Posts 2 Posters 2.6k Views
  • 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.
  • P Offline
    P Offline
    pascor
    wrote on last edited by
    #1

    I've created a complete python app starting from a MainWindow in Designer. It's loaded and run by a simple main wrapper which includes the MainWindow class py file import.

    import sys
    
    from PySide6.QtWidgets import QApplication
    
    from MainWindow import Ui_MainWindow
    
    app = QApplication(sys.argv)
    
    mainWindow = Ui_MainWindow()
    mainWindow.show()
    sys.exit(app.exec())
    

    However, I've been forced to hand edit the previously converted MainWindow python file so that the Ui_MainWindow class is based on a QMainWindow widget rather than the generic 'object' class that Designer automatically creates. I've also had to add an init() method.

    Designer bases its setupUi() method on a QMainWindow, but not its own Ui_MainWindow class definition. Is there a way to configure Designer to set the parent of the class to be a QMainWindow, too ?

    Hand edited from:

    class Ui_MainWindow(object):   # Why this?
        def setupUi(self, MainWindow):
    ...
    

    to:

    class Ui_MainWindow(QMainWindow):   # Why not this?
    
        def __init__(self, parent=None):
            super().__init__(parent)
            self.setupUi(self)
    
        def setupUi(self, MainWindow):  # Why not just 'self'?
    ...
    

    My edited MainWindow class works as expected, but I'd like Designer to outpu this in its .ui file to avoid this editing every time a new .ui file is saved.

    JonBJ 1 Reply Last reply
    0
    • P pascor

      I've created a complete python app starting from a MainWindow in Designer. It's loaded and run by a simple main wrapper which includes the MainWindow class py file import.

      import sys
      
      from PySide6.QtWidgets import QApplication
      
      from MainWindow import Ui_MainWindow
      
      app = QApplication(sys.argv)
      
      mainWindow = Ui_MainWindow()
      mainWindow.show()
      sys.exit(app.exec())
      

      However, I've been forced to hand edit the previously converted MainWindow python file so that the Ui_MainWindow class is based on a QMainWindow widget rather than the generic 'object' class that Designer automatically creates. I've also had to add an init() method.

      Designer bases its setupUi() method on a QMainWindow, but not its own Ui_MainWindow class definition. Is there a way to configure Designer to set the parent of the class to be a QMainWindow, too ?

      Hand edited from:

      class Ui_MainWindow(object):   # Why this?
          def setupUi(self, MainWindow):
      ...
      

      to:

      class Ui_MainWindow(QMainWindow):   # Why not this?
      
          def __init__(self, parent=None):
              super().__init__(parent)
              self.setupUi(self)
      
          def setupUi(self, MainWindow):  # Why not just 'self'?
      ...
      

      My edited MainWindow class works as expected, but I'd like Designer to outpu this in its .ui file to avoid this editing every time a new .ui file is saved.

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @pascor
      Because that is the way Designer intends it to be for PySide (or PyQt). The Ui_MainWindow is a "helper" class, which is designed to accept a widget (your MainWindow/QMainWindow) as a parameter which it fills in self.setupUi(self, MainWindow) with the design-time content. It also works like this from C++. It is not intended to be derived from QMainWindow.

      When you run pyuic or whatever it is [pyside6-uic] which parses the .ui file and produces the .py file from it you cannot alter this behaviour (unless you wrote your own equivalent of pyuic to produce what you want, which is a non-trivial task). Why should you want to? It works perfectly well as it is.

      If you have not already done so you should read Option A: Generating a Python class which explains how it works. Note that there is an alternative approach there, Option B: Loading it directly. That works by reading the .ui file at run-time instead of at design-time, and it produces a widget directly (via QUiLoader.load()) instead of a helper class. However I would not recommend it, you do not get any design-time support for the widgets you have added in Designer, and at run-time you do not get Python variables for those widgets, you have to use QObject.find(...) to find them dynamically and assign them to variables.

      However, I've been forced to hand edit the previously converted MainWindow python file so that the Ui_MainWindow class is based on a QMainWindow widget rather than the generic 'object' class that Designer automatically create

      Do not do this. It means you would lose all your work any time you make a change in Designer and need to run the pyuic again. Why did you feel you had to do so, other people work fine from Python or C++ with the way it works now with the helper class route?

      P.S.
      For your desired approach, there are ways of achieving it without you having to alter the generated .py file, which you should never do. See the following:

      https://stackoverflow.com/a/70067108/489865

      class MainWindow(QMainWindow, Ui_MainWindow):
          def __init__(self):
              super(MainWindow, self).__init__()
              self.setupUi(self)
      

      The above uses multiple inheritance --- the MainWindow class is a QMainWindow, but also inherits objects/methods from the Ui_MainWindow helper class. If you have designed a widget named widget you will access it from MainWindow via self.widget. It is like the way you changed to, but without altering the generated Ui_MainWindow class.

      https://stackoverflow.com/a/69625698/489865

      class UI(QtWidgets.QMainWindow):
          def __init__(self):
              super().__init__()
      
              self.ui = Ui_MainWindow()
              self.ui.setupUi(self)
      

      The above uses encapsulation --- the UI class is a QMainWindow, but it also contains a self.ui member which is the Ui_MainWindow helper class, you can access its objects/methods via self.ui. If you have designed a widget named widget you will access it from MainWindow via self.ui.widget. This is the way one does it from C++.

      P 1 Reply Last reply
      1
      • JonBJ JonB

        @pascor
        Because that is the way Designer intends it to be for PySide (or PyQt). The Ui_MainWindow is a "helper" class, which is designed to accept a widget (your MainWindow/QMainWindow) as a parameter which it fills in self.setupUi(self, MainWindow) with the design-time content. It also works like this from C++. It is not intended to be derived from QMainWindow.

        When you run pyuic or whatever it is [pyside6-uic] which parses the .ui file and produces the .py file from it you cannot alter this behaviour (unless you wrote your own equivalent of pyuic to produce what you want, which is a non-trivial task). Why should you want to? It works perfectly well as it is.

        If you have not already done so you should read Option A: Generating a Python class which explains how it works. Note that there is an alternative approach there, Option B: Loading it directly. That works by reading the .ui file at run-time instead of at design-time, and it produces a widget directly (via QUiLoader.load()) instead of a helper class. However I would not recommend it, you do not get any design-time support for the widgets you have added in Designer, and at run-time you do not get Python variables for those widgets, you have to use QObject.find(...) to find them dynamically and assign them to variables.

        However, I've been forced to hand edit the previously converted MainWindow python file so that the Ui_MainWindow class is based on a QMainWindow widget rather than the generic 'object' class that Designer automatically create

        Do not do this. It means you would lose all your work any time you make a change in Designer and need to run the pyuic again. Why did you feel you had to do so, other people work fine from Python or C++ with the way it works now with the helper class route?

        P.S.
        For your desired approach, there are ways of achieving it without you having to alter the generated .py file, which you should never do. See the following:

        https://stackoverflow.com/a/70067108/489865

        class MainWindow(QMainWindow, Ui_MainWindow):
            def __init__(self):
                super(MainWindow, self).__init__()
                self.setupUi(self)
        

        The above uses multiple inheritance --- the MainWindow class is a QMainWindow, but also inherits objects/methods from the Ui_MainWindow helper class. If you have designed a widget named widget you will access it from MainWindow via self.widget. It is like the way you changed to, but without altering the generated Ui_MainWindow class.

        https://stackoverflow.com/a/69625698/489865

        class UI(QtWidgets.QMainWindow):
            def __init__(self):
                super().__init__()
        
                self.ui = Ui_MainWindow()
                self.ui.setupUi(self)
        

        The above uses encapsulation --- the UI class is a QMainWindow, but it also contains a self.ui member which is the Ui_MainWindow helper class, you can access its objects/methods via self.ui. If you have designed a widget named widget you will access it from MainWindow via self.ui.widget. This is the way one does it from C++.

        P Offline
        P Offline
        pascor
        wrote on last edited by
        #3

        @JonB said in Make complete python script from Qt Designer:

        class MainWindow(QMainWindow, Ui_MainWindow):

        I thought it would be nice to have complete, "ready-to-use" modules that a simple top-level python script could run.

        This key for me to understand is: "However I would not recommend it, you do not get any design-time support for the widgets you have added in Designer, and at run-time you do not get Python variables for those widgets ...". Why this wasn't clearly explained elsewhere is a terrible ommision and misdirection in multiple tutorials I've come across.

        Using your recommendation, once the ui is designed by one person, another can write the rest of the application code without having to change the ui in Designer. It can be changed/customized by accessing the "Python variables for those widgets".

        Thanks for your thorough response. This really should be "stickyed" somewhere on this forum in a easy to find place for all the newbies like me.

        JonBJ 1 Reply Last reply
        1
        • P pascor

          @JonB said in Make complete python script from Qt Designer:

          class MainWindow(QMainWindow, Ui_MainWindow):

          I thought it would be nice to have complete, "ready-to-use" modules that a simple top-level python script could run.

          This key for me to understand is: "However I would not recommend it, you do not get any design-time support for the widgets you have added in Designer, and at run-time you do not get Python variables for those widgets ...". Why this wasn't clearly explained elsewhere is a terrible ommision and misdirection in multiple tutorials I've come across.

          Using your recommendation, once the ui is designed by one person, another can write the rest of the application code without having to change the ui in Designer. It can be changed/customized by accessing the "Python variables for those widgets".

          Thanks for your thorough response. This really should be "stickyed" somewhere on this forum in a easy to find place for all the newbies like me.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by JonB
          #4

          @pascor
          When I did Python-Qt stuff a few years ago I used PyCharm as my IDE. Which I found very good. Certainly if you did elect to use the pyuic/pyside6-uic route of processing the .ui file to produce a source file --- which the C++ build has to do --- rather than the run-time QUiLoader::load() you got invaluable development-time support like auto-completion of member variables etc. etc. It is true that the hassle of having to run pyuic each time after changing the .ui file was a minor irritant, but worth it for the other benefits one gained.

          I don't know what the editing/debugging experience for PySide inside Qt Creator is these days, but probably poor? There was no support at all in my time. Does it have an integrated Python debugger with your source code when you run? If not I would use PyCharm.

          1 Reply Last reply
          0

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved