When changing screens with QStackedWidget, how to call a function in the changed screen?

1k Views Asked by At

I'm trying to call the init function of the screen I'm changing my screen index to

For an example, i have this code:

from PyQt5 import QtWidgets   as qtw
from PyQt5 import QtGui       as qtg
from sys   import argv        as sysArgv
from sys   import exit        as sysExit

arialLarge = qtg.QFont("Arial", 18)

class MainWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()
        # Current screen label;
        mainWindowLabel = qtw.QLabel("This is the main window", self)
        mainWindowLabel.setFont(arialLarge)
        mainWindowLabel.move(20, 40)
        # Button for going to the HelloWindow screen;
        gotoHelloWindowButton = qtw.QPushButton("Go to hello window", self, clicked=lambda: appStack.setCurrentIndex(appStack.currentIndex()+1))
        gotoHelloWindowButton.move(100, 100)


class HelloWindow(qtw.QWidget):
    def __init__(self):
        super().__init__()
        # EG: print hello world when I visit this page
        print("hello world")


        # Current screen label;
        helloWindowLabel = qtw.QLabel("This is the hello window", self)
        helloWindowLabel.setFont(arialLarge)
        helloWindowLabel.move(20, 40)
        # Button for going to the MainWindow screen;
        gotoMainWindowButton = qtw.QPushButton("Go to main window", self, clicked=lambda: appStack.setCurrentIndex(appStack.currentIndex()-1))
        gotoMainWindowButton.move(100, 100)


if __name__ == "__main__":
    app = qtw.QApplication(sysArgv)
    appStack = qtw.QStackedWidget()
    appStack.addWidget(MainWindow())
    appStack.setFixedSize(300, 300)
    appStack.show()
    appStack.addWidget(HelloWindow())
    sysExit(app.exec())

If im visiting the HelloWindow from the MainWindow, how can i run the init function of the HelloWindow screen so I can run whatever code I want in there?

I need to be able to do this as on the app im working on as on the mainpage i have dynamically created buttons that all have functions parameters with different indexes to my server, and i need to be able to fetch the data from server based off the clicked button's data index so on the other page I can view the desired data.

1

There are 1 best solutions below

4
musicamante On

The __init__ of a python class is what is called when an instance is created (using SomeClass()), so you should not try (or even think) to call it again, as it could create serious problems and bugs that are hard to track.

I strongly suggest you to read the documentation about classes in Python, as you cannot ignore that aspect in object oriented programming.

If you need to call something everytime the index is changed, then you should better subclass QStackedWidget and control everything from there.

A good solution is to create a standardized function that will be called everytime the page is presented, and ensure that the stack widget correctly calls it.

class FirstPage(QtWidgets.QWidget):
    def __init__(self):
        super().__init__(self)
        # ...
        self.nextButton = QtWidgets.QPushButton('Next')
        self.doSomething()

    def doSomething(self):
        ...


class SecondPage(QtWidgets.QWidget):
    def __init__(self):
        super().__init__(self)
        # ...
        self.prevButton = QtWidgets.QPushButton('Previous')
        self.doSomething()

    def doSomething(self):
        ...


class Stack(QtWidgets.QStackedWidget):
    def __init__(self):
        super().__init__(self)
        self.first = FirstPage()
        self.first.nextButton.clicked.connect(self.goNext)
        self.addWidget(self.first)

        self.second = SecondPage()
        self.second.prevButton.clicked.connect(self.goPrev)

        self.currentChanged.connect(self.initCurrent)

    def goNext(self):
        self.setCurrentIndex(1)

    def goPrev(self):
        self.setCurrentIndex(0)

    def initCurrent()
        if self.currentWidget():
            self.currentWidget().doSomething()


if __name__ == "__main__":
    app = qtw.QApplication(sysArgv)
    appStack = Stack()
    appStack.setFixedSize(300, 300)
    appStack.show()
    sysExit(app.exec())

Note that adding a QMainWindow to a parent is not a good idea, as Qt main windows are intended to be used as top level windows; also note that using fixed geometries (positions and sizes) is often considered bad practice, and you should use layout managers instead.