【问题标题】:PySide: TreeView widget for foldersPySide:文件夹的 TreeView 小部件
【发布时间】:2020-03-09 02:45:13
【问题描述】:

我想使用 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 小部件的高度和宽度吗?

【问题讨论】:

    标签: python treeview maya directory-structure qtreewidget


    【解决方案1】:

    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)
    

    它只是遍历一个起始目录,直到找不到任何目录为止。

    【讨论】:

    • 谢谢你这是答案
    • 有没有办法将 QTreeWidget 与 Autodesk Maya 窗口结合起来?
    • 您在最初的问题中没有做到这一点吗?您尝试找到一个 Maya 布局元素并添加一个 QTreeWidget。
    【解决方案2】:

    您需要组织您的数据!在您的上一条评论中,您告诉我您不知道您的数据是什么,当您拥有它时,您可以遍历它并使用“while”或“for”将子节点添加到树中

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

    这部分是你添加孩子的循环:

    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 : QTreeView Display Directory 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)
    

    【讨论】:

    • 我只是在屏幕截图中展示了一个文件夹结构示例,我想说的是我想显示给定路径中指定的所有文件夹内容,例如 Tkinter 示例
    • 我不知道有多少子文件夹,所以我可以显示所选子文件夹中的图像
    • 用while循环组织你的数据,也用它来组织你的数据,一旦你有了你的数据,你就在里面循环并嵌套Qtreewidget。编辑代码,尝试一些东西,然后我们可以通过更正您的代码来帮助您
    • @ITWorld 如果您尝试递归获取任意数量的子文件夹及其内容,您可以使用内置的os.walk收集所有这些数据
    • @GreenCell 你能给我建议一个例子吗?我怎样才能区分父文件夹和子文件夹?
    【解决方案3】:

    您正在混合使用 Maya 和 Qt 小部件,这有什么原因吗?如果父级没有,QtWidgets 会自动创建一个窗口。一个非常好的做法是将小部件子类化,这样您就可以将所有必需的数据保存在一个地方,如下所示:

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

    应该会出现一个窗口。此窗口不会始终位于 Maya 窗口的顶部。如果需要,请导入 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")
    

    【讨论】:

    • 但我的问题是如何用文件夹内容填充树视图?
    • 啊,好吧,只需使用以下命令读取文件夹内容: os.listdir() 并为每个添加项目并搜索子目录或使用 os.walk() 获取层次结构中的所有文件。
    • 因为我想做这样的事情:stackoverflow.com/q/58270255/10591725。但是 Maya 树视图不允许我在其中添加同名的文件夹。这就是我选择使用 PySide 的原因
    • 我想说的是,没有必要使用cmds.window()及其布局,简单使用QT如上所述。
    • 他在混音是因为他不知道 Qt 我想,我是给他这个解决方法来扩展 cmds.treeview 的人:stackoverflow.com/questions/58270255/…
    猜你喜欢
    • 2017-10-31
    • 1970-01-01
    • 1970-01-01
    • 2014-02-17
    • 2013-05-12
    • 1970-01-01
    • 1970-01-01
    • 2016-04-12
    • 2016-10-21
    相关资源
    最近更新 更多