4

I have a QTreeView populated with items from a model. When a call to edit() is made on an index, a custom editor displays. The editor consists of two QLineEdit widgets.

enter image description here

I want the focus to switch between the two QLineEdit widgets when Tab is pressed. However, pressing Tab cycles through everything else on my program. All my QPushButton and QTabWidget objects are included in the Tab order even though they are completely different widgets than my editor.

I've tried setting the tab order using setTabOrder() to loop it between the two QLineEdit widgets, however this still doesn't isolate the editor widget from the surrounding widgets. Why is this happening?

NOTE: I'm not trying to disable tab ordering anywhere else, just isolate it to my editor for the time being.

Thanks for your time!

mrg95
  • 2,371
  • 11
  • 46
  • 89
  • Show what you have tried. – eyllanesc Dec 31 '16 at 05:00
  • @eyllanesc I did. I said I tried setting a tab order (specifically one that loops around to the start) but that was ignored. The other thing I tried was to disable the focus of all other widgets that are being focused that I didn't want to, but the problem there obviously is that when not editing, I want to be able to tab focus those. – mrg95 Dec 31 '16 at 05:05
  • Check out the **documentation**. It may not necessarily help with this but it very often helps. – Cheers and hth. - Alf Dec 31 '16 at 05:33
  • Yeah I did, that's where I read about how `setTabOrder` works and why I can't loop it back to the start. It's the first place I go, but sometimes it's tough when you don't know what to look for. – mrg95 Dec 31 '16 at 05:35
  • Do the line edits even get the tab key event, or is it filtered out before? – peppe Dec 31 '16 at 12:52
  • @peppe The get the event. They cycle along with around 10 other things around my program. But I would like the tab to only cycle in the editor widget, similar to a QMenu only tabs through it's items. – mrg95 Dec 31 '16 at 12:59
  • So, worst case scenario, you could just subclass QLineEdit, reimplement the `event` method, and cycle the focus to the other line edit? – peppe Dec 31 '16 at 13:08
  • So is that the answer? Just.... not use it? There's really no way to isolate a widget for tab focus like the base QMenu class does to it's items? Or dialogs? or whatever without subclassing it and listening for keys? – mrg95 Dec 31 '16 at 13:18
  • Subclass the lineedit to be able to set a prefered sibling. Reimplement the keyevent and consume it on tab press. Manually set focus to the sibling. – Sebastian Lange Apr 04 '17 at 07:38
  • @SebastianLange Would you mind posting this as an answer? I subclassed `QLineEdit` and reimplemented both `eventFilter` and `keyPressEvent` and pressing tab fires neither event. I even reimplemented the `eventFilter` function found in the subclassed `QStyledItemDelegate` that holds the custom editor widget and all Tab key press events are not called. Other keys do however. It's being filtered somewhere and it's really annoying. – mrg95 Apr 05 '17 at 14:25
  • You need to install an event filter on `QTreeView` (or `view->viewport()`) and filter out "tab" keyboard events when start editing delegate is called. Unfortunatly I have no installed Qt on my PC now, so I can't provide a code sample. You may check this for some code: http://stackoverflow.com/questions/22813494/qcombobox-with-checkboxes – Dmitry Sazonov Apr 06 '17 at 08:15
  • `QMenu` realization also use reimplemented `event` method for correcting tab order – ramzes2 Apr 06 '17 at 09:58
  • @DmitrySazonov I just installed an event filter on `QTreeView` and it's not getting any key press events either. It's so weird, the delegate gets key press event but not tab. The line edits get key press events but not tab. And QTreeView gets none. – mrg95 Apr 06 '17 at 12:05
  • @mrg95 did you try to set an event filter on viewport? – Dmitry Sazonov Apr 06 '17 at 12:47
  • Yep. I did `treeView->viewport()->installEventFilter(treeView);` and there was no change. – mrg95 Apr 06 '17 at 13:10

1 Answers1

3

This can be easily implemented using QWidget::focusNextPrevChild as follows:

class EditWidget : public QWidget
{
public:
  EditWidget(QWidget *pParent) : QWidget(pParent)
  {
    QHBoxLayout *pLayout = new QHBoxLayout(this);
    setLayout(pLayout);
    pLayout->addWidget(m_pEdit1 = new QLineEdit ());
    pLayout->addWidget(m_pEdit2 = new QLineEdit ());
  }

  bool focusNextPrevChild(bool next)
  {
    if (m_pEdit2->hasFocus())
      m_pEdit1->setFocus();
    else
      m_pEdit2->setFocus();
    return true; // prevent further actions (i.e. consume the (tab) event)
  }

protected:
  QLineEdit *m_pEdit1;
  QLineEdit *m_pEdit2;
};
m7913d
  • 10,244
  • 7
  • 28
  • 56
  • PERFECT! Thank you so much! I'm surprised it took so long when the answer was so simple. This is exactly what I was looking for :D :D :D – mrg95 Apr 07 '17 at 08:07