简体   繁体   中英

pyqt5 python: how to keep open dialog box when clicking "retry" button on same dialog

Is there any way to keep the dialog box open once clicking one of the buttons to retry the IF statement that opens this box in first instance? I want to continue clicking the "Retry" button once the condition is achieved without having this dialog box closed... otherwise, can you give me an idea how I can make this functionality?

import random
import sys

from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QPushButton

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("My App")

        button = QPushButton("Press me for a dialog!")
        button.clicked.connect(self.button_clicked)
        self.setCentralWidget(button)

    def button_clicked(self):
        self.rand = random.uniform(0, 1)
        print(self.rand)
        if self.rand > 0.5:
            self.critical = QMessageBox.critical(
            self,
            "Oh no!",
            "Something went very wrong.",
            buttons=QMessageBox.Retry | QMessageBox.Cancel,
            defaultButton=QMessageBox.Retry)
            if self.critical == QMessageBox.Retry:
                print("Retry!")
                self.rand = random.uniform(0, 1)
                print(self.rand)
            else:
                print("Cancel!")
        
        else:
            self.ok = QMessageBox(self)
            self.ok.setWindowTitle("All good!")
            self.ok.setText("Everything looks perfect!")
            self.button = self.ok.exec()
    
            if self.button == QMessageBox.Ok:
                print("OK!")
            

app = QApplication(sys.argv)

window = MainWindow()
window.show()

app.exec()

Thanks heaps!

The static functions of QMessageBox automatically connect its buttons, so you only have two options: you either use a while loop and create a QMessageBox every time the value isn't valid and the reply button has been pressed, or you create a QMessageBox instance and disconnect its default signals.

Basic while loop

This is the simplest solution: a while loop that continuously shows the message box until the value is valid; the drawback is that you cannot reuse the existing dialog, and a new one will always be shown;

    def button_clicked(self):
        self.rand = random.uniform(0, 1)
        print(self.rand)
        if self.rand > 0.5:
            while self.rand > 0.5:
                self.critical = QMessageBox.critical(
                self,
                "Oh no!",
                "Something went very wrong.",
                buttons=QMessageBox.Retry | QMessageBox.Cancel,
                defaultButton=QMessageBox.Retry)
                if self.critical == QMessageBox.Retry:
                    print("Retry!")
                    self.rand = random.uniform(0, 1)
                    print(self.rand)
                else:
                    print("Cancel!")
                    break
        # ...

Using a QMessageBox instance

This is a bit more complex, but also more consistent. You need to create a new instance of QMessageBox, disconnect the clicked signal of its buttonbox (which is what QMessageBox uses to decide how to set its finished value), and instead connect its accepted and rejected signals; the latter will cancel the dialog, while the former will call a local function that generates a new value, and eventually accepts the dialog if it's valid:

    def button_clicked(self):
        self.rand = random.uniform(0, 1)
        if self.rand > 0.5:
            def checkRand():
                self.rand = random.uniform(0, 1)
                if self.rand > 0.5:
                    msgBox.accept()
                    print('OK!')
                else:
                    print(self.rand)

            msgBox = QMessageBox(
                QMessageBox.Critical, 
                "Oh no!", 
                "Something went very wrong.", 
                buttons=QMessageBox.Retry | QMessageBox.Cancel, 
                parent=self
                )
            buttonBox = msgBox.findChild(QDialogButtonBox)
            buttonBox.clicked.disconnect()
            buttonBox.rejected.connect(msgBox.reject)
            buttonBox.accepted.connect(checkRand)
            msgBox.exec_()
        # ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM