QMessageBox 添加自定义按钮并保持打开状态

QMessageBox add custom button and keep open

我想向 QMessagebox 添加一个自定义按钮以打开 matplotlib window,以及一个 Ok 按钮供用户在想要关闭它时单击

我目前可以正常使用,但我希望这两个按钮分别执行操作而不是打开 window。

我知道我可以创建一个具有所需结果的对话框 window,但我想知道如何使用 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()

想要的结果:

确定按钮 - 关闭 QMessageBox

View Graph 按钮 - 打开 matplotlib window 并保持 QMessageBox 打开直到用户点击 Ok

好的,首先你没有在 QtCore 中使用任何东西,所以不需要导入它。这应该可以帮助您了解您需要做什么。我稍微调整了一下,我不得不添加 2 sys.exits,或者当您按下 View Graphs 时,由于您当前的设置方式,程序刚刚挂起。如果您不选择调整此代码流,则将 sys.exit 从 if/else 中拉出并将其放在 if/else 之后 - 没有不必要的冗余代码

from sys import exit as sysExit

from PyQt5.QtWidgets import QApplication, QMessageBox

def Main():
    msgbox = QMessageBox()
    msgbox.setWindowTitle("Information")
    msgbox.setText('Test')
    msgbox.addButton(QMessageBox.Ok)
    msgbox.addButton('View Graphs', QMessageBox.YesRole)

    bttn = msgbox.exec_()

    if bttn == QMessageBox.Ok:
        print("Ok")
        sysExit()
    else:
        print("View Graphs")
        sysExit()

if __name__ == "__main__":
    MainThred = QApplication([])

    MainApp = Main()

    sysExit(MainThred.exec_())

也就是你的 non-redundant if/else 看起来如下

    if bttn == QMessageBox.Ok:
        print("Ok")
    else:
        print("View Graphs")

    sysExit()

IMO 有点老套,但在添加 View Graphs 按钮后,您可以断开其 clicked 信号并将其重新连接到您选择的插槽,例如

import sys
from PyQt5 import QtCore, QtWidgets

def show_graph():
    print('Show Graph')

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

    yes_button = msgbox.addButton('View Graphs', QtWidgets.QMessageBox.YesRole)
    yes_button.clicked.disconnect()
    yes_button.clicked.connect(show_graph)

    bttn = msgbox.exec_()

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

if __name__ == "__main__":
    main()

QMessageBox 和所有 QDialogs 一样,在返回 exec_() 之前阻塞所有内容,但它也会自动将所有按钮连接到任一 accepted/rejected 信号,在任何情况下都返回 exec_()

您的代码的可能解决方案是:

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

就是说,在 sys.exit(app.exec_()) 调用之外(如在 "before" 中)使用 QDialog.exec_() 时要小心,因为如果您不知道自己在做什么,可能会导致意外行为正在做。