Python:PyQt QTreeView示例 - 选择

10

我正在使用 Python 2.7 和 Qt Designer,对 MVC 不太熟悉:

我已经在 Qt 中完成了一个 View,用于显示一个目录树列表,并且控制器也已经就绪。我的问题是:

在 QTree view 中选择文件夹后,如何获取该文件夹的路径?

enter image description here

下面是代码片段,我认为是 SIGNAL(..),但我不确定:

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!"
4个回答

17
你要查找的信号是由树状图所拥有的selectionModel发出的selectionChanged。该信号将选定的项目作为第一个参数和取消选定的项目作为第二个参数发出,两者都是QItemSelection的实例。因此,您可能需要更改以下行:
QtCore.QObject.connect(self.ui.treeView, QtCore.SIGNAL('clicked()'), self.test)

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

我建议您使用新的信号和槽样式。将您的test函数重新定义为:

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

这里有一个可工作的例子:

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

在PyQt5中有一点不同(感谢Carel和saldenisov的评论和回答)。

...当PyQt从4转换到5时,connect从对象方法移动到对属性进行操作的方法

所以,现在可以这样使用:

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

现在你写:

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.

这是一个使用PyQt5的示例(由saldenisov提供)。

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_())

1
你是否尝试在PyQt5中运行过这个程序?我收到了“Attribute Error connect is not an attribute of QObject”错误。 - Carel
我在PyQt5方面也遇到了问题。您能提供PyQt5的代码吗? - saldenisov
@Carel,请看下面我的回答。 - saldenisov

5
在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_())

谢谢您的回复。也许对于其他人来说,提到当PyQt从4升级到5时,connect方法已经从对象方法转变为作用于属性的方法可能会有所帮助。我认为这一点在文档中得到了更广泛的说明。 - Carel
对于那些更喜欢英语而不是粤语的人(@Carel:“从对象方法到作用于属性的方法”):Connect 从 QObject 的类/静态方法转变为信号对象上的实例方法。 - Miloslav Raus

1
我是一名有用的助手,可以为您进行文本翻译。以下是需要翻译的内容:

我尝试了这种替代方法来获取文件名...

而不是:

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

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

我尝试过:

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

这似乎也起作用了...


1

如果我理解问题正确,您想选择目录或文件名。

这是我的做法:

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_())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接