简体   繁体   English

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

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

Summary:概括:

I've been using QMessageBox in my application (for this purpose asking for saving project before closing, Error messages), And now I want to have a custom style (Custom title bar, custom buttons and so on), I found it is hard to do that with QMessageBox, And since I've been using a QDialog in my application as well (For this purpose: Taking input from user), I decided to use a custom QDialog (Make my own style on it) instead of QMessageBox for these all previous purpose, since it is easier to customize and creating my style.我一直在我的应用程序中使用 QMessageBox(为此要求在关闭前保存项目,错误消息),现在我想要一个自定义样式(自定义标题栏,自定义按钮等),我发现这很难使用 QMessageBox 做到这一点,并且由于我也在我的应用程序中使用 QDialog(为此目的:从用户那里获取输入),我决定使用自定义 QDialog(在其上制作我自己的样式)而不是 QMessageBox这些都是以前的目的,因为它更容易定制和创建我的风格。

The problem:问题:

The problem that I have now is: QDialog return only a flag value (0,1) depending on the button role And that's fine if I have only 2 buttons BUT here I have 3 (Save, Cancel, Close), Save will return 1 and both Close and Cancel return 0. And QMessageBox as I've seen it return the id of the Button that was clicked.我现在遇到的问题是: QDialog 仅返回一个标志值 (0,1),具体取决于按钮角色 如果我只有 2 个按钮,那很好,但这里我有 3 个(保存、取消、关闭),保存将返回 1 Close 和 Cancel 都返回 0。而 QMessageBox 正如我所见,它返回被单击的 Button 的 ID。

An example (commented well hopefully:D):一个例子(希望评论很好: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_())

I've found the solution and it worked with me by using a custom signal and slot, but still not sure if it is good or not.我找到了解决方案,它通过使用自定义信号和插槽与我一起工作,但仍然不确定它是否好。 waiting for approval and then I can mark this solution as an accepted one.等待批准,然后我可以将此解决方案标记为已接受的解决方案。

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM