Alternative to "QMessageBox.Yes" for PyQt6

Question:

I am trying to port over a script of mine from PyQt5 to PyQt6. I have figured out how to port most of the things thanks to this answer, however, I have run into an issue.

I have figured out that PyQt6 uses QtWidgets.QMessageBox.StandardButtons.Yes instead of PyQt5’s QtWidgets.QMessageBox.Yes.

However, when checking if the user pressed "Yes" after a QMessageBox opens, replacing QtWidgets.QMessageBox.Yes with QtWidgets.QMessageBox.StandardButtons.Yes doesn’t work (check the examples below).


Examples:

PyQt5:

reply = QtWidgets.QMessageBox()
reply.setText("Some random text.")
reply.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)

x = reply.exec_()

if x == QtWidgets.QMessageBox.Yes:
    print("Hello!")

Printing "Hello!" here works normally. (16384 == 16384)

PyQt6:

reply = QtWidgets.QMessageBox()
reply.setText("Some random text.")
reply.setStandardButtons(QtWidgets.QMessageBox.StandardButtons.Yes | 
                         QtWidgets.QMessageBox.StandardButtons.No)

x = reply.exec()

if x == QtWidgets.QMessageBox.StandardButtons.Yes:
    print("Hello!")

"Hello!" here doesn’t print at all. (16384 != StandardButtons.yes)


I know I could just do:

x = reply.exec()

if x == 16384:
    print("Hello!")

because, after pressing "Yes", the QMessageBox equals to 16384 (see this), but I’d like to not use that approach, and rather use something like the PyQt5 example.

Asked By: DespawnedDiamond

||

Answers:

This is kind of strange. According to the documentation for QMessageBox.exec:

When using a QMessageBox with standard buttons, this function returns
a StandardButton value indicating the standard button that was
clicked.

You are using standard buttons, so this should return a QMessageBox.StandardButtons enum.

It’s also worth mentioning that comparing integers with enums was not a problem in PyQt5, because enums were implemented with enum.IntEnum. Now, they’re implemented with enum.Enum. From the Riverbank Computing website:

All enums are now implemented as enum.Enum (PyQt5 used enum.IntEnum
for scoped enums and a custom type for traditional named enums). PyQt5
allowed an int whenever an enum was expected but PyQt6 requires the
correct type.

However, for some reason, QMessageBox.exec returns an integer (I just tried it with PyQt6==6.0.0)!

For now, you can get around this by deliberately constructing an enum object from the returned integer:

if QtWidgets.QMessageBox.StandardButtons(x) == QtWidgets.QMessageBox.StandardButtons.Yes:
            print("Hello!")

And, since you’re comparing enums, I would suggest using is rather than ==.

Answered By: Paul M.

QtWidgets.QMessageBox.StandardButtons are implemented using enum.Flag in PyQt6, while QDialog.exec() returns an int. Sadly these cannot be directly compared, but you can still use:

if x == QtWidgets.QMessageBox.StandardButtons.Yes.value:
    print("Hello!")

Note that the idiomatic x == int(Yes) does not work either.

PyQt5 used a wrapped custom StandardButtons class (type in Yes | No to see this), NOT an enum.IntEnum as the other answer is claiming. An IntEnum would have been a logical choice however since it specifically allows int comparisons.

Answered By: xjcl

I had the same problem (from PyQt5 to PyQt6) but coding in this way it’s running smooth:

if QtWidgets.QMessageBox.critical(self,"Foo","PROTECTION NOT FOUND - Exit",QtWidgets.QMessageBox.StandardButtons.Yes):
                print("Exit")

I used it as ‘critical’ or ‘question’ and even ‘information’ and it’s always running

Answered By: Mauro O

StandardButtons is not an Attribute/Method I can choose for QMessageBox. Not sure if this was maybe updated in the last 4 months, but for me the code works with StandardButton instead of StandardButtons.

from PyQt6.QtWidgets import QMessageBox

reply = QMessageBox()
reply.setText("Some random text.")
reply.setStandardButtons(QMessageBox.StandardButton.Yes | 
                     QMessageBox.StandardButton.No)

x = reply.exec()

if x == QMessageBox.StandardButton.Yes:
    print("Hello!")
Answered By: Sebastian

I know the answer might be a little late, but here’s what works for me in pyqt6.

msg = QMessageBox()
msg.setIcon(QMessageBox.Icon.Information)

msg.setText('Teste')
msg.setInformativeText("This is additional information")
msg.setWindowTitle("MessageBox demo")
#msg.setDetailedText("The details are as follows:")
msg.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.Cancel)
msg.buttonClicked.connect(self.msgbtn)
msg.exec()

def msgbtn(self, i):
    print( "Button pressed is:",i.text() )
Answered By: Luis Chaves

This way it also served me very well, mainly because it already translates the text of the button.

    msgBox = QMessageBox()
    msgBox.setIcon(QMessageBox.Icon.Information)
    msgBox.setWindowTitle('Excluir Ponto')
    msgBox.setText('Tem certeza que deseja excluir o ponto {point}?'.format(point = self.dialogCUDP.UI.lineEditPoint.text()))
    btn_delete = msgBox.addButton('Excluir', QMessageBox.ButtonRole.YesRole)
    btn_cancel = msgBox.addButton('Cancelar', QMessageBox.ButtonRole.NoRole)
    msgBox.exec()

    if msgBox.clickedButton() == btn_delete:
        if self._serverOn:
            if self.GM.dfPointsManager.deletePointPMCSV(Priceformat.setFormatStrFloat(self.dialogCUDP.UI.lineEditPoint.text())):
                QMessageBox.information(self, 'Excluir Ponto', 'Ponto {point}, excluído com sucesso!'.format(point = self.dialogCUDP.UI.lineEditPoint.text()))
                self.disableFieldCUDPoint()
                self.clearFieldCUDPoint()
            else:
                QMessageBox.warning(self, 'Excluir Ponto', 'Não foi possível excluir o ponto {point}!nPor favor, tente novamente'.format(point = self.dialogCUDP.UI.lineEditPoint.text()))
                msgBox.close()
        else:
            if self._createnewpointPM.deletePointPMCSV(Priceformat.setFormatStrFloat(self.dialogCUDP.UI.lineEditPoint.text())):
                QMessageBox.information(self, 'Excluir Ponto', 'Ponto {point}, excluído com sucesso!'.format(point = self.dialogCUDP.UI.lineEditPoint.text()))
                self.disableFieldCUDPoint()
                self.clearFieldCUDPoint()
            else:
                QMessageBox.warning(self, 'Excluir Ponto', 'Não foi possível excluir o ponto {point}!nPor favor, tente novamente'.format(point = self.dialogCUDP.UI.lineEditPoint.text()))
                msgBox.close()
Answered By: Luis Chaves

use .StandardButton !

reply = QtWidgets.QMessageBox()
reply.setText("Some random text.")
reply.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Yes | 
QtWidgets.QMessageBox.StandardButton.No)

x = reply.exec_()

if x == QtWidgets.QMessageBox.StandardButton.Yes:
    print("Hello!")
Answered By: sanjaya
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.