【问题标题】:QMessageBox result as a buttonroleQMessageBox 结果为按钮角色
【发布时间】:2017-04-06 20:08:08
【问题描述】:

我想将 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");
    }

【问题讨论】:

    标签: c++ qt qmessagebox qt5.7


    【解决方案1】:

    question 方法是静态的。它不使用您上面的消息框。您方法的前 3 行基本上什么都不做。

    这就是你的方法的真正作用:

    void MainWindow::on_pushButton_clicked()
    {
        int result = QMessageBox::question(this,"Hola","My 1st Msg");
        [...]
    }
    

    唉,QMessageBox 有一个长期存在的错误:在接受或拒绝对话框时,它会忽略 (!) 自定义按钮角色。虽然角色被传递给底层QDialogButtonBox,但在单击按钮时无法正确解释。

    虽然您可以使用QMessageBox::buttonRole 找回角色,但QMessageBoxPrivate::_q_buttonClicked 使用按钮的index 调用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"
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-11-07
      • 1970-01-01
      • 2019-09-19
      • 1970-01-01
      • 2014-05-19
      • 1970-01-01
      • 2016-06-23
      • 1970-01-01
      相关资源
      最近更新 更多