How to catch keystrokes in editable QTableWidgetItem?

Now I can handle all keystrokes in my QTableWidget in the eventFilter() function (after calling myTable->viewport()->installEventFilter(this); in the constructor).

The only place where this does not work is the editable cell when editing (because it captures all keystrokes). To fix this, I cannot call installEventFilter() for each element of the table, because these elements are not a QObject (nor can I use connect to enter my keystroke processing).

The only solution I have is to put a QLineEdit in these cells and use an event filter to capture keystrokes during editing. But is it possible to resolve it using only standard elements? (i.e. only QTableWidgetItem with the Qt::ItemIsEditable )

Also I can call grabKeyboard() for my QTableWidget . In this case, I will have all the keystrokes (even when editing cells by the user), but it blocks the editing window (i.e., the User cannot enter anything). Maybe you can fix broken edit fields after calling grabKeyboard() on the table?

+5
source share
4 answers

It is so easy to achieve. Just a subclass of QStyledItemDelegate overrides the createEditor method as follows:

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

Instead of replacing the delegate for QTableWidget.

Or it is even better to subclass the proxy class that accepts the original QAbstractItemDelegate (more spelling, but much more universal and can be compiled with other changes).

 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. 
+2
source

Since QTableWidgetItem does not have a keyEvent () function that you can overload, this is not possible.

What you need to do is install a delegate with a custom factory editor that creates widgets where keyEvent is overloaded.

+1
source

But can it be solved using only standard elements? (i.e. only QTableWidgetItem with the Qt :: ItemIsEditable flag)

Not really. In Qt4, a QTableWidget leaks KeyRelease events from the cell editor, but using this would be an ugly hack.

Maybe you can fix broken edit fields after calling grabKeyboard () on the table?

I tried this somehow and then dispatched events to a QTableWidget , but ran into a problem.

Actually, you need to create your own delegate and set the event filter in createEditor . You can do something like this:

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

Then your MainWindow constructor will look something like this:

 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent) { setupUi(this); tableWidget->setItemDelegate(new FilterDelegate(this)); tableWidget->installEventFilter(this); } 

And your event filter:

 bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if(event->type() == QEvent::KeyPress) { // do something } return QMainWindow::eventFilter(obj, event); } 
+1
source

OTHER ALTERNATIVE:

You can set an event filter on a QApplication object and commit all events. This is a little redundant if you ask me, but it will work for a small application and requires minimal code.

All you have to do is:

 qApp->installEventFilter(this); 

and

 bool MainWindow::eventFilter(QObject *obj, QEvent *event) { if(event->type() == QEvent::KeyPress) { // do something } return QMainWindow::eventFilter(obj, event); } 
+1
source

Source: https://habr.com/ru/post/1246936/


All Articles