Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Selection change on key press in QTreeView



  • I have a relatively simple task - I need to get the currently selected item details from QTreeView after the user pressed a key.
    Simple scenario: the user clicks some element in the tree and then presses "arrow down" key. I need to get the element that is currently in focus. I haven't found the built-in mechanism in QTreeView for getting the key pressed events, so I'm using eventFilter().

    I expect that after user presses a key currentIndex() changes and I can get the value, however this doesn't happen. If you run the example below you'll see that the function returns the currently selected file on mouse click, but if you press arrow up/down after that the selection seems to "lag" - it shows the file from the previously selected index. However, if you press the arrow up/down and then something else, for example, Enter, it will return the expected result.

    What am I missing?
    Thanks.

    from PySide6.QtCore import *
    from PySide6.QtGui import *
    from PySide6.QtWidgets import *
    
    if __name__ == '__main__':
        class Dialog(QDialog):
            def __init__(self, parent=None):
                super(Dialog, self).__init__(parent)
                self.initUI()
                self.model = QFileSystemModel()
                self.model.setRootPath(".")   
                self.view.setModel(self.model)
                self.view.setRootIndex(self.model.index("."))
                self.view.clicked.connect(self.print_item)
                self.view.installEventFilter(self)
    
            def eventFilter(self, source, event):
                if source == self.view:
                    if event.type() == QEvent.KeyPress:
                        self.print_item()
                        return False
                return super(Dialog, self).eventFilter(source, event)
    
            def print_item(self):
                print(self.model.filePath(self.view.currentIndex()))
    
            def initUI(self):
                self.view = QTreeView(self)
                self.view.setWindowTitle('Simple Tree Model')
                self.view.setGeometry(10, 10, 400, 300)
                self.setGeometry(300, 300, 420, 320)
    
        import sys
    
        app = QApplication(sys.argv)
        dialog = Dialog()
        dialog.show()
        sys.exit(app.exec_())
    


  • @midnightdim
    Purely at a guess: the selection won't have changed till after you have allowed the default Qt handling of the key press? Whereas in your eventFilter() you do it before the default. Try something like:

            def eventFilter(self, source, event):
                result = super(Dialog, self).eventFilter(source, event)
                if source == self.view:
                    if event.type() == QEvent.KeyPress:
                        self.print_item()
                        return False
                return result
    

    Separate question from why you need even filter at all, not just handle currentChanged/selectionChanged?



  • @JonB said in Selection change on key press in QTreeView:

    Separate question from why you need even filter at all, not just handle currentChanged/selectionChanged?

    I didn't know how to do that :-) But now I figured it out, thanks!

    P.S. Changing the order of key press handling in eventFilter doesn't seem to have the effect.


Log in to reply