QMessageBox结果作为按钮角色

3

我希望能够将QMessageBox的结果作为按钮角色来获取,但是结果总是16384或65536。我不想使用标准结果,只想使用按钮角色类型的按钮。我在这里做错了什么吗?
(我在QT中非常新手)

    void MainWindow::on_pushButton_clicked()
    {
        QMessageBox msgBox;
        QPushButton *a=msgBox.addButton("OK",QMessageBox::ActionRole);
        QPushButton *b=msgBox.addButton("CANCEL",QMessageBox::RejectRole);

        int result=msgBox.question(this,"Hola","My 1st Msg");
        //result always return 16384 or 65536(integer) PROBLEM HERE
        if(result==QMessageBox::RejectRole)
            this->setWindowTitle("rejected");
        else
            this->setWindowTitle("accepted");
    }
1个回答

3
question 方法是静态的,它不使用你上面的消息框。你方法的前三行本质上没做任何事情。
以下是你的方法实际执行的内容:
void MainWindow::on_pushButton_clicked()
{
    int result = QMessageBox::question(this,"Hola","My 1st Msg");
    [...]
}

哎呀,QMessageBox 有一个长期存在的 bug:当涉及到对话框的接受或拒绝时,它会忽略自定义按钮角色。虽然角色被传递给底层的 QDialogButtonBox,但是当点击按钮时,它并没有被正确地解释。

尽管你可以使用 QMessageBox::buttonRole 获取角色,但是 QMessageBoxPrivate::_q_buttonClicked 通过按钮的索引调用了 QDialog::done

因此,第一个添加的按钮将导致对话框被拒绝,第二个按钮将导致对话框被接受,而进一步的按钮将不会产生作用。接受/拒绝完全忽略了角色,仅基于按钮的索引,由于添加的顺序。

因此,除非前两个按钮按照这个顺序直接映射到这些角色,否则不应该使用 rejected/accepted 信号,应该使用 buttonClicked 信号并直接获取按钮的角色:

void MainWindow::on_pushButton_clicked()
{
   auto box = new QMessageBox{this};
   box->setAttribute(Qt::WA_DeleteOnClose);
   box->addButton("OK", QMessageBox::ActionRole);
   box->addButton("CANCEL", QMessageBox::RejectRole);
   box->setIcon(QMessageBox::Question);
   box->setWindowTitle("Hola");
   box->setText("My 1st message.");
   box->show();

   connect(box, &QMessageBox::buttonClicked, [=](QAbstractButton *button){
      switch (box->buttonRole(button)) {
      case QMessageBox::AcceptRole: return setWindowTitle("accept-role");
      case QMessageBox::ActionRole: return setWindowTitle("action-role");
      case QMessageBox::RejectRole: return setWindowTitle("reject-role");
      }
   });
}

哎呀,还有一个问题:如果通过平台的窗口管理器(对话框标题栏上的关闭按钮)关闭对话框,它也将被拒绝。因此,您需要能够使用rejected信号,但不是在出错时使用。最好将此功能分解到一个MessageBoxAdapter类中,该类仅会发出正确的acceptedrejected信号:

// https://github.com/KubaO/stackoverflown/tree/master/questions/messagebox-roles-40753898
#include <QtWidgets>

class MessageBoxAdapter : public QObject {
   Q_OBJECT
public:
   MessageBoxAdapter(QObject *parent = nullptr) : QObject(parent) {
      watch(parent);
   }
   void watch(QObject *obj) {
      auto box = qobject_cast<QMessageBox*>(obj);
      if (!box) return;
      connect(box, &QMessageBox::rejected, [=]{
         if (!box->clickedButton()) emit rejected();
      });
      connect(box, &QMessageBox::buttonClicked, [=](QAbstractButton *button){
         auto role = box->buttonRole(button);
         if (role == QMessageBox::AcceptRole) emit accepted();
         else if (role == QMessageBox::RejectRole) emit rejected();
         emit roleClicked(role);
      });
   }
   Q_SIGNAL void accepted();
   Q_SIGNAL void rejected();
   Q_SIGNAL void roleClicked(QMessageBox::ButtonRole role);
};

还需要一些用户界面来尝试它:

struct Ui : public QWidget {
   QVBoxLayout layout{this};
   QTextBrowser browser;
   QPushButton button{"Open"};
   MessageBoxAdapter adapter{this};
public:
   Ui() {
      layout.addWidget(&browser);
      layout.addWidget(&button);
      connect(&button, &QPushButton::clicked, this, &Ui::onClicked);
      connect(&adapter, &MessageBoxAdapter::accepted, [=]{ browser.append("accepted"); });
      connect(&adapter, &MessageBoxAdapter::rejected, [=]{ browser.append("rejected"); });
      connect(&adapter, &MessageBoxAdapter::roleClicked, [=](QMessageBox::ButtonRole role){
         browser.append(QStringLiteral("clicked role=%1").arg(role));
      });
   }
   void onClicked() {
      auto box = new QMessageBox{this};
      adapter.watch(box);
      box->setAttribute(Qt::WA_DeleteOnClose);
      box->addButton("OK", QMessageBox::AcceptRole);
      box->addButton("ACTION", QMessageBox::ActionRole);
      box->addButton("CANCEL", QMessageBox::RejectRole);
      box->setIcon(QMessageBox::Question);
      box->setWindowTitle("Hola");
      box->setText("My 1st message.");
      box->show();
   }
};

int main(int argc, char ** argv) {
   QApplication app{argc, argv};
   Ui ui;
   ui.show();
   return app.exec();
}
#include "main.moc"

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接