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