Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Problem with pressing TAB key during QTableView cell edit
Forum Updated to NodeBB v4.3 + New Features

Problem with pressing TAB key during QTableView cell edit

Scheduled Pinned Locked Moved Unsolved General and Desktop
qt4.8qtableviewqitemdelegateeditortab
4 Posts 2 Posters 4.9k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • B Offline
    B Offline
    Ben35
    wrote on 18 Jul 2016, 12:55 last edited by Ben35
    #1

    Hello all,

    PROBLEM

    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.

    RESEARCH

    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)
    {
        Q_Q(QAbstractItemView);
        QWidget *w = editorForIndex(index).widget.data();
        if (!w) {
            QAbstractItemDelegate *delegate = delegateForIndex(index);
            if (!delegate)
                return 0;
            w = delegate->createEditor(viewport, options, index);
            if (w) {
               w->installEventFilter(delegate);
        ......
    }
    

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

    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 :

    setFocusPolicy(Qt::WheelFocus);
    setFocusProxy(internalSpinbox);
    

    Anyone to save me ? :)

    R 1 Reply Last reply 18 Jul 2016, 13:12
    0
    • B Ben35
      18 Jul 2016, 12:55

      Hello all,

      PROBLEM

      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.

      RESEARCH

      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)
      {
          Q_Q(QAbstractItemView);
          QWidget *w = editorForIndex(index).widget.data();
          if (!w) {
              QAbstractItemDelegate *delegate = delegateForIndex(index);
              if (!delegate)
                  return 0;
              w = delegate->createEditor(viewport, options, index);
              if (w) {
                 w->installEventFilter(delegate);
          ......
      }
      

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

      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 :

      setFocusPolicy(Qt::WheelFocus);
      setFocusProxy(internalSpinbox);
      

      Anyone to save me ? :)

      R Offline
      R Offline
      raven-worx
      Moderators
      wrote on 18 Jul 2016, 13:12 last edited by raven-worx
      #2

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

      --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
      If you have a question please use the forum so others can benefit from the solution in the future

      1 Reply Last reply
      1
      • B Offline
        B Offline
        Ben35
        wrote on 18 Jul 2016, 14:09 last edited by
        #3

        Not sure how i can do this ...

        1 Reply Last reply
        0
        • B Offline
          B Offline
          Ben35
          wrote on 18 Jul 2016, 14:56 last edited by
          #4

          I think i've found a solution.

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

          internalSpinbox->installEventFilter(this);
          

          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 http://stackoverflow.com/questions/12145522/why-pressing-of-tab-key-emits-only-qeventshortcutoverride-event
          
              if (event->type() == QEvent::KeyPress)
              {
                  auto keyEvent = static_cast<QKeyEvent *>(event);
                  if (keyEvent->key() == Qt::Key_Tab || keyEvent->key() == Qt::Key_Backtab) {
                      QApplication::postEvent(
                          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);
          }
          
          1 Reply Last reply
          1

          3/4

          18 Jul 2016, 14:09

          • Login

          • Login or register to search.
          3 out of 4
          • First post
            3/4
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved