2015-07-01 46 views
1

我在PySide中爲Maya(3D軟件)構建了一個工具,該工具可以自動版本並將文件保存在目錄中。將QTreeView/QAbstractItemModel與QTreeWidget比較

我花了幾天的時間試圖將我的初始QTreeWidget代碼轉換爲模型/視圖模式與QTreeView和QAbstractItemModel以獲得工具提示和其他功能,但我發現它比預期更難。當我正在學習一種新的編碼語言/技術時,我喜歡找到兩個腳本來做同樣的事情 - 一個使用新技術,一個使用舊技術。這樣我可以比較和分解新代碼的功能。

我的一大障礙是,我無法找到一個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() 

回答

3

這是你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_()) 
+0

太好了,謝謝你這麼多,tmoreau!所以在這種情況下,使用QStandardItemModel而不是QAbstractItemModel有什麼優勢?另外,說QTreeWidget這樣的便利類的行爲類似QStandardItemModel,但QStandardItemModel要求視圖才能看到數據,這是否過於簡單化? –

+0

來自'QTreeWidget'的文檔:「不需要Model/View框架靈活性的開發人員可以很容易地使用這個類來創建簡單的分層列表,一種更加靈活的方法是將QTreeView與標準項目模型相結合。允許將數據的存儲從其表示中分離出來。「 – Mel