Метод 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"