PySide:文件夹的 TreeView 小部件

PySide: TreeView widget for folders

我想使用 PySide for Autodesk Maya 创建一个 TreeView 小部件,它可以显示目录的内容,如下例所示:

我确实找到了一个使用 tkinter 的简单 python 脚本示例: Tkinter: Treeview widget。但我想使用 Pyside,这样我就可以 运行 在 Autodesk Maya 中使用它

我确实创建了一个可以显示简单 TreeView 小部件的脚本:

这是我的代码:

try:
  from PySide2.QtCore import * 
  from PySide2.QtGui import * 
  from PySide2.QtWidgets import *
  from PySide2 import __version__
  from shiboken2 import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI
except ImportError:
  from PySide.QtCore import * 
  from PySide.QtGui import * 
  from PySide import __version__
  from shiboken import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI

treepop = collections.defaultdict(list)
treepop[""]=['layer_1',
             'layer_2',
             'layer_3',
             'layer_4',
             'layer_5',
             'layer_6',
             'layer_12']
treepop["layer_2"] = ['layer_7',
                        'layer_9',
                        'layer_11']
treepop["layer_3"] = ['layer_7']
treepop["layer_8"] = ['layer_10']
treepop["layer_10"] = ['layer_13']

def mayaToQT(name):
    # Maya -> QWidget
    ptr = OpenMayaUI.MQtUtil.findControl(name)
    if ptr is None:         ptr = OpenMayaUI.MQtUtil.findLayout(name)
    if ptr is None:         ptr = OpenMayaUI.MQtUtil.findMenuItem(name)
    if ptr is not None:     return wrapInstance(long(ptr),
                                                          QWidget)


cmds.window()
layout = cmds.columnLayout(rowSpacing=10, columnWidth=250)
qwidget= mayaToQT(layout)
qlayout = qwidget.children()[0]
treeview = QTreeWidget()
treeview.setSelectionMode(QAbstractItemView.ExtendedSelection)
treeview.setColumnCount(1)
treeview.setAlternatingRowColors(True)
treeview.clear()
qlayout.addWidget(treeview)

items = []
for k in treepop[""]:
    root_item = QTreeWidgetItem()
    root_item.setText(0,k)
    print(k)

    if k in treepop:
        for v in treepop[k]:
            child_item = QTreeWidgetItem()
            child_item.setText(0,v)
            root_item.addChild(child_item)

    items.append(root_item)
treeview.addTopLevelItems(items)

cmds.showWindow()

def getSelected():
    items = treeview.selectedItems()
    for i in items:
        print(i.text(0))

谁能帮帮我!

编辑: 在大家的帮助下我确实解决了问题,谢谢大家:

try:
  from PySide2.QtCore import * 
  from PySide2.QtGui import * 
  from PySide2.QtWidgets import *
  from PySide2 import __version__
  from shiboken2 import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI
  import os
except ImportError:
  from PySide.QtCore import * 
  from PySide.QtGui import * 
  from PySide import __version__
  from shiboken import wrapInstance 
  import collections
  import maya.OpenMayaUI as OpenMayaUI
  import os
class MyTree(QTreeWidget):
    def __init__(self, parent=None):
        QTreeWidget.__init__(self, parent)        
        self.startDir = "C:/users/user/desktop/myFolder"
        self.setHeaderLabels([self.startDir])
        self.setColumnWidth(0,400)
        self.setContentsMargins(0, 0, 0, 0)
        self.header().setDefaultSectionSize(300)
        self.header().setStretchLastSection(False)
        self.header().setResizeMode(0, QHeaderView.ResizeToContents)
        self.header().setResizeMode(0, QHeaderView.Stretch)
        self.setSelectionMode(QAbstractItemView.ExtendedSelection)
        self.setColumnCount(1)
        self.setAlternatingRowColors(True)
        self.fillTree()
        self.show()


    def fillTree(self):                
        def iterate(currentDir, currentItem):            
            for f in os.listdir(currentDir):

                path = os.path.join(currentDir, f)
                if os.path.isdir(path):

                    dirItem = QTreeWidgetItem(currentItem)
                    dirItem.setText(0, f)
                    iterate(path, dirItem)
        iterate(self.startDir, self)



def mayaToQT(name):
    # Maya -> QWidget
    ptr = OpenMayaUI.MQtUtil.findControl(name)
    if ptr is None:         ptr = OpenMayaUI.MQtUtil.findLayout(name)
    if ptr is None:         ptr = OpenMayaUI.MQtUtil.findMenuItem(name)
    if ptr is not None:     return wrapInstance(long(ptr),QWidget)


cmds.window(w=600, h=300)
layout = cmds.columnLayout(rowSpacing=60, columnWidth=400, w=600, h=600)
qwidget= mayaToQT(layout)
qlayout = qwidget.children()[0]
treeview = MyTree()

qlayout.addWidget(treeview)
cmds.showWindow()

但是谁能帮忙设置 QTreeView 小部件的高度和宽度?

您正在混合使用 Maya 和 Qt 小部件,这有什么原因吗?如果父项是 none,QtWidgets 会自动创建一个 window。一个很好的做法是子类化一个小部件,它使您能够将所有必要的数据保存在一个地方,如下所示:

class MyTree(QtWidgets.QTreeWidget):
    def __init__(self, parent=None):
        super(MyTree, self).__init__(parent)
        self.fillTree()

    def fillTree(self):
        self.clear()
        for i in range(10):
            item = QtWidgets.QTreeWidgetItem(self)
            item.setText(0, str(i))

如果你在init方法中的self.fillTree()之后添加self.show()或者从maya中调用它,你就可以自动显示它:

mt = MyTree()
mt.show()

应该出现 window。这个 window 不会总是在 Maya window 之上。如果需要,请导入 mayaMixin 并从 mixin 继承:

import maya.app.general.mayaMixin as MayaMixin

class MyTree(MayaMixin.MayaQWidgetBaseMixin, QtWidgets.QTreeWidget):
    .....

接下来您可以开始用正确的数据填充树并添加子项。可以通过使用当前项作为父项来简单地添加子项:

item = QtWidgets.QTreeWidgetItem(self)
item.setText(0, "parent")
subItem = QtWidgets.QTreeWidgetItem(item)
subItem.setText(0, "child")

您需要整理数据!在你最后的评论中,你告诉我你不知道你的数据是什么,当你拥有它时,你可以循环遍历它并使用 'while' 或 'for' 将 child 添加到树中

my_data_folders = {'parent1': {'Lips':['A', 'B', 'C']}}

下面这部分是你要添加的循环 children :

items = []
for k in treepop:
    # this is "parent1"
    root_item = QTreeWidgetItem()
    root_item.setText(0,k)

    if treepop[k]:
        # if there is children to "parent1", add Lips children to parent1
        for v in treepop[k]:
            child_item = QTreeWidgetItem()
            child_item.setText(0,v)
            root_item.addChild(child_item)
        if treepop[k][v]:
            for sub in treepop[k][v]:

                sub_item = QTreeWidgetItem()
                sub_item.setText(0, sub)
                child_item.addChild(sub_item)

    items.append(root_item)
treeview.addTopLevelItems(items)

一切皆有可能,最复杂的事情是组织数据

请注意,如果您正在尝试制作资源管理器,则 Qt 中有 QDirModel 的东西: https://doc.qt.io/qtforpython/PySide2/QtWidgets/QDirModel.html

model = QtWidgets.QDirModel()
model.setReadOnly(True);
model.setSorting(QtCore.QDir.DirsFirst|QtCore.QDir.IgnoreCase|QtCore.QDir.Name)
model.setFilter(QtCore.QDir.Dirs)

treeView.setModel(model)

QDirModel 很棒。万一你想要另一个解决方案,你可以试试这个:

class MyTree(QtWidgets.QTreeWidget):
    def __init__(self, parent=None):
        super(MyTree, self).__init__(parent=parent)
        self.startDir = "C:/daten/backup"
        self.fillTree()
        self.show()

    def fillTree(self):        
        def iterate(currentDir, currentItem):            
            for f in os.listdir(currentDir):
                path = os.path.join(currentDir, f)
                if os.path.isdir(path):
                    dirItem = QtWidgets.QTreeWidgetItem(currentItem)
                    dirItem.setText(0, f)
                    iterate(path, dirItem)
                else:
                    fileItem = QtWidgets.QTreeWidgetItem(currentItem)
                    fileItem.setText(0, f)
        iterate(self.startDir, self)

它只是遍历起始目录,直到不再找到任何目录。