QDialog exec() and getting result value

2020-01-28 12:20发布

问题:

I have subclassed QDialog to implement functionality similar to QMessageBox ( I needed this to allow for customization). It has a text message and OK, Cancel buttons. I am showing the dialog using exec() to make it blocking. Now, how do I return values of true/false when the user clicks on OK/Cancel?

I tried connecting the buttons to setResult() and then, return the result value when clicked, but

  1. Clicking the buttons does not close the dialog box
  2. the return value is incorrect. Following is the code I have written. I think I am wrong in the exec/result part - but I am not sure how to fix it.
class MyMessageBox : public QDialog {
    Q_OBJECT

private slots:

    void onOKButtonClicked() { this->setResult(QDialog::Accepted); }
    void onCancelButtonClicked() { this->setResult(QDialog::Rejected); }

public:
    MyMessageBox(QMessageBox::Icon icon, const QString& title,
        const QString& text, bool showCancelButton = true,
        QWidget* parent = 0);

    virtual void resizeEvent(QResizeEvent* e);

    QDialog::DialogCode showYourself()
    {
        this->setWindowModality(Qt::ApplicationModal);
        this->exec();
        return static_cast<QDialog::DialogCode>(this->result());
    }
};

The user will instantiate the class and call showYourself() which is expected to return the value and also close(and delete) the dialog.

I have posted partial code. Let me know if you need more and I will post the complete version.

回答1:

Some points :

  1. Rather than using setResult() yourself, use QDialog::accept() and QDialog::reject().
  2. It seems you are not taking full advantage of the signals and slots. You need the object which create the dialog (or another one) to listen to the signals of the dialog.
  3. In your code you are not connecting signals to slots either.
  4. With my fix onOKButtonClicked and onCancelButtonClicked are unnecessary.
  5. With my fix you don't need showYourself(). Just call exec and with the events information will flow.

You need to add this code before showing the dialog (this assume it is in a dialog method):

QObject::connect(acceptButton, SIGNAL(clicked()), this, SLOT(accept()));
QObject::connect(rejectButton, SIGNAL(clicked()), this, SLOT(reject()));

In the caller object you have

void someInitFunctionOrConstructor(){
   QObject::connect(mydialog, SIGNAL(finished (int)), this, SLOT(dialogIsFinished(int)));
}

void dialogIsFinished(int){ //this is a slot
   if(result == QDialog::Accepted){
       //do something
       return
   }
   //do another thing
}


回答2:

Another solution:

    // set signal and slot for "Buttons"
    connect(YesButton, SIGNAL(clicked()), dlg, SLOT(accept()));
    connect(NoButton, SIGNAL(clicked()), dlg, SLOT(reject()));

    // show modal window event loop and wait for button clicks
    int dialogCode = dlg->exec();

    // act on dialog return code
    if(dialogCode == QDialog::Accepted) { // YesButton clicked }
    if(dialogCode == QDialog::Rejected) { // NoButton clicked }


回答3:

Case 1 Clicking the buttons does not close the dialog box.

For this you have to close the dialog on respective SLOTS, so Use

void onOKButtonClicked(){ this->setResult(QDialog::Accepted); this->close();}
void onCancelButtonClicked(){ this->setResult(QDialog::Rejected);this->close();}  

Note: Only after you have clicked the Ok button or Cancel button in a standard QMessageBox, setResult() function is triggered and the status is changed. It's not the same effect when done vice versa.

Case 2 The return value is incorrect.

I think only after your dialog gets closed, you will have the result available in result() function. So I guess it will be solved, after you have made the changes specified in Case 1.

If it still persists, use your own private member function to resolve it.



标签: c++ qt qdialog