Return 在 QDialog-PyQt5 上单击按钮 ID 而不是(接受、拒绝标志)

Return clicked button id instead of (accept, reject flags) on QDialog- PyQt5

总结:

我一直在我的应用程序中使用 QMessageBox(为此要求在关闭前保存项目、错误消息),现在我想要自定义样式(自定义标题栏、自定义按钮等),我发现用 QMessageBox 很难做到这一点,而且由于我也在我的应用程序中使用 QDialog(为此目的:从用户那里获取输入),我决定使用自定义 QDialog(在上面制作我自己的样式) 而不是 QMessageBox 用于这些所有先前的目的,因为它更容易自定义和创建我的样式。

问题:

我现在遇到的问题是:QDialog return 只有一个标志值 (0,1),具体取决于按钮角色 如果我只有 2 个按钮也没关系,但这里我有 3 个(保存,取消,关闭),保存将 return 1,关闭和取消都将 return 0。正如我所见,QMessageBox return 被点击的按钮的 ID。

一个例子(希望评论很好 :D):

from PyQt5.QtWidgets import *


class CustomDialog(QDialog):
    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Data will be lost")
        label = QLabel("Are you sure you want close the app before saving?")
        buttonBox = QDialogButtonBox()
        buttonBox.addButton(QDialogButtonBox.Save)
        buttonBox.addButton(QDialogButtonBox.Cancel)
        buttonBox.addButton(QDialogButtonBox.Close)

        layout = QVBoxLayout()
        layout.addWidget(label)
        layout.addWidget(buttonBox)
        self.resize(300, 100)
        self.setLayout(layout)

        # These two lines, return 0 or 1.
        buttonBox.rejected.connect(self.reject)
        buttonBox.accepted.connect(self.accept)    

class Window(QWidget):
    def __init__(self):
        super().__init__()
        label = QLabel('Hello Dialog', self)
        open_dialog_button = QPushButton('Open Dialog', self)
        open_dialog_button.clicked.connect(self.showDialog)

        open_message_box_button = QPushButton('Open Message Box', self)
        open_message_box_button.clicked.connect(self.show_message_box)

        layout = QVBoxLayout()
        layout.addWidget(label)
        layout.addWidget(open_dialog_button)
        layout.addWidget(open_message_box_button)
        self.setLayout(layout)

    def showDialog(self):
        self.dialog = CustomDialog(self)
        btn_clicked = self.dialog.exec_()  # dialog exec returns 0 or 1 (Save = 1, Close and Cancel returns 0)

        # I want something like this.
        if btn_clicked == QDialogButtonBox.Save:
            print("Close.. After Saving...")
        elif btn_clicked == QDialogButtonBox.Close:
            print("Close.. Without saving")
        else:
            print("Cancel.. Don't exit the program")

    def show_message_box(self):
        msg = QMessageBox()
        msg.setIcon(QMessageBox.Warning)
        msg.setText("Are you sure you want close the app before saving?")
        msg.setStandardButtons(QMessageBox.Close | QMessageBox.Save | QMessageBox.Cancel)
        msg.setWindowTitle("Data will be lost")
        btn_clicked = msg.exec_()

        # Here i can do this.
        if btn_clicked == QMessageBox.Save:
            print("Close.. After Saving...")
        elif btn_clicked == QMessageBox.Close:
            print("Close.. Without saving")
        else:
            print("Cancel.. Don't exit the program")


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    win = Window()
    win.resize(200, 200)
    win.show()
    sys.exit(app.exec_())

我找到了解决方案,它通过使用自定义信号和槽与我一起工作,但仍然不确定它是否好。等待批准,然后我可以将此解决方案标记为已接受。

from PyQt5.QtWidgets import *
from PyQt5.QtCore import *


class CustomDialog(QDialog):
    # Create a signal
    signal = pyqtSignal(int)

    def __init__(self, parent=None):
        super().__init__(parent)
        self.setWindowTitle("Data will be lost")
        label = QLabel("Are you sure you want close the app before saving?")
        self.buttonBox = QDialogButtonBox()
        self.buttonBox.addButton(QDialogButtonBox.Save)
        self.buttonBox.addButton(QDialogButtonBox.Cancel)
        self.buttonBox.addButton(QDialogButtonBox.Close)

        layout = QVBoxLayout()
        layout.addWidget(label)
        layout.addWidget(self.buttonBox)
        self.resize(300, 100)
        self.setLayout(layout)

        # connect each button with custom slot
        self.buttonBox.button(QDialogButtonBox.Save).clicked.connect(lambda: self.customSlot(QDialogButtonBox.Save))
        self.buttonBox.button(QDialogButtonBox.Close).clicked.connect(lambda: self.customSlot(QDialogButtonBox.Close))
        self.buttonBox.button(QDialogButtonBox.Cancel).clicked.connect(lambda: self.customSlot(QDialogButtonBox.Cancel))

        # connect signal with buil-in function from QDialog (done())
        # This done function will return <int> value and close the dialog.
        self.signal.connect(self.done)

    def customSlot(self, button_id):
        # emit button's id
        self.signal.emit(button_id)


class Window(QWidget):
    def __init__(self):
        super().__init__()
        label = QLabel('Hello Dialog', self)
        open_dialog_button = QPushButton('Open Dialog', self)
        open_dialog_button.clicked.connect(self.showDialog)

        layout = QVBoxLayout()
        layout.addWidget(label)
        layout.addWidget(open_dialog_button)
        self.setLayout(layout)

    def showDialog(self):
        dialog = CustomDialog()
        btn_clicked = dialog.exec_()  # dialog exec returns button's id

        # Now you can use the following lines of code
        if btn_clicked == QDialogButtonBox.Save:
            print("Close.. After Saving...")
        elif btn_clicked == QDialogButtonBox.Close:
            print("Close.. Without saving")
        else:
            print("Cancel.. Don't exit the program")


if __name__ == '__main__':
    import sys

    app = QApplication(sys.argv)
    win = Window()
    win.resize(200, 200)
    win.show()
    sys.exit(app.exec_())