Как предотвратить закрытие ключа ввода 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" (отклонение) (либо с помощью ввода, либо путем нажатия кнопок)