pythonpyqtpyqt5pyqt6

Alternative to "QMessageBox.Yes" for PyQt6


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.


Solution

  • 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 ==.