模型/表格视图:行与列

Posted

技术标签:

【中文标题】模型/表格视图:行与列【英文标题】:Model/TableView: Rows vs Columns 【发布时间】:2015-01-11 02:06:09 【问题描述】:

为了简单易读,这里省略了 Qt 小部件:

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_0nodeB2_1。再次查询QModelIndex 我将使用myModel.index() 方法为其提供三个参数:行号、列号(这两个数字都相对于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 参数对应于模型的行和列表变量索引号 - 存储在典型列表变量中的元素的有序数量。

问题:查看我的底层数据结构,我找不到实现 数字的方法。我应该如何、在哪里以及为什么要使用 Columns?

稍后编辑:

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

在 QTableView 中,我们使用行号或列号。不是两者。因此,我们设计了底层数据结构变量和相应的处理它的模型。我说的对吗?

【问题讨论】:

“我应该如何、在哪里以及为什么要使用 Columns?”我不明白你如何期望有人在不解释你想要显示的内容的情况下回答这个问题。也许你不应该有任何列?也许您确实有要在列中显示的数据。这一切都取决于你想要什么,你还没有告诉我们。没有上下文,几乎不可能猜测出解决方案。还有,这和this基本是同一个问题吗,你放弃这个问题了吗? 列数就是树的深度不是吗? 【参考方案1】:

如果我理解正确,您有一个树模型,您想在表格视图而不是树视图中显示。 由于在表格视图中显示数据的最简单解决方案是使用 2D 数组 ([[]]),因此您可以使用 QAbstractProxyModel 将树状数据模型转换为 2D 数组数据模型。 这样,实现rowCountcolumnCountdata就很容易了。

【讨论】:

以上是关于模型/表格视图:行与列的主要内容,如果未能解决你的问题,请参考以下文章

SQL:将行与列中的逗号分隔值合并

07版本的excel阅读模式在哪

HTML中做的表格为什么填充 间距 边框 三个都设置为0了,表格内部行与列之间还是有空隙。

MySQL——视图

MySQL学习随笔--视图

非关系型数据库——HBase