【问题标题】:QTreeView with drag and drop support in PyQt在 PyQt 中支持拖放的 QTreeView
【发布时间】:2011-05-09 00:04:42
【问题描述】:

在 PyQt 4 中,我想创建一个 QTreeView,可以通过拖放操作重新组织其结构。

我已经为 QTreeView 实现了自己的模型(QAbstractItemModel),因此我的 QTreeView 可以正确显示数据。 现在我想添加对树节点的拖放支持,以便能够将树内的节点从一个父节点移动到另一个父节点、拖放复制等,但我找不到任何完整的教程来实现这一点。我找到了一些关于 QTreeWidget 的教程和提示,但没有找到带有自定义模型的 QTreeView。 有人能指点我在哪里看吗?

谢谢。

【问题讨论】:

    标签: python drag-and-drop pyqt qtreeview


    【解决方案1】:

    您可以通过将 QtGui.QAbstractItemView.InternalMove 设置为树视图控件的 dragDropMode 属性来启用对树视图项的拖放支持。另请查看Using drag & drop with item views 此处的文档。下面是一个为其项目启用内部拖放的树视图的小示例。

    import sys
    from PyQt4 import QtGui, QtCore
    
    class MainForm(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MainForm, self).__init__(parent)
    
            self.model = QtGui.QStandardItemModel()
    
            for k in range(0, 4):
                parentItem = self.model.invisibleRootItem()
                for i in range(0, 4):
                    item = QtGui.QStandardItem(QtCore.QString("item %0 %1").arg(k).arg(i))
                    parentItem.appendRow(item)
                    parentItem = item
    
            self.view = QtGui.QTreeView()
            self.view.setModel(self.model)
            self.view.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
    
            self.setCentralWidget(self.view)
    
    def main():
        app = QtGui.QApplication(sys.argv)
        form = MainForm()
        form.show()
        app.exec_()
    
    if __name__ == '__main__':
        main()
    

    Edit0:树视图+抽象模型,支持拖放

    import sys
    from PyQt4 import QtGui, QtCore
    
    class TreeModel(QtCore.QAbstractItemModel):
        def __init__(self):
            QtCore.QAbstractItemModel.__init__(self)
            self.nodes = ['node0', 'node1', 'node2']
    
        def index(self, row, column, parent):
            return self.createIndex(row, column, self.nodes[row])
    
        def parent(self, index):
            return QtCore.QModelIndex()
    
        def rowCount(self, index):
            if index.internalPointer() in self.nodes:
                return 0
            return len(self.nodes)
    
        def columnCount(self, index):
            return 1
    
        def data(self, index, role):
            if role == 0: 
                return index.internalPointer()
            else:
                return None
    
        def supportedDropActions(self): 
            return QtCore.Qt.CopyAction | QtCore.Qt.MoveAction         
    
        def flags(self, index):
            if not index.isValid():
                return QtCore.Qt.ItemIsEnabled
            return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | \
                   QtCore.Qt.ItemIsDragEnabled | QtCore.Qt.ItemIsDropEnabled        
    
        def mimeTypes(self):
            return ['text/xml']
    
        def mimeData(self, indexes):
            mimedata = QtCore.QMimeData()
            mimedata.setData('text/xml', 'mimeData')
            return mimedata
    
        def dropMimeData(self, data, action, row, column, parent):
            print 'dropMimeData %s %s %s %s' % (data.data('text/xml'), action, row, parent) 
            return True
    
    
    class MainForm(QtGui.QMainWindow):
        def __init__(self, parent=None):
            super(MainForm, self).__init__(parent)
    
            self.treeModel = TreeModel()
    
            self.view = QtGui.QTreeView()
            self.view.setModel(self.treeModel)
            self.view.setDragDropMode(QtGui.QAbstractItemView.InternalMove)
    
            self.setCentralWidget(self.view)
    
    def main():
        app = QtGui.QApplication(sys.argv)
        form = MainForm()
        form.show()
        app.exec_()
    
    if __name__ == '__main__':
        main()
    

    希望这会有所帮助,问候

    【讨论】:

    • 感谢您的回答。但这并不能解决我的问题。我知道使用 QStandardItemModel + QStandardItem 可以按预期工作。但我需要使用自定义模型(QAbstractItemModel 的纯子类)使其工作。我想我需要在模型中实现一些方法或为树项使用一些专门的对象。现在即使设置为显示,拖动也不会显示下降指示器......显然我只是错过了一些东西。
    • 我还有一条评论。如果以 PyQt 标准示例中的“simpletreemodel”为例:如何为其添加拖放支持?如果我只是添加 setAcceptsDrop(True)、setDragEnabled(True)、setDragDropMode(view.InternalMove) 来查看和标记 ItemIsDragEnabled | ItemIsDropEnabled 来建模,仅仅有拖放功能是不够的。
    • 从未见过任何标准示例;但请记住,QT 是开源的,因此您可以随时查看 QStandardItemModel 内部发生的情况,它是 QAbstractItemModel 的后代并支持拖放。我用简单的抽象模型示例编辑了我的帖子,它应该支持拖放。
    • 是的,现在可以使用了!你不知道我有多想感谢你。真的很感谢。
    • 我发现python3内部的PyQt中不存在QString。我读了这篇文章为我解决了这个问题:inputvalidation.blogspot.com/2010/10/…
    猜你喜欢
    • 2012-01-14
    • 1970-01-01
    • 1970-01-01
    • 2016-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-20
    • 2015-03-06
    相关资源
    最近更新 更多