2016-11-23 7 views
3

Я хочу получить результат QMessagebox как buttonrole. но результат всегда 16384 или 65536 Я не хочу использовать стандартные результаты, хочу использовать только кнопки типа кнопок. что я делаю неправильно здесь?
(я очень новичок в QT)Результат QMessageBox как buttonrole

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

ответ

2

Метод question является статическим. Он не использует окно сообщения, которое вы указали выше. Первые 3 строки вашего метода по существу ничего не делают.

Вот что ваш метод действительно:

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

Увы, QMessageBox имеет давнюю ошибку: она игнорирует пользовательские роли кнопки, когда речь идет о принятии или отказе от диалога (!). Хотя роль передается в базовый 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 класс, который будет издавать только правильные accepted и rejected сигналы:

// 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"