2015-01-11 21 views
0

为了保持简单和容易阅读Qt的窗口小部件被省略:型号/ TableView中:行VS列

from PyQt4 import QtCore, QtGui 
class Node(object):  
    def __init__(self, name, parentNode=None):   
     self.name=name 
     self._children=[] 
     self._parentNode=parentNode 
     if parentNode: 
      parentNode._children.append(self) 

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

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

    def __repr__(self): 
     return self.log() 
    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 

class NodeModel(QtCore.QAbstractItemModel):  
    def __init__(self, parent=None): 
     super(NodeModel, self).__init__(parent) 

     self._rootNode = Node("Root") 
     nodeA0 = Node("nodeA0", self._rootNode) 
     nodeA1 = Node("nodeA1", nodeA0) 
     nodeA2 = Node("nodeA2", nodeA1) 

     nodeB0 = Node("nodeB0", self._rootNode) 
     nodeB1 = Node("nodeB1", nodeB0) 
     nodeB2_0 = Node("nodeB2_0", nodeB1) 
     nodeB2_1 = Node("nodeB2_1", nodeB1) 

     print self._rootNode 

    def rowCount(self, parentIndex):  
     if not parentIndex.isValid(): 
      parentNode = self._rootNode 
     else: 
      parentNode = parentIndex.internalPointer() 
     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: 
      if index.column() == 0: 
       return node.name()     

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

    def parent(self, index): 
     node = self.getNode(index) 
     parentNode = node._parentNode 

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

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

    def index(self, row, column, parentIndex): 
     print row, column 
     parentNode = self.getNode(parentIndex) 
     childNode = parentNode.getChildNode(row) 

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

myModel=NodeModel() 

这里是底层数据结构的示图:

|------Root 
    |------nodeA0 
     |------nodeA1 
      |------nodeA2 



    |------nodeB0 
     |------nodeB1 
      |------nodeB2_0 

      |------nodeB2_1 

步骤1

我从查询第1行和第0列的顶级QModelIndex开始:

nodeB0_modelIndex=myModel.index(1, 0, QtCore.QModelIndex()) 

其中1是行号,0是列数和QtCore.QModelIndex()是空QModelIndex(这是我们如何让模型知道,我们要求顶级QModelIndex)。使用QModelIndex.internalPointer()方法我查询数据变量连接到接收QModelIndex

下一页:

nodeB0=nodeB0_modelIndex.internalPointer() 
print 'Confirming: top-level node at row 1 column 0: "%s"'%nodeB0.name 

确认打印,我得到一个“正确”的可变后:

确认:上在第1行第0列的高级节点上:“nodeB0”

步骤2

现在有一个顶级QModelIndex挂“nodeB0”我可以把数据层次传播到nodeB1再到​​和nodeB2_1。再次查询我将使用myModel.index()方法使用三个参数供给它QModelIndex:行号,列号(两个数字是相对于QModelIndex -parent)和QModelIndex -parent本身作为第三个参数:

nodeB1_modelIndex=myModel.index(0, 0, nodeB0_modelIndex) 
nodeB1=nodeB1_modelIndex.internalPointer() 
print 'Confirming: node B at row 0 column 0: "%s"'%nodeB1.name 

nodeB2_0_modelIndex=myModel.index(0, 0, nodeB1_modelIndex) 
nodeB2_0=nodeB2_0_modelIndex.internalPointer() 
print 'Confirming: node B at row 0 column 0: "%s"'%nodeB2_0.name 

nodeB2_1_modelIndex=myModel.index(1, 0, nodeB1_modelIndex) 
nodeB2_1=nodeB2_1_modelIndex.internalPointer() 
print 'Confirming: node B at row 1 column 0: "%s"'%nodeB2_1.name 

到目前为止,我一直只使用行号。因为我是用0 列数字看在self._rootNode定义我的基础数据结构,我可以明白为什么:

该模型的行号最终被用于查询存储在_children列表变量节点实例:

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

其中row参数对应于模型的行和列表变量索引号 - 存储在典型列表变量中的有序数量的元素。

问题:纵观我的基础数据结构,我无法找到实现数字的方法。如何,在哪里以及为什么我应该使用列?

稍后编辑:

当我想到一个想法时,我正在重读自己的问题......如果我的问题的答案是:如果我们打算将节点项垂直放置在QTableView中,并使用Row#0处的零号编号项目以及所有其他项目下降(因此只有一个Column#0正在使用)。如果我们决定水平定位节点项目,我们可以使用列号。这样第一项是最左边的。以下所有项目在右侧彼此相邻放置。然后只使用一个单独的行#0。

使用QTableView我们使用行或列号。不是两者。所以我们设计底层的数据结构变量和相应的模型。我对么?

enter image description here

+1

“我应该如何使用列以及为什么使用列?”我不明白你是如何期望别人回答这个问题而不解释你想要显示的。也许你不应该有任何专栏?也许你有数据要显示在列中。这一切都取决于你想要什么,你还没有告诉我们。没有上下文,几乎不可能猜测出解决方案。此外,这是基本相同的问题[这个](http://stackoverflow.com/questions/27870213/how-internalpointer-method-works),你有没有放弃这个问题? –

+0

列数是树的深度,不是吗? – Trilarion

回答

1

如果我理解正确的话,你必须要在一个表视图,而不是树视图显示一个树模型。 由于在表格视图中显示数据的最简单解决方案是使用二维数组([[]]),因此可以使用QAbstractProxyModel将您的树(如数据模型)转换为二维数组数据模型。 这样,实现rowCount,columnCountdata是非常容易的。