将 QTreeView/QAbstractItemModel 与 QTreeWidget 进行比较

Comparing QTreeView/QAbstractItemModel to QTreeWidget

我正在为 Maya(3D 软件)在 PySide 中构建一个工具,该工具可以自动版本化并将文件保存在目录中。

过去几天我一直在尝试将我的初始 QTreeWidget 代码转换为 model/view 模式,其中包含 QTreeView 和 QAbstractItemModel 以获取工具提示和其他功能,但我发现这比预期的要难。当我学习新的编码时 language/technique 我喜欢找到两个脚本做同样的事情 - 一个使用新技术,一个使用旧技术。这样我就可以比较和分解新代码的作用。

我最大的障碍是我无法找到一个 QTreeView 示例来完成我的 QTreeWidget 示例的功能。此外,大多数示例手动填充 QTreeView,这对我也没有太大帮助。如果有人可以修改 QTreeView 代码,使其执行我的 QTreeWidget 代码的操作,那就太好了。对 QTreeView 最佳实践的评论也很棒!

我的 QTreeWidget 代码目前...

1) 从源获取字符串列表并将它们列在第一列

2) 从每个字符串中获取日期并将其放在第二列

QTreeView代码:

from PySide import QtCore, QtGui
from shiboken import wrapInstance
import maya.OpenMayaUI as mui
import sys, os

def get_parent():
    ptr = mui.MQtUtil.mainWindow()
    return wrapInstance( long( ptr ), QtGui.QWidget )   

################################################################################
class MyTree(QtGui.QMainWindow):
    def __init__(self, parent=get_parent() ):
        super(MyTree, self).__init__(parent)

        data = MyData.init()
        frame = QtGui.QFrame();
        frame.setLayout( QtGui.QHBoxLayout() );

        treeViewModel = TreeViewModel(data)
        treeView = Widget_TreeView(treeViewModel)
        frame.layout().addWidget( treeView );

        self.setCentralWidget(frame)

################################################################################
class MyData():
    def __init__(self, txt, parent=None):
        self.txt = txt
        self.tooltip = None
        self.parent = parent
        self.child = []
        self.icon = []
        self.index = None
        self.widget = None

    #---------------------------------------------------------------------------
    # test initialization
    @staticmethod
    def init():
        root = MyData("root")
        root.tooltip = "root tooltip"
        for i in range(0, 2):
            child1 = MyData("child %i" % (i), root)
            child1.tooltip = "child1 tooltip"
            root.child.append(child1)
            for x in range(0, 2):
                child2 = MyData("child %i %i" % (i, x), child1)
                child2.tooltip = "child2 tooltip"
                child1.child.append(child2)
        return root

        # my failed attempt at adding my own data.  
        '''
        path = "C:\Program Files"
        contents = os.listdir( path )
        data_list = []
        for item in contents:
            _data = MyData(item)
            _data.tooltip = "_data tooltip"
            data_list.append(_data)
        return data_list # [0] adding this adds the first item to the UI, 
                         # but i need every item from the directory
        '''

    ################################################################################
class TreeViewModel(QtCore.QAbstractItemModel):
    #---------------------------------------------------------------------------
    def __init__(self, tree):
        super(TreeViewModel, self).__init__()
        self.__tree = tree
        self.__view = None

    #---------------------------------------------------------------------------
    def flags(self, index):
        flag = QtCore.Qt.ItemIsEnabled
        if index.isValid():
            flag |= QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable 
        return flag

    #---------------------------------------------------------------------------
    def index(self, row, column, parent=QtCore.QModelIndex()):
        node = QtCore.QModelIndex()
        if parent.isValid():
            nodeS = parent.internalPointer()
            nodeX = nodeS.child[row]
            node = self.__createIndex(row, column, nodeX)
        else:
            node = self.__createIndex(row, column, self.__tree)
        return node

    #---------------------------------------------------------------------------
    def parent(self, index):
        return QtCore.QModelIndex()
    #---------------------------------------------------------------------------
    def rowCount(self, index=QtCore.QModelIndex()):
        count = 1
        node = index.internalPointer()
        if node is not None:
            count = len(node.child)
        return count

    #---------------------------------------------------------------------------
    def columnCount(self, index=QtCore.QModelIndex()):
        return 2

    #---------------------------------------------------------------------------
    def data(self, index, role=QtCore.Qt.DisplayRole):
        data = None
        return data

    #---------------------------------------------------------------------------
    def setView(self, view):
        self.__view = view

    #---------------------------------------------------------------------------
    def __createIndex(self, row, column, node):
        if node.index == None:
            index = self.createIndex(row, column, node)
            node.index = index
        if node.widget is None:
            node.widget = Widget_Tooltip(node)
            self.__view.setIndexWidget(index, node.widget)
        return node.index

################################################################################
class Widget_TreeView(QtGui.QTreeView):
    #---------------------------------------------------------------------------
    def __init__(self, model, parent=None):
        super(Widget_TreeView, self).__init__(parent)
        self.setModel(model)
        #self.setIndentation(0)
        model.setView(self)
        root = model.index(0,0)

################################################################################
class Widget_Tooltip(QtGui.QWidget):
    #---------------------------------------------------------------------------
    def __init__(self, node):
        super(Widget_Tooltip, self).__init__()

        # Vars
        self.node = node
        self.txt = None
        # Commands
        self.create_tooltip(self.node)

    ############################################
    def create_tooltip(self, node):
        layout = QtGui.QHBoxLayout()
        self.txt = QtGui.QLabel( node.txt)
        self.txt.setToolTip("Text tooltip %s %s" % (node.txt, node.tooltip))
        layout.addWidget(self.txt, 1)
        self.setLayout(layout)

################################################################################
if __name__ == '__main__':
    try:
        form_ui.close()
        form_ui.deleteLater()
    except:
        pass

    form_ui = MyTree()
    form_ui.show()

    try:
        form_ui.show()
    except:
        form_ui.close()
        form_ui.deleteLater()

QTreeWidget 代码:

import sys, os, time
from PySide import QtCore, QtGui
from shiboken import wrapInstance
import maya.OpenMayaUI as mui

def get_parent():
    ptr = mui.MQtUtil.mainWindow()
    return wrapInstance( long( ptr ), QtGui.QWidget )   

class Main_Window(QtGui.QDialog):
    def __init__(self, parent = get_parent()):
        super(Main_Window, self).__init__(parent)



        # Commands
        self.create_gui()
        self.create_layout()
        self.get_contents( None )

    def create_gui( self ):
        self.tw_file_list = File_List( self )
        self.parent = self.tw_file_list.invisibleRootItem()

    def create_layout( self ):
        self.layout = QtGui.QHBoxLayout( self )
        self.layout.addWidget(self.tw_file_list)
        self.setLayout( self.layout )

    def get_contents( self, path ):
        self.tw_file_list.clear()
        path = "C:\Program Files"
        contents = os.listdir( path )

        for item in contents:
            print item
            parent = self.tw_file_list.invisibleRootItem()
            date = self.get_date( item, path)
            self.add_item(item, date, parent)

    def add_item(self, name, date, parent):
        item = QtGui.QTreeWidgetItem(parent)
        item.setText(0, name)
        item.setText(1, date)
        item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled )
        return item

    def get_date( self, item, path):
        path = "C:\Program Files"
        file = str(path + "/" + item)
        date = time.localtime(os.path.getmtime(file))
        clean_date = "{0}_{1}_{2}  {3}:{4}".format( date[0], date[1], date[2], date[3], str(date[4]).zfill(2) )
        return clean_date    

############################################
class File_List( QtGui.QTreeWidget ):
    ''' Create the file filters '''
    def __init__( self, parent=get_parent() ):
        super( File_List, self ).__init__( parent )

        # Setup UI
        self.setColumnCount(2)
        self.setHeaderLabels(["name","date"])
        self.parent = self.invisibleRootItem()

############################################
if __name__ == "__main__":
    # Workaround hack for a PySide bug within maya
    try:
        main_ui.close()
        main_ui.deleteLater()
    except:
        pass

    # Show stuff
    main_ui = Main_Window()
    main_ui.show()

    try:
        main_ui.show()
    except:
        main_ui.close()
        main_ui.deleteLater()

这是您的 QTreeWidget 示例,经过简化:

import sys
from PySide import QtCore, QtGui
class File_List( QtGui.QTreeWidget ):
    def __init__( self, parent=None):
        super( File_List, self ).__init__( parent )
        self.setColumnCount(2)
        self.setHeaderLabels(["name","date"])
        self.get_contents()

    def get_contents( self):
        self.clear()
        contents = ["path1","path2"]
        for path in contents:
            date = self.get_date(path)
            self.add_item(path,date)

    def add_item(self, name, date):
        item = QtGui.QTreeWidgetItem(self)
        item.setText(0, name)
        item.setText(1, date)
        item.setFlags(QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsUserCheckable | QtCore.Qt.ItemIsEnabled )
        return item

    def get_date(self, path):
        return "a date"

if __name__ == "__main__":  
    app = QtGui.QApplication(sys.argv)
    win= File_List()
    win.show() 
    sys.exit(app.exec_())

QTreeViewQStandardItemModel 也是一样的(+ 如何添加 children):

import sys
from PySide import QtCore, QtGui

class MyModel(QtGui.QStandardItemModel):
    def __init__(self, parent=None):
        super(MyModel, self).__init__(parent)
        self.get_contents()

    def get_contents(self):
        self.clear()
        contents=["path1","path2"]
        for path in contents:
            date = self.get_date(path)
            self.add_item(path,date)

    def add_item(self,name,date):
        item1 = QtGui.QStandardItem(name)
        item2 = QtGui.QStandardItem(date)
        self.appendRow([item1, item2])
        #to append child items
        childItem=QtGui.QStandardItem("child")
        item1.appendRow(childItem)

    def get_date(self, path):
        return "a date"


if __name__ == "__main__":  
    app = QtGui.QApplication(sys.argv)
    model=MyModel()
    treeView=QtGui.QTreeView()
    treeView.setModel(model)
    model.setHorizontalHeaderLabels(["name","date"])
    treeView.show()
    sys.exit(app.exec_())