Problem with pressing TAB key during QTableView cell edit

  • Hello all,


    I have a problem with the editing behaviour in a QTableView (i'm using Qt4.8). I have a QTableView in which i defined custom ItemDelegates with custom editors :

    • a custom widget A which inherits from QComboBox;
    • a custom widget B which inherits from QWidget and that contains a custom QDoubleSpinBox which inherits from QDoubleSpinBox;

    When i start edit a cell, a TAB keypress validates the current edition an the next cell becomes editable, which is the standard behaviour of QTableView. But with my custom editor widget B, when i press TAB during the edition, the focus is given to the next cell, but not in an editing mode. I don't have this problem with my custom widget A. I guess it is because this widget is composed with an internal spinbox.


    When a view calls createEditor function of delegate it also installs the delegate event filter to editor, so i guess that events on editor widgets are trapped and treated by the ItemDelegate :

    QWidget *QAbstractItemViewPrivate::editor(const QModelIndex &index,
                                              const QStyleOptionViewItem &options)
        QWidget *w = editorForIndex(index);
        if (!w) {
            QAbstractItemDelegate *delegate = delegateForIndex(index);
            if (!delegate)
                return 0;
            w = delegate->createEditor(viewport, options, index);
            if (w) {

    With the widget A, which work perfectly, the keyPressEvent is treated in eventFilter method of my delegate :

    bool QStyledItemDelegate::eventFilter(QObject *object, QEvent *event)
        QWidget *editor = qobject_cast<QWidget*>(object);
        if (!editor)
            return false;
        if (event->type() == QEvent::KeyPress) {
            switch (static_cast<QKeyEvent *>(event)->key()) {
            case Qt::Key_Tab:
                emit commitData(editor);
                emit closeEditor(editor, QAbstractItemDelegate::EditNextItem);
                return true;
            case Qt::Key_Backtab:
                emit commitData(editor);
                emit closeEditor(editor, QAbstractItemDelegate::EditPreviousItem);

    With my widget B, this eventFilter method doesn't receive the KeyPressEvent which is actually treated by the QWidget::event(QEvent *event) method of my internal spinbox, which explains why it does a focusNextPrevChild instead of the closeEditor(editor, QAbstractItemDelegate::EditNextItem) that i would expect.

        case QEvent::KeyPress: {
            QKeyEvent *k = (QKeyEvent *)event;
            bool res = false;
            if (!(k->modifiers() & (Qt::ControlModifier | Qt::AltModifier))) {  //### Add MetaModifier?
                if (k->key() == Qt::Key_Backtab
                    || (k->key() == Qt::Key_Tab && (k->modifiers() & Qt::ShiftModifier)))
                    res = focusNextPrevChild(false);
                else if (k->key() == Qt::Key_Tab)
                    res = focusNextPrevChild(true);
                if (res)

    WHY ?

    I don't undestand how to resolve my problem, and why this keyPressEvent on my custom editor B is not treated by the delegate.

    In my custom editor widget B, i already did this :


    Anyone to save me ? :)

  • Moderators

    @Ben35 said:

    I don't undestand how to resolve my problem, and why this keyPressEvent on my custom editor B is not treated by the delegate.

    Because the item delegate is only installed as event filter on the widget you create as editor. But you need to filter events of a child widget.
    So when creating the editor widget you also need to make sure to install the item delegate (this) as event filter on the sub-editor-widget.

  • Not sure how i can do this ...

  • I think i've found a solution.

    First, i install an eventFilter in my custom editor widget B on the internal spinbox :


    Then, i implement eventFilter to treat the events on the spinbox and duplicate them to the parent:

    bool AbstractRatioQuantitySpinbox::eventFilter(QObject *object, QEvent *event)
        // cf
        if (event->type() == QEvent::KeyPress)
            auto keyEvent = static_cast<QKeyEvent *>(event);
            if (keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab) {
                    this, new QKeyEvent(keyEvent->type(), keyEvent->key(), keyEvent->modifiers()));
                return true;
        else if (event->type() == QEvent::FocusOut)
            auto focusEvent = static_cast<QFocusEvent *>(event);
            QApplication::postEvent(this, new QFocusEvent(focusEvent->type(), focusEvent->reason()));
            return false;
        return QWidget::eventFilter(object, event);