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.
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
# ...
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_()
# ...