4

I made a tree structure with QTreeWidget, and it works well. But I have a problem with that. Commonly, with a tree structure, if I want to deselect all, I click on a blank area of the tree-widget. But QTreeWidget does not seem to support that (or I can't find out how).

Could sub-classing or something else solve the problem? Determining a click on a blank area seems the key to the solution, but I can't find a signal or anything.

ekhumoro
  • 115,249
  • 20
  • 229
  • 336
Hyun-geun Kim
  • 919
  • 3
  • 22
  • 37

1 Answers1

9

The example code below will clear the selection (and current item) when clicking on a blank area, or when pressing Esc when the tree widget has the keyboard focus. It will work with any widget which inherits QAbstractItemView (not just QTreeWidget):

class MyWidget(QTreeWidget):
    def keyPressEvent(self, event):
        if (event.key() == Qt.Key_Escape and
            event.modifiers() == Qt.NoModifier):
            self.selectionModel().clear()
        else:
            super(MyWidget, self).keyPressEvent(event)

    def mousePressEvent(self, event):
        if not self.indexAt(event.pos()).isValid():
            self.selectionModel().clear()
        super(MyWidget, self).mousePressEvent(event)

To avoid subclassing, an event-filter can be used instead:

class MainWindow(QMainWindow):
    def __init__(self):
        super(MainWindow, self).__init__()
        self.widget = QTreeWidget()
        self.widget.installEventFilter(self)
        self.widget.viewport().installEventFilter(self)
        ...

    def eventFilter(self, source, event):
        if ((source is self.widget and
             event.type() == QEvent.KeyPress and
             event.key() == Qt.Key_Escape and
             event.modifiers() == Qt.NoModifier) or
            (source is self.widget.viewport() and
             event.type() == QEvent.MouseButtonPress and
             not self.widget.indexAt(event.pos()).isValid())):
            self.widget.selectionModel().clear()
        return super(Window, self).eventFilter(source, event)
ekhumoro
  • 115,249
  • 20
  • 229
  • 336
  • Thank you for your advice. It works well!!! But I modified above script a little... self.clearSelection() ---> self.setCurrentItem(None) clearSelection method deselect widget apparently but actually TreeWidget has a currentItem. So, I did select nothing. – Hyun-geun Kim Dec 16 '11 at 11:55
  • Nice answer, because not using `if self.itemAt(event.pos()) is None` you'd get the selection cleared when expanding/collapsing items :) – BPL Aug 03 '18 at 13:33