QMessageBox 结果作为按钮角色
QMessageBox result as a buttonrole
我想将 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");
}
question
方法是静态的。它不使用您上面的消息框。您的方法的前 3 行基本上什么都不做。
以下是您的方法的实际作用:
void MainWindow::on_pushButton_clicked()
{
int result = QMessageBox::question(this,"Hola","My 1st Msg");
[...]
}
唉,QMessageBox
有一个 long-standing 错误:它在接受或拒绝对话框时忽略 (!) 自定义按钮角色。当角色被传递到基础 QDialogButtonBox
时,单击按钮时它没有被正确解释。
尽管您可以使用 QMessageBox::buttonRole
取回角色,但 QMessageBoxPrivate::_q_buttonClicked
会使用按钮的 index 调用 QDialog::done
。
因此,您添加的第一个按钮将导致对话框被拒绝,第二个按钮将导致对话框被接受,而更多的按钮将导致两者都不会。由于添加的顺序,acceptance/rejection 完全忽略该角色,仅基于按钮的索引。
因此你不应该使用 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");
}
});
}
唉,还有另一个问题:通过平台的 window 管理器(对话框标题栏上的关闭按钮)关闭对话框也会被拒绝。所以你需要能够使用 rejected
信号,但不是在它出错的时候。最好将此功能分解为 MessageBoxAdapter
class,它只会发出正确的 accepted
和 rejected
信号:
// https://github.com/KubaO/Whosebugn/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"
我想将 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");
}
question
方法是静态的。它不使用您上面的消息框。您的方法的前 3 行基本上什么都不做。
以下是您的方法的实际作用:
void MainWindow::on_pushButton_clicked()
{
int result = QMessageBox::question(this,"Hola","My 1st Msg");
[...]
}
唉,QMessageBox
有一个 long-standing 错误:它在接受或拒绝对话框时忽略 (!) 自定义按钮角色。当角色被传递到基础 QDialogButtonBox
时,单击按钮时它没有被正确解释。
尽管您可以使用 QMessageBox::buttonRole
取回角色,但 QMessageBoxPrivate::_q_buttonClicked
会使用按钮的 index 调用 QDialog::done
。
因此,您添加的第一个按钮将导致对话框被拒绝,第二个按钮将导致对话框被接受,而更多的按钮将导致两者都不会。由于添加的顺序,acceptance/rejection 完全忽略该角色,仅基于按钮的索引。
因此你不应该使用 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");
}
});
}
唉,还有另一个问题:通过平台的 window 管理器(对话框标题栏上的关闭按钮)关闭对话框也会被拒绝。所以你需要能够使用 rejected
信号,但不是在它出错的时候。最好将此功能分解为 MessageBoxAdapter
class,它只会发出正确的 accepted
和 rejected
信号:
// https://github.com/KubaO/Whosebugn/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"