pythonpyqtpyqt5qwizardqwizardpage

Show messagebox after page load pyqt5


I have a PyQt5 Wizard and on the second page I want the behavior to change based on previous content.

I have implemented initializePage

def initializePage(self): 
    if self.altThing:
        self.onloadbtn.show()
        # .. do Something
        QMessageBox.about(self, 'Hello', 'Hello') #Pops up before the page is rendered
        # do other stuff..

I want the page to load first and then do some stuff such as download files and display a progress bar etc. but not until the page loads.

What happens is the QMessageBox will pop up before the page is loaded.

Below is a MVCE

import sys
from PyQt5.QtGui import *
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *


class Wizard(QWizard):
    def __init__(self, parent=None):
        super(Wizard, self).__init__(parent)

        self.addPage(EnterToken(self)) 
        self.addPage(ProcessData(self))

        self.buttons = [self.button(t) for t in (QWizard.NextButton, QWizard.FinishButton)]

        for btn in self.buttons:
            btn.installEventFilter(self)

    def eventFilter(self, obj, event):
        if obj in self.buttons and event.type() == QEvent.Show:
            obj.setDefault(False)
        return super(Wizard, self).eventFilter(obj, event)

class EnterToken(QWizardPage):
    def __init__(self, parent=None):
        super(EnterToken, self).__init__(parent)

        self.setTitle("Enter your token here")
        self.setSubTitle(" ")           

        # Enter Token Widgets
        self.label = QLabel()
        self.enter_token_box = QLineEdit()        

        self.btn = QPushButton('OK')

        # layout options
        layout = QVBoxLayout()
        layout.addWidget(self.label)        
        self.label.setText("Enter Your 12 Digit Code.")
        layout.addWidget(self.enter_token_box)
        layout.addWidget(self.btn)

        # Enter Key TRigger
        self.enter_token_box.returnPressed.connect(self._EnterToken)

        self.btn.clicked.connect(self._EnterToken)

        self.setLayout(layout)         

    def _EnterToken(self):
        """ Method for processing user input after the button is pressed"""
        pass


class ProcessData(QWizardPage):
    """ Sensor Code Entry """
    def __init__(self, parent=None):
        super(ProcessData, self).__init__(parent)        

        self.altThing = True

        # num of logs combo box
        self.num_logs_combo = QComboBox(self)

        self.alt = QComboBox(self)


        # ~buttons
        self.btn = QPushButton('OK')
        self.onloadbtn = QPushButton('OK')

        layout = QVBoxLayout()
        layout.addWidget(self.num_logs_combo)
        layout.addWidget(self.alt)
        layout.addWidget(self.btn) 
        layout.addWidget(self.onloadbtn)  

        self.onloadbtn.hide()
        self.alt.hide()

        self.setLayout(layout)  

        self.btn.clicked.connect(self._EnterToken)  


    def initializePage(self): 
        if self.altThing:
            self.onloadbtn.show()
            # .. do Something
            QMessageBox.about(self, 'Hello', 'Hello') #Pops up before the page is rendered
            # do other stuff..

    def _EnterToken(self):
        """ Method for processing user input after the button is pressed"""
        pass

if __name__ == '__main__':
    app = QApplication(sys.argv)
    wizard = Wizard()
    wizard.show()
    sys.exit(app.exec_())

Solution

  • initializePage() method is called a moment before displaying the page so you should not call that logic in that part, a possible solution is to use a QTimer.

    class ProcessData(QWizardPage):
        """ Sensor Code Entry """
        def __init__(self, parent=None):
            super(ProcessData, self).__init__(parent)        
            self.altThing = True
            # num of logs combo box
            self.num_logs_combo = QComboBox(self)
            self.alt = QComboBox(self)
            # ~buttons
            self.btn = QPushButton('OK')
            self.onloadbtn = QPushButton('OK')
    
            layout = QVBoxLayout(self)
            layout.addWidget(self.num_logs_combo)
            layout.addWidget(self.alt)
            layout.addWidget(self.btn) 
            layout.addWidget(self.onloadbtn)  
    
            self.onloadbtn.hide()
            self.alt.hide()
            self.btn.clicked.connect(self._EnterToken) 
    
        def foo(self):
            if self.altThing:
                # .. do Something
                QMessageBox.about(self, 'Hello', 'Hello') #Pops up before the page is rendered
                # do other stuff..""
    
        def initializePage(self):
            QTimer.singleShot(0, self.foo)
    
        def _EnterToken(self):
            """ Method for processing user input after the button is pressed"""
            pass