我有一个
QDialog
和 QDialogButtonBox
。 OK 和Cancel 按钮处于活动状态。有时,我会根据对话框的状态禁用或隐藏“确定”按钮。看来,无论我做什么,Enter 键总是会激活“确定”按钮。我真的不希望这种事发生。我试过了:
对于上述所有内容的组合,Enter 键仍然接受该对话框。有谁知道如何阻止这个?这么简单的事情好像我也能屏蔽掉?
按键事件过滤应该在对话框本身上完成,因为处理将
Return
和 Enter
键转发到默认按钮的代码位于 QDialog::keyPressEvent
中。
void Dialog::keyPressEvent(QKeyEvent *evt)
{
if(evt->key() == Qt::Key_Enter || evt->key() == Qt::Key_Return)
return;
QDialog::keyPressEvent(evt);
}
或者
theDialog−>installEventFilter(anotherClassObject);
bool AnotherClass::eventFilter(QObject *obj, QEvent *evt)
{
if(evt->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent*>(evt);
if(keyEvent->key() == Qt::Key_Enter || keyEvent->key() == Qt::Key_Return )
return true; // mark the event as handled
}
return false;
}
如果对话框上有普通的 QPushButtons,那么如果按钮设置了 autoDefault 和/或默认属性,那么您将获得一个默认按钮 - 这是 Enter 键触发的。在这种情况下,摆脱按钮上的 autoDefault 并在另一个小部件中按 Enter 键不再关闭对话框。
对于 QDialogButtonBox,您可能可以迭代按钮以在对话框的构造函数中关闭此功能。此处未测试,但应该可以工作。如果没有,那么您还需要查看 QDialog 本身是否也设置了默认按钮。
一种选择是覆盖对话框的显示事件,以便允许显示 QDialogButtonBox,之后它将设置一个带有 AcceptRole 的默认按钮,然后将所有按钮设置为非默认按钮。
void MyDialog::showEvent(QShowEvent* event)
{
// When a QDialogButtonBox is shown, it will set a default button if none are found so we need to disable the
// default buttons after the button box has been shown.
QDialog::showEvent(event);
// For example, with a dialog which has two buttons, Save and Cancel, we remove all defaults
// It might be good enough to remove the default on just the buttons with have the AcceptRole, but
// I didn't test extensively enough to see what would happen if any buttons had "autoDefault" set or
// verify this behavior on all platforms.
ui->buttonBox->button(QDialogButtonBox::Save)->setDefault(false);
ui->buttonBox->button(QDialogButtonBox::Cancel)->setDefault(false);
}
尝试在显示 QDialogButtonBox 之前删除默认值,例如在对话框的构造函数中,只会被 QDialogButtonBox::showEvent() 中的代码覆盖。
问题是事件过滤器不应该安装在“确定”按钮上。
如果您的“确定”按钮被禁用,那么它将不会收到输入事件。无论哪个小部件获得焦点都会。如果他们不接受输入事件,那么
QDialog
将会 accept()
本身。
解决问题的两种方法:
1) 覆盖
QDialog::accept()
,仅当启用 OK 时才在新 QDialog
函数中调用 accept
的 Accept 方法
void MyDialog::accept() {
if (okEnabled) {
QDialog::accept();
}
}
2) 在对话框中的每个小部件上安装一个事件过滤器,不接受回车键(行编辑,...)。
事件过滤器就像这样:
class KeyPressEater : public QObject
{
Q_OBJECT
protected:
bool eventFilter(QObject *obj, QEvent *event);
};
bool KeyPressEater::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::KeyPress) {
QKeyEvent *keyEvent = static_cast<QKeyEvent *>(event);
bool res = QObject::eventFilter(obj, event);
if (keyEvent->key() == Qt::Key_Return) {
return true; /* Always accept return */
} else {
return res;
}
} else {
// standard event processing
return QObject::eventFilter(obj, event);
}
}
在您的代码中,对于对话框中的每个小部件:
myWidget->installEventFilter(myKeyPressEater);
QDialog 有一个名为
accept()
的私有插槽。每当 QDialogButtonBox 发出 accepted()
(通过按回车键或单击“确定”)时,就会调用该专用插槽。所以尝试断开它们。
disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));
这对我有用。
避免使用“确定”按钮或“Enter”键关闭对话框: 在 ui xml 文件中,删除接受/拒绝的连接/插槽。然后,在您的代码中,根据需要发出 Accept() ;
连接accept()槽的ui文件示例:
<connections>
<connection>
<sender>products_ButtonBox</sender>
<signal>accepted()</signal>
<receiver>Products_Dialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>e
</hints>
</connection>
在对话框的
accept()
方法中,选中“确定”按钮以获得焦点:
void accept() override
{ if (!dialogButtonBox->button(QDialogButtonBox::Ok)->hasFocus())
return;
...
QDialog::accept();
}
关键是要设置自己的按钮,都是NoRole,既不接受也不拒绝来自按钮框的信号。这将允许您为默认按钮设置自己的行为。
class Dialog(QDialog):
def __init__():
super(Dialog, self).__init__()
self.buttonBox = QDialogButtonBox()
self.btn_save = self.buttonBox.addButton('Save', QDialogButtonBox.NoRole)
self.btn_cancel = self.buttonBox.addButton('Cancel', QDialogButtonBox.NoRole)
self.btn_save.clicked.connect(self.onAccept)
self.btn_save.setMouseTracking(True)
self.btn_cancel.clicked.connect(self.onReject)
# STATUS BAR
self.status = QStatusBar()
self.status.addPermanentWidget(self.buttonBox)
def onAccept(self):
if not self.btn_save.underMouse():
return
self.submitChanges(self.model)
self.accept()
def onReject(self):
self.reject()
由于多种原因,上述答案对我不起作用。
我最终添加了一个隐形按钮并将其设置为默认按钮。
也许这个简单俗气的想法会对某人有所帮助。
在 PySide(我想是 PyQt)中,我能够重新定义 QDialog 的接受和拒绝函数。
def custom_accept ():
# perform custom actions when you hit open
pass
def custom_reject ():
# perform custom actions when you hit cancel
pass
file_dialog = QtGui.QFileDialog(directory=".")
file_dialog.accept = custom_accept
file_dialog.reject = custom_reject
这可以防止文件对话框关闭,并在触发“确定”(接受)或“取消”(拒绝)功能(通过输入或单击按钮)时让我访问数据