Model/TableView:行与列
Model/TableView: Rows vs Columns
为了简单易读,此处省略了 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 列查询 top-level QModelIndex
:
nodeB0_modelIndex=myModel.index(1, 0, QtCore.QModelIndex())
其中 1
是行号,0
是列号,QtCore.QModelIndex()
是空的 QModelIndex(这就是我们让模型知道我们请求 top-level QModelIndex
).
接下来使用 QModelIndex
.internalPointer()
方法我查询链接到接收到的 QModelIndex
:
的 data-variable
nodeB0=nodeB0_modelIndex.internalPointer()
print 'Confirming: top-level node at row 1 column 0: "%s"'%nodeB0.name
确认打印我得到一个 "correct" 变量:
Confirming: top-level node at row 1 column 0: "nodeB0"
步骤 2
现在有一个 top-level QModelIndex
链接到 "nodeB0" 我可以向下传播数据层次结构到 nodeB1
然后到 nodeB2_0
和 nodeB2_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
列表变量中的 Node-instance:
def getChildNode(self, row):
return self._children[row]
其中 row
参数对应于模型的行和列表变量索引号 - 存储在典型列表变量中的有序元素数。
问题:查看我的底层数据结构,我找不到实现 Column 数字的方法。我应该如何、在何处以及为何使用 Columns?
稍后编辑:
当我想到一个想法时,我正在重读我自己的问题......如果我的问题的答案是:当我们打算将 node-items 垂直放置在 QTableView 中时,我们使用行号,其中零第 0 行的编号项目和所有其他项目都在下降(因此只有单个第 0 列在使用中)。如果我们决定水平放置 node-items,我们将使用列号代替。这样第一项就在最左边。并且以下所有项目都放在右侧并排放置。然后只使用一个 Row # 0。
对于 QTableView,我们使用行号或列号。不是两者。因此,我们设计了底层数据结构变量和相应地处理它的模型。我说得对吗?
如果我没理解错的话,您有一个树模型要显示在 table 视图中而不是树视图中。
由于在 table 视图中显示数据的最简单解决方案是使用二维数组 ([[]]
),您可以使用 QAbstractProxyModel 将树状数据模型转换为二维数组数据模型。
这样,实现rowCount
、columnCount
、data
就很容易了。
为了简单易读,此处省略了 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 列查询 top-level QModelIndex
:
nodeB0_modelIndex=myModel.index(1, 0, QtCore.QModelIndex())
其中 1
是行号,0
是列号,QtCore.QModelIndex()
是空的 QModelIndex(这就是我们让模型知道我们请求 top-level QModelIndex
).
接下来使用 QModelIndex
.internalPointer()
方法我查询链接到接收到的 QModelIndex
:
nodeB0=nodeB0_modelIndex.internalPointer()
print 'Confirming: top-level node at row 1 column 0: "%s"'%nodeB0.name
确认打印我得到一个 "correct" 变量:
Confirming: top-level node at row 1 column 0: "nodeB0"
步骤 2
现在有一个 top-level QModelIndex
链接到 "nodeB0" 我可以向下传播数据层次结构到 nodeB1
然后到 nodeB2_0
和 nodeB2_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
列表变量中的 Node-instance:
def getChildNode(self, row):
return self._children[row]
其中 row
参数对应于模型的行和列表变量索引号 - 存储在典型列表变量中的有序元素数。
问题:查看我的底层数据结构,我找不到实现 Column 数字的方法。我应该如何、在何处以及为何使用 Columns?
稍后编辑:
当我想到一个想法时,我正在重读我自己的问题......如果我的问题的答案是:当我们打算将 node-items 垂直放置在 QTableView 中时,我们使用行号,其中零第 0 行的编号项目和所有其他项目都在下降(因此只有单个第 0 列在使用中)。如果我们决定水平放置 node-items,我们将使用列号代替。这样第一项就在最左边。并且以下所有项目都放在右侧并排放置。然后只使用一个 Row # 0。
对于 QTableView,我们使用行号或列号。不是两者。因此,我们设计了底层数据结构变量和相应地处理它的模型。我说得对吗?
如果我没理解错的话,您有一个树模型要显示在 table 视图中而不是树视图中。
由于在 table 视图中显示数据的最简单解决方案是使用二维数组 ([[]]
),您可以使用 QAbstractProxyModel 将树状数据模型转换为二维数组数据模型。
这样,实现rowCount
、columnCount
、data
就很容易了。