【问题标题】:Comparing QTreeView/QAbstractItemModel to QTreeWidget将 QTreeView/QAbstractItemModel 与 QTreeWidget 进行比较
【发布时间】:2015-07-01 16:49:46
【问题描述】:

我正在 PySide for Maya(3D 软件)中构建一个工具,用于自动版本并将文件保存在目录中。

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

我的最大障碍是我无法找到与我的 QTreeWidget 示例相同的 QTreeView 示例。此外,大多数示例手动填充 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()

【问题讨论】:

    标签: python pyside qtreeview qtreewidget qabstractitemmodel


    【解决方案1】:

    这是您的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 也是一样的(+ 如何添加孩子):

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

    【讨论】:

    • 太好了,非常感谢,tmoreau!那么在这种情况下,使用 QStandardItemModel 代替 QAbstractItemModel 有什么好处呢?另外,说像 QTreeWidget 这样的便利类的行为类似于 QStandardItemModel 是不是过于简单化了,除了 QStandardItemModel 需要一个视图来查看数据?
    • 来自QTreeWidget 上的文档:“不需要模型/视图框架灵活性的开发人员可以使用此类非常轻松地创建简单的分层列表。更灵活的方法涉及组合 QTreeView使用标准项目模型。这允许将数据的存储与其表示分离。"
    猜你喜欢
    • 2011-09-29
    • 2016-07-20
    • 2015-03-06
    • 1970-01-01
    • 2015-05-31
    • 2013-05-04
    • 2021-04-24
    • 2019-11-28
    • 2020-12-30
    相关资源
    最近更新 更多