2015-07-01 3 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_()) 

И вот то же самое с QTreeView и QStandardItemModel (+ как добавить детей):

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

Отлично, спасибо большое , тморо! Итак, в этом случае, каковы преимущества использования QStandardItemModel вместо QAbstractItemModel? Кроме того, трудно ли утверждать, что класс удобства, такой как QTreeWidget, действует как QStandardItemModel, за исключением того, что QStandardItemModel требует просмотра данных? –

+0

Из документа на 'QTreeWidget':« Разработчики, которым не нужна гибкость структуры Model/View, могут использовать этот класс для простого создания простых иерархических списков. Более гибкий подход предполагает объединение QTreeView со стандартной моделью элементов. позволяет хранить данные от их представления ». – Mel