Теперь я могу обрабатывать все нажатия клавиш в моей QTableWidget
в функции eventFilter()
(после вызова myTable->viewport()->installEventFilter(this);
в конструкторе).
Единственное место, где это не работает, - редактируемая ячейка при редактировании (потому что она захватывает все нажатия клавиш). Чтобы исправить это, я не могу вызвать installEventFilter()
для каждого элемента таблицы, потому что эти элементы не являются QObject
(а также я не могу использовать connect
для ввода моей обработки нажатия клавиш).
Единственное решение, которое у меня есть, - это положить QLineEdit
в эти ячейки и использовать фильтр событий для захвата нажатия клавиш во время редактирования. Но можно ли разрешить его, используя только стандартные элементы? (т.е. только QTableWidgetItem
с флагом Qt::ItemIsEditable
)
Также я могу вызвать grabKeyboard()
для моего QTableWidget
. В этом случае у меня будут все нажатия клавиш (даже при редактировании ячеек пользователем), но он блокирует окно редактирования (т.е. Пользователь не может вводить ничего). Может быть, можно исправить сломанные поля редактирования после вызова grabKeyboard()
для таблицы?
Это так легко достичь. Просто подкласс QStyledItemDelegate
переопределяет createEditor
метод следующим образом:
QWidget *AlterEditorDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QWidget *result = QStyledItemDelegate::createEditor(parent, option, index);
result->installEventFilter(new YourEventFilter(result));
return result;
}
Вместо замены делегата для QTableWidget.
Или даже лучше подклассифицировать класс прокси, который принимает оригинал QAbstractItemDelegate
(более написание, но гораздо более универсальное и может быть составлено с другими изменениями).
AlterEditorProxyDelegate::AlterEditorProxyDelegate(QAbstractItemDelegate *original, QObject *parent)
: QAbstractItemDelegate(parent)
, original(original)
{}
QWidget *AlterEditorProxyDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const {
QWidget *result = original->createEditor(parent, option, index);
result->installEventFilter(new YourEventFilter(result));
return result;
}
// other methods which invokes respective methods for `original` style.
Но можно ли его решить, используя только стандартные элементы? (т.е. только QTableWidgetItem с флагом Qt:: ItemIsEditable)
Не совсем. В Qt4 QTableWidget
утечка KeyRelease
событий из редактора ячейки, но использование этого было бы уродливым взломом.
Может быть, можно исправить сломанные поля редактирования после вызова grabKeyboard() для таблицы?
Я как-то пробовал это, а затем отправлял события на QTableWidget
, но столкнулся с проблемой.
Собственно, нужно создать собственный делегат и установить фильтр событий в createEditor
. Вы можете сделать что-то вроде этого:
class FilterDelegate : public QStyledItemDelegate
{
public:
FilterDelegate(QObject *filter, QObject *parent = 0) :
QStyledItemDelegate(parent), filter(filter)
{ }
virtual QWidget *createEditor(QWidget *parent,
const QStyleOptionViewItem &option,
const QModelIndex &index) const
{
QWidget *editor = QStyledItemDelegate::createEditor(parent, option, index);
editor->installEventFilter(filter);
return editor;
}
private:
QObject *filter;
};
Тогда ваш конструктор MainWindow
будет выглядеть примерно так:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
setupUi(this);
tableWidget->setItemDelegate(new FilterDelegate(this));
tableWidget->installEventFilter(this);
}
И ваш фильтр событий:
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
// do something
}
return QMainWindow::eventFilter(obj, event);
}
tableWidget->installEventFilter(this);
не обязательно. Ты согласен?
ДРУГОЙ АЛЬТЕРНАТИВ:
Вы можете установить фильтр событий на объект QApplication
и зафиксировать все события. Это немного лишний, если вы спросите меня, но он будет работать для небольшого приложения и требует минимального кода.
Все, что вам нужно сделать, это:
qApp->installEventFilter(this);
и
bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{
if(event->type() == QEvent::KeyPress)
{
// do something
}
return QMainWindow::eventFilter(obj, event);
}
Так как QTableWidgetItem не имеет функции keyEvent(), которую вы можете перегрузить, это невозможно.
Что вам нужно сделать, это установить делегат с настраиваемым редактором factory, который создает виджеты, где keyEvent перегружен.
grabKeyboard()
для моего QTableWidget
. После этого у меня будут все нажатия клавиш (даже при редактировании ячеек пользователем), но также и это поле редактирования не будет работать так, как ожидается.
QTableWidgetItem
подклассыQTableWidgetItem
, чтобы иметь все функцииQTableWidgetItem
и ваши собственные функции для получения желаемого поведения?