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
QtWS25 Last Chance

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 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 ? :)

    raven-worxR 1 Reply Last reply
    0
    • B Ben35

      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 ? :)

      raven-worxR Offline
      raven-worxR Offline
      raven-worx
      Moderators
      wrote on 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 last edited by
        #3

        Not sure how i can do this ...

        1 Reply Last reply
        0
        • B Offline
          B Offline
          Ben35
          wrote on 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

          • Login

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