Python: PyQt QTreeview example - selection
Asked Answered
G

4

10

I'm using Python 2.7 and Qt designer and I'm new to MVC: I have a View completed within Qt to give me a directory tree list, and the controller in place to run things. My question is:

Given a Qtree view, how may I obtain a directory once a dir is selected?

enter image description here

Code snap shot is below, I suspect it's SIGNAL(..) though I'm unsure:

class Main(QtGui.QMainWindow):
  plot = pyqtSignal()

  def __init__(self):
    QtGui.QMainWindow.__init__(self)
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)

    # create model
    model = QtGui.QFileSystemModel()
    model.setRootPath( QtCore.QDir.currentPath() )

    # set the model
    self.ui.treeView.setModel(model)

    **QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)**

  def test(self):
    print "hello!"
Glare answered 2/6, 2014 at 11:52 Comment(0)
O
17

The signal you're looking for is selectionChanged emmited by the selectionModel owned by your tree. This signal is emmited with the selected item as first argument and the deselected as second, both are instances of QItemSelection.

So you might want to change the line:

QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)

to

QtCore.QObject.connect(self.ui.treeView.selectionModel(), QtCore.SIGNAL('selectionChanged()'), self.test)

Also I recommend you to use the new style for signals and slots. Redefine your test function as:

 @QtCore.pyqtSlot("QItemSelection, QItemSelection")
 def test(self, selected, deselected):
     print("hello!")
     print(selected)
     print(deselected)

Here you have a working example:

from PyQt4 import QtGui
from PyQt4 import QtCore

class Main(QtGui.QTreeView):

  def __init__(self):

    QtGui.QTreeView.__init__(self)
    model = QtGui.QFileSystemModel()
    model.setRootPath( QtCore.QDir.currentPath() )
    self.setModel(model)
    QtCore.QObject.connect(self.selectionModel(), QtCore.SIGNAL('selectionChanged(QItemSelection, QItemSelection)'), self.test)

  @QtCore.pyqtSlot("QItemSelection, QItemSelection")
  def test(self, selected, deselected):
      print("hello!")
      print(selected)
      print(deselected)

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(app.exec_())

PyQt5

In PyQt5 is a little bit different (thanks to Carel and saldenisov for comments and aswer.)

... connect moved from being an object method to a method acting upon the attribute when PyQt went from 4 to 5

So instead the known:

QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)

now you write:

class Main(QTreeView):
    def __init__(self):
        # ...  
        self.setModel(model)
        self.doubleClicked.connect(self.test)  # Note that the the signal is now a attribute of the widget.

Here is a the example (by saldenisov) using PyQt5.

from PyQt5.QtWidgets import QTreeView,QFileSystemModel,QApplication

class Main(QTreeView):
    def __init__(self):
        QTreeView.__init__(self)
        model = QFileSystemModel()
        model.setRootPath('C:\\')
        self.setModel(model)
        self.doubleClicked.connect(self.test)

    def test(self, signal):
        file_path=self.model().filePath(signal)
        print(file_path)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(app.exec_())
Outvote answered 4/6, 2014 at 19:17 Comment(3)
Have you by chance tried this in PyQt5 ? I receive "Attribute Error connect is not an attribute of QObject"Cosimo
I also have problems with PyQt5. Could you provide code for PyQt5 as well?Denicedenie
@Carel, see my answer belowDenicedenie
D
5

In PyQt5 it can be done in this way:

from PyQt5.QtWidgets import QTreeView,QFileSystemModel,QApplication

class Main(QTreeView):
    def __init__(self):
        QTreeView.__init__(self)
        model = QFileSystemModel()
        model.setRootPath('C:\\')
        self.setModel(model)
        self.doubleClicked.connect(self.test)

    def test(self, signal):
        file_path=self.model().filePath(signal)
        print(file_path)


if __name__ == '__main__':
    import sys
    app = QApplication(sys.argv)
    w = Main()
    w.show()
    sys.exit(app.exec_())
Denicedenie answered 22/8, 2015 at 16:7 Comment(2)
Thanks, for the response. Perhaps for others it'd help to mention that connect moved from being an object method to a method acting upon the attribute when PyQt went from 4 to 5. Though I believe the documentation stating this is more prevalent these days.Cosimo
For those who prefer English to Cantonese (@Carel: "from object method to methond acting upon the attribute"): Connect went from a class/static method on QObject to instance method on the signal object.C
T
1

If I understand the question correctly you would like the directory or file name selected.

This is what I do:

from PyQt4 import QtGui
from PyQt4 import QtCore

# ---------------------------------------------------------------------
class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        super().__init__(parent)

        self.resize(600,400)
        self.setWindowTitle("Treeview Example")

        self.treeview = QtGui.QTreeView(self)

        self.treeview.model = QtGui.QFileSystemModel()
        self.treeview.model.setRootPath( QtCore.QDir.currentPath() )
        self.treeview.setModel(self.treeview.model)
        self.treeview.setColumnWidth(0, 200)

        self.setCentralWidget(self.treeview)

        self.treeview.clicked.connect(self.on_treeview_clicked)

# ---------------------------------------------------------------------

    @QtCore.pyqtSlot(QtCore.QModelIndex)
    def on_treeview_clicked(self, index):
        indexItem = self.treeview.model.index(index.row(), 0, index.parent())

        # path or filename selected
        fileName = self.treeview.model.fileName(indexItem)
        # full path/filename selected
        filePath = self.treeview.model.filePath(indexItem)

        print(fileName)
        print(filePath)

# ---------------------------------------------------------------------

if __name__ == '__main__':
    import sys
    app = QtGui.QApplication(sys.argv)
    w = MainWindow()
    w.show()
    sys.exit(app.exec_())
Teresita answered 5/6, 2014 at 13:52 Comment(0)
U
1

I tried this alternative to get the file name...

Instead of:

indexItem = self.treeview.model.index(index.row(), 0, index.parent())

# path or filename selected
fileName = self.treeview.model.fileName(indexItem)

I tried:

# path or filename selected
fileName = index.internalPointer().fileName

Which also seems to work...

Unwarrantable answered 2/1, 2015 at 22:59 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.