2015-01-08 1 views
0

В PyQt4 Model-View tutorial автор
конструкции Node() класса для использования с QAbstractItemModel связанно с QTreeView:View/модель/контроллер: Как создать иерархическую переменную данные

class Node(object):  
    def __init__(self, name, parent=None):   
     self._name = name 
     self._children=[] 
     self._parent=parent 

     if parent is not None: 
      parent.addChild(self) 

    def typeInfo(self): 
     return "NODE" 

    def addChild(self, child): 
     self._children.append(child) 

    def name(self): 
     return self._name 

    def setName(self, name): 
     self._name = name 

    def child(self, row): 
     return self._children[row] 

    def childCount(self): 
     return len(self._children) 

    def parent(self): 
     return self._parent 

    def row(self): 
     if self._parent is not None: 
      return self._parent._children.index(self) 

Затем он переходит с возможностью объявления сама переменная данных. Сначала он объявляет rootNode переменных для использования в качестве родителя для всех элементов верхнего уровня-переменных:

rootNode = Node("Root") 

Затем он объявляет два верхних уровень детал-переменные А и В: childNodeA0 и childNodeB0. И для каждого из этих двух элементов-переменных верхнего уровень двух дочерних элемент-переменные объявляются (я переименовал переменные, чтобы все выглядело более общим):

childNodeA0 = Node("childNodeA0", rootNode) 
childNodeA1 = Node("childNodeA1", childNodeA0) 
childNodeA2 = Node("childNodeA2", childNodeA1) 

childNodeB0 = Node("childNodeB0", rootNode) 
childNodeB1 = Node("childNodeB1", childNodeB0) 
childNodeB3 = Node("childNodeB3", childNodeB1) 

Вот схематическое представление данных, хранящихся в переменная RootNode:

|------Root 
     |------childNodeA0 
       |------childNodeA1 
         |------childNodeA2 

     |------childNodeB0 
       |------childNodeB1 
         |------childNodeB3 

Теперь я объявляю третий переменный элемент под названием childNodeC0:

childNodeC0 = Node("childNodeC0", rootNode) 

Я передаю rootNode в качестве родителя. Вот это схемный:

|------Root 
     |------childNodeA0 
       |------childNodeA1 
         |------childNodeA2 

     |------childNodeB0 
       |------childNodeB1 
         |------childNodeB3 

     |------childNodeC0 

Теперь, используя метод .addChild() прилагает childNodeC0 переменные как ребенок childNodeB0. Так childNodeC0 является потомком двух переменных: это ребенок rootNode и childNodeB0:

childNodeB0.addChild(childNodeC0) 

Вот это схемные:

Все идет, как ожидалось. Но когда эта переменная данных присваивается «реальной» модели, переменная item childNodeC0 отображается только в виде дочернего элемента Root, а не как дочерний элемент childNodeB0. Кроме того, переменная item childNodeB0 показана в TreeView дважды: как ребенок Root (как и предполагалось). А также показано, как ребенок сам по себе !:

enter image description here

Вопрос:

Как сделать TreeView, чтобы показать данные, хранящийся в корневой переменной должным образом?

from PyQt4 import QtCore, QtGui 
import sys 

class Node(object):  
    def __init__(self, name, parent=None):   
     self._name = name 
     self._children=[] 
     self._parent=parent 

     if parent is not None: 
      parent.addChild(self) 

    def typeInfo(self): 
     return "NODE" 

    def addChild(self, child): 
     self._children.append(child) 

    def name(self): 
     return self._name 

    def setName(self, name): 
     self._name = name 

    def child(self, row): 
     return self._children[row] 

    def childCount(self): 
     return len(self._children) 

    def parent(self): 
     return self._parent 

    def row(self): 
     if self._parent is not None: 
      return self._parent._children.index(self) 

    def log(self, tabLevel=-1): 
     output  = "" 
     tabLevel += 1 

     for i in range(tabLevel): 
      output += "\t" 

     output += "|------" + self._name + "\n" 

     for child in self._children: 
      output += child.log(tabLevel) 

     tabLevel -= 1 
     output += "\n" 

     return output 

    def __repr__(self): 
     return self.log() 

class SceneGraphModel(QtCore.QAbstractItemModel):  
    def __init__(self, root, parent=None): 
     super(SceneGraphModel, self).__init__(parent) 
     self._rootNode = root 

    def rowCount(self, parent):  

     if not parent.isValid(): 
      parentNode = self._rootNode 
     else: 
      parentNode = parent.internalPointer() 
      # print 'VALID: ', type(parent), parent.row(), parent.column() 

     return parentNode.childCount() 

    def columnCount(self, parent): 
     return 1 

    def data(self, index, role):  
     if not index.isValid(): 
      return None 

     node = index.internalPointer() 

     if role == QtCore.Qt.DisplayRole or role == QtCore.Qt.EditRole: 
      if index.column() == 0: 
       return node.name()    

    def setData(self, index, value, role=QtCore.Qt.EditRole): 
     if index.isValid():    
      if role == QtCore.Qt.EditRole:     
       node = index.internalPointer() 
       node.setName(value)     
       return True 
     return False  

    def headerData(self, section, orientation, role): 
     if role == QtCore.Qt.DisplayRole: 
      if section == 0: 
       return "Column #0"   

    def flags(self, index):   
     return QtCore.Qt.ItemIsEnabled | QtCore.Qt.ItemIsSelectable | QtCore.Qt.ItemIsEditable  

    def parent(self, index): 

     node = self.getNode(index) 
     parentNode = node.parent() 

     if parentNode == self._rootNode: 
      return QtCore.QModelIndex() 

     return self.createIndex(parentNode.row(), 0, parentNode)   

    def index(self, row, column, parent): 

     parentNode = self.getNode(parent) 
     childItem = parentNode.child(row) 

     if childItem: 
      return self.createIndex(row, column, childItem) 
     else: 
      return QtCore.QModelIndex() 

    def getNode(self, index):  
     if index.isValid(): 
      node = index.internalPointer() 
      if node: 
       return node    
     return self._rootNode  








if __name__ == '__main__': 
    app = QtGui.QApplication(sys.argv) 

    rootNode = Node("Root") 
    childNodeA0 = Node("childNodeA0", rootNode) 
    childNodeA1 = Node("childNodeA1", childNodeA0) 
    childNodeA2 = Node("childNodeA2", childNodeA1) 

    childNodeB0 = Node("childNodeB0", rootNode) 
    childNodeB1 = Node("childNodeB1", childNodeB0) 
    childNodeB3 = Node("childNodeB3", childNodeB1) 

    childNodeC0 = Node("childNodeC0", rootNode) 
    childNodeB0.addChild(childNodeC0)  

    treeView=QtGui.QTreeView()  

    model = SceneGraphModel(rootNode) 
    treeView.setModel(model) 
    treeView.show() 

    print rootNode 

    sys.exit(app.exec_()) 

ответ

2

Я думаю, что с этой моделью данных у вас не может быть узла с двумя разными родителями. addChild сбивает с толку, потому что кажется, что вы можете это сделать. Если вы посмотрите в модели графа сцены, она будет просить Node для его родителей (в parent(self, index)):

parentNode = node.parent() 

и Node.parent() возвращает только родительский определенный при строительстве пункта:

return self._parent 

Если вы хотите иметь одного и того же ребенка в двух разных местах, вы можете его скопировать или улучшить модель данных.

 Смежные вопросы

  • Нет связанных вопросов^_^