Warm tip: This article is reproduced from stackoverflow.com, please click
pyqt pyqt5 python python-3.x qmessagebox

QMessageBox add custom button and keep open

发布于 2020-03-27 10:17:50

I want to add a custom button to QMessagebox that opens up a matplotlib window, along with an Ok button for user to click when they want to close it

I currently have it somewhat working, but I want the two buttons to do separate things and not open the window.

I know I can just create a dialog window with the desired results, but I wanted to know how to with a QMessageBox.

import sys
from PyQt5 import QtCore, QtWidgets

def main():
    app = QtWidgets.QApplication(sys.argv)
    msgbox = QtWidgets.QMessageBox()
    msgbox.setWindowTitle("Information")
    msgbox.setText('Test')
    msgbox.addButton(QtWidgets.QMessageBox.Ok)
    msgbox.addButton('View Graphs', QtWidgets.QMessageBox.YesRole)

    bttn = msgbox.exec_()

    if bttn:
        print("Ok")
    else:
        print("View Graphs")
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

Desired result:

Ok button - closes QMessageBox

View Graph button - opens matplotlib window and keeps QMessageBox open until user clicks Ok

Questioner
Drees
Viewed
142
musicamante 2019-07-03 21:32

A QMessageBox, as all QDialogs, blocks everything until exec_() is returned, but it also automatically connects all buttons to either accepted/rejected signals, returning the exec_() in any case.

A possible solution for your code is:

app = QtWidgets.QApplication(sys.argv)
msgbox = QtWidgets.QMessageBox()
# the following is if you need to interact with the other window
msgbox.setWindowModality(QtCore.Qt.NonModal)
msgbox.addButton(msgbox.Ok)
viewGraphButton = msgbox.addButton('View Graphs', msgbox.ActionRole)
# disconnect the clicked signal from the slots QMessageBox automatically sets
viewGraphButton.clicked.disconnect()

# this is just an example, replace with your matplotlib widget/window
graphWidget = QtWidgets.QWidget()

viewGraphButton.clicked.connect(graphWidget.show)
msgbox.button(msgbox.Ok).clicked.connect(graphWidget.close)
# do not use msgbox.exec_() or it will reset the window modality
msgbox.show()
sys.exit(app.exec_())

That said, be careful in using QDialog.exec_() outside (as in "before") the sys.exit(app.exec_()) call, as it might result in unexpected behavior if you don't know what you are doing.