20

我有QDialog一个QDialogButtonBoxOKCancel按钮处于活动状态。有时我会根据对话框的状态禁用或隐藏“确定”按钮。看来,无论我做什么,Enter 键总是会激活 OK 按钮。我真的不希望这种情况发生。我努力了:

  • 每次我显示/隐藏/启用/禁用/任何按钮时,将默认和自动默认属性设置为 false
  • 在 OK 按钮上安装事件过滤器以拦截关键事件(按下和释放)以进行返回、输入和空格
  • 将按钮上的焦点策略设置为NoFocus

上面这些东西的所有组合,回车键仍然接受对话框。有谁知道如何阻止这个?看来我应该能够阻止像这样简单的事情?

4

9 回答 9

20

按键事件过滤应该在对话框本身上完成,因为处理将ReturnEnter键转发到默认按钮的代码位于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;
}
于 2013-04-06T00:15:08.577 回答
4

如果您在对话框上有正常的 QPushButtons,那么如果按钮上设置了 autoDefault 和/或默认属性,那么您将获得一个默认按钮 - 这是 enter 键触发的内容。在这种情况下,去掉按钮上的 autoDefault 并在另一个小部件中按 enter 不再关闭对话框。

在 QDialogBu​​ttonBox 的情况下,您可能可以遍历按钮以在对话框的 ctor 中关闭这些东西。在这里没有测试,但应该可以工作。如果没有,那么您还需要查看 QDialog 本身是否也设置了默认按钮。

于 2015-01-27T16:11:04.917 回答
2

问题是事件过滤器不应该安装在确定按钮上。

如果您的 OK 按钮被禁用,那么它将不会收到 enter 事件。无论哪个小部件都有焦点。如果他们不接受 enter 事件,那么QDialog就会accept()自行处理。

解决问题的两种方法:

1)仅当启用 OK时,才在新函数中覆盖QDialog::accept()和调用accept 方法QDialogaccept

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);
于 2013-12-29T02:15:08.910 回答
2

QDialog 有一个名为accept(). 每当 QDialogBu​​ttonBox 发出accepted()(通过按返回键或单击确定)时,就会调用该私有插槽。所以尝试断开它们。

disconnect(ui->buttonBox, SIGNAL(accepted()), this, SLOT(accept()));

这对我有用。

于 2013-04-08T20:43:16.063 回答
1

为避免关闭对话框中的“确定”按钮或“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>
于 2017-07-08T21:02:03.337 回答
0

在对话框的accept()方法中,检查确定按钮以获得焦点:

void accept() override
{ if (!dialogButtonBox->button(QDialogButtonBox::Ok)->hasFocus())
  return;

...

  QDialog::accept();
}
于 2019-06-24T19:18:02.053 回答
0

关键是设置自己的按钮,全部使用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()
于 2020-07-07T18:48:36.260 回答
0

一种选择是覆盖对话框的显示事件以允许显示 QDialogBu​​ttonBox,之后它将设置一个带有 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);
}

尝试在 QDialogBu​​ttonBox 显示之前删除默认值,例如在对话框的构造函数中,将被 QDialogBu​​ttonBox::showEvent() 中的代码覆盖。

于 2021-06-18T16:03:31.877 回答
-1

在 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

这使文件对话框无法关闭,并允许我在触发“确定”(接受)或“取消”(拒绝)功能时访问数据(通过输入或单击按钮)

于 2013-09-23T17:46:17.457 回答