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

How can QUiLoader load ui to "self" and trigger closeEvent



  • This is how it is used for most ppl I think:

    class Mainwin():#inherit QMainWindow or not wont make any difference. The right logic here is not to I think.
        def __init__(self):
            super().__init__()
            self.LoadUI()
            self.ui.show()
        def LoadUI(self):
                loader=QUiLoader()
                uifile=QFile('youruifile.ui')
                uifile.open(QFile.ReadOnly)
                self.ui = loader.load(uifile,self)
                uifile.close()    
    
    

    Is there a way to use QUiLoader to load ui to "self"?
    so I can access widgets by self.widget instead of self.ui.widget.

    Also, since it is not loading ui to self, the class where I load the ui is just a shell, defining closeEvent in it won't work.

    Since self.ui is the real QMainWindow so I tried override the closeEvent of the class but still it won't work.

    def closeEvent(self, event:QCloseEvent) -> None:
        print('closed')
    QWidget.closeEvent=closeEvent
    QMainWindow.closeEvent=closeEvent
    

  • Lifetime Qt Champion

    @sylvalas said in How can QUiLoader load ui to "self" and trigger closeEvent:

    Is there a way to use QUiLoader to load ui to "self"?

    Why would you want to do so?
    What is the problem using self.ui? ui is a member of your class (so "inside" self).

    "defining closeEvent in it won't work" - subclass QMainWindow and override closeEvent().
    See https://stackoverflow.com/questions/12365202/how-do-i-catch-a-pyqt-closeevent-and-minimize-the-dialog-instead-of-exiting



  • @jsulm
    I changed from pyqt5 to pyside6 I dont wanna go through it all and rewrite those lol but that's not the biggest problem.

    The biggest problem is closeEvent, with pyside, the window you close is not actually self but self.ui so it somehow just won't trigger the closeEvent if you define it in the class. That was why I tried to override the method of the QMainWindow class, cuz that's what QUiLoader() returns


  • Lifetime Qt Champion

    @sylvalas said in How can QUiLoader load ui to "self" and trigger closeEvent:

    the window you close is not actually self but self.ui

    No. If Mainwin is a QMainWindow subclass then you can override closeEvent() like any other.



  • @jsulm
    I can't upload files so if you create a ui file and try this:

    from PySide6.QtWidgets import QApplication
    from PySide6.QtWidgets import QMainWindow
    from PySide6.QtUiTools import QUiLoader
    from PySide6.QtCore import QFile
    
    import sys
    
    class MainThread(QMainWindow):
        def __init__(self):
            super().__init__()
            self.LoadUI()
    # This gives you a blank window if you close this one, it'll trigger the closeEvent
            self.show()
    #This is the real window but won't trigger closeEvent
            self.ui.show()
    
        def LoadUI(self):
            loader=QUiLoader()
            uifile=QFile('testui.ui')
            uifile.open(QFile.ReadOnly)
            self.ui = loader.load(uifile,self)
            uifile.close()
        
        def closeEvent(self, event):
            super(MainThread, self).closeEvent(event)
            print('closed')
        
    
    if __name__== '__main__':
        app = QApplication(sys.argv)
        mainthread=MainThread()
        sys.exit(app.exec_())
    


  • @sylvalas said in How can QUiLoader load ui to "self" and trigger closeEvent:

    I changed from pyqt5 to pyside6 I dont wanna go through it all and rewrite those lol but that's not the biggest problem.

    This is the problem area. Unfortunately PyQt and PySide use different ways to implement loading UI from file, and that is why you are having trouble with self.ui.

    If you say self.ui.show() is what "shows the real window" then that means self.ui is your QMainWindow. And so your def closeEvent(self, event): override needs to be in the class of the self.ui, not in your class MainThread(QMainWindow).

    I notice https://doc.qt.io/qt-5/quiloader.html says:

    In addition, you can customize or create your own user interface by deriving your own loader class.

    I don't know if that is the clue to what you are supposed to do to achieve what you want.

    Before you spend too long on this. Are you wedded to using QUiLoader on a .ui file at runtime? When I did Python I preferred to use the uic to generate Python code from .ui files, just like when using C++. It gives you more design/development-time support for your widgets. It is true, however, that the uic must be re-run every time you alter the .ui file. I don't know whether Creator now recognises and supports this if using Python/PySide, I think it might now. If you chose that you have a Python class where you can override methods like in C++.

    This is all covered in Using .ui files from Designer or QtCreator with QUiLoader and pyside6-uic. I like the Option A: Generating a Python class there.



  • @JonB
    Thank you.
    Actually, with pyqt I used to use "from PyQt5 import uic" and "self.ui=loadUi('GUI.ui',self)" that way it is automatically loaded to self.

    Yeah i might have to go back to pyqt again lol



  • @sylvalas
    That's not the uic I mean. You are talking about a PyQt class of that name, and loadUi("file.ui") at runtime. I was talking about the uic "pre-processor command" in PySide, I think it's pyuic in PyQt5. Which takes a different approach, no runtime .ui file, instead it produces Python source code from it when you develop, and you get a dedicated class for your .ui files.


Log in to reply