视图/模型/控制器:如何设计分层数据变量

2024-09-28 16:57:37 发布

您现在位置:Python中文网/ 问答频道 /正文

在PyQt4模型视图tutorial中,作者
设计要与链接到QTreeViewNode()一起使用的Node()类:

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变量作为所有顶级项变量的父级:

^{pr2}$

然后他声明了两个顶级项变量A和B:childNodeA0和{}。 对于这两个顶级项目变量,分别声明两个子项目变量 (我重新命名了变量以使其看起来更通用):

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.addChild(childNodeC0)

以下是示意图:

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


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

                |------childNodeC0    

        |------childNodeC0

一切如期而至。但是当这个数据变量被分配给一个“真实”模型时,childNodeC0项变量只显示为Root的子变量,而不是{}的子变量。除此之外,childNodeB0item变量在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_())

Tags: nameselfnodeindexreturnifdefparent
1条回答
网友
1楼 · 发布于 2024-09-28 16:57:37

我认为使用这种数据模型,节点不能有两个不同的父节点。 addChild很混乱,因为看起来你可以做到。 如果您查看场景图模型,它将向Node请求它的父对象(在parent(self, index)中):

parentNode = node.parent()

并且Node.parent()只返回在构造项时定义的父级:

^{pr2}$

如果您希望在两个不同的位置拥有相同的子级,则可能需要复制它或改进数据模型。在

相关问题 更多 >