Как предотвратить закрытие ключа ввода QQialog (Qt 4.8.1)

У меня есть QDialog с QDialogButtonBox. Активны кнопки ОК и Отмена. Иногда я отключаю или скрываю кнопку "ОК" в зависимости от состояния моего диалога. Кажется, что бы я ни делал, клавиша Enter всегда активирует кнопку OK. Я действительно НЕ хочу, чтобы это произошло. Я пробовал:

  • Настройка свойств по умолчанию и autoDefault на false каждый раз, когда я показываю/скрываю/разрешаю/деактивирую/независимо от кнопки
  • установка фильтра событий на кнопке OK для перехвата ключевых событий (нажатых и отпущенных) для возврата, ввода и пробела
  • Настройка политики фокусировки на кнопке NoFocus

И при всех комбинациях этих вещей клавиша Enter все еще принимает диалог. Кто-нибудь знает, как это блокировать? Кажется, я должен уметь блокировать что-то столь же простое, как это?

Ответ 1

Фильтрация событий нажатия клавиш должна выполняться в самом диалоге, поскольку код, обрабатывающий пересылку ключей 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;
}

Ответ 2

Если у вас есть обычные QPushButtons в диалоговом окне, тогда, если у кнопок есть установленные параметры autoDefault и/или default, вы получаете кнопку по умолчанию - это то, что запускает ключ ввода. В этом случае избавиться от autoDefault на кнопках и нажать "Enter" в другом виджетах больше не закрывает диалог.

В случае QDialogButtonBox вы, вероятно, можете перебирать кнопки, чтобы отключить этот материал в ctor вашего диалога. Не проверено здесь, но должно работать. Если нет, вам также нужно будет увидеть, есть ли кнопка по умолчанию, которая также устанавливается на сам QDialog.

Ответ 3

QDialog имеет частный слот под названием accept(). Всякий раз, когда QDialogButtonBox испускает accepted() (нажав клавишу возврата или нажав "ОК" ), этот частный слот вызывается. Поэтому попробуйте отключить их.

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

Это сработало для меня.

Ответ 4

Проблема заключается в том, что фильтр событий не должен быть установлен на кнопку OK.

Если ваша кнопка ОК отключена, то она не получит событие ввода. Какой бы виджет не фокусировался. И если они не принимают событие ввода, то QDialog собирается accept().

Два способа решить проблему:

1) Переопределить QDialog::accept() и вызвать метод QDialog accept в новой функции accept только в том случае, если включено OK

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

Ответ 5

Чтобы избежать нажатия кнопки "ОК" или клавиши "Enter" из диалогового окна закрытия: в файле ui xml удалите соединение/слот для принятия/отклонения. Затем в вашем коде emmit accept(), когда и когда необходимо,

пример из файла ui, который соединяет слот accept():

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

Ответ 6

В вашем диалоге метод accept(), проверьте кнопку Ok для фокуса:

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

...

  QDialog::accept();
}

Ответ 7

В PySide (и я представляю PyQt) я смог переопределить функции accept и reject 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

Это закрыло диалоговое окно файла и дало мне доступ к данным, когда были активированы функции "ok" (accept) или "cancel" (отклонение) (либо с помощью ввода, либо путем нажатия кнопок)