Guimoute
Guimoute

Reputation: 4649

How to call a method in PyQt5 right after the interface is done loading?

I am making an instrument interface in Qt5 and it works fine. The only issue is that it's slow to start because the interface __init__ contains a time-consuming method (5-10 seconds) used to connect to the instrument. Currently, nothing shows up for several seconds then the whole interface shows up with the "successfully connected to the instrument" message already written in its console (a textEdit widget).

What I would like is to have the interface show up instantly, and only after it's shown it should start the communication protocol. I am sure this is just a matter of moving one line around, but I can't figure it out. Any help is appreciated.

Here is a minimal example of the program structure:

# ================================================
#      Interface management.
# ================================================

class RENAMEMELATER(Ui_renamemetoo, QObject):

     def __init__(self, parent):
        super(Ui_renamemetoo, self).__init__()
        self.ui = Ui_renamemetoo()
        self.ui.setupUi(parent)

        # Redirect IDE console towards GUI console.
        sys.stdout = EmittingStream()
        sys.stdout.textWritten.connect(self.redirect_console_messages)
        sys.stderr = EmittingStream()
        sys.stderr.textWritten.connect(self.redirect_console_messages)

        # Initialize PC/instrument communication (MOVE SOMEWHERE ELSE?)
        self.T = TaborSE5082("USB0::0x168C::0x5082::0000218391::INSTR") # TIME CONSUMING.



   def redirect_console_messages(self, text):
       """All print() from the program are appended on a textEdit
          instead of the IDE console."""

        self.ui.Console_textEdit.append(text.rstrip("\n"))



    def close_program(self):
        """Call those functions after the user clicked on exit."""

        self.T.CLOSE()
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__
        print("Program terminated.")

# ================================================
#      Program execution.
# ================================================

if __name__ == "__main__":

    # Define the app.
    if not QtWidgets.QApplication.instance():
        app = QtWidgets.QApplication(sys.argv)
    else:
        app = QtWidgets.QApplication.instance()

    # Start the interface.
    Form = QtWidgets.QWidget()
    prog = RENAMEMELATER(Form)
    Form.show()

    # Handle what happens at program exit.
    app.setQuitOnLastWindowClosed(True)
    app.aboutToQuit.connect(prog.close_program)

    # Launch.
    app.exec()

In the main I can use app.aboutToQuit to close the instrument. Maybe there is some sort of app.isDoneLoading that I could .connect to my instrument initialization in the same way?

Thank you.

Upvotes: 2

Views: 833

Answers (1)

eyllanesc
eyllanesc

Reputation: 244202

A task that takes 5 to 10 seconds is heavy so apart from not showing the GUI you can freeze it so the solution is to run it in another thread:

def __init__(self, parent):

    # ...
    threading.Thread(target=self.callback, daemon=True).start()

def callback(self):
    self.T = TaborSE5082("USB0::0x168C::0x5082::0000218391::INSTR")
    # another code

Upvotes: 2

Related Questions