Python QHBarModelMapper和QBStractItemModel行编号
我是Python和Qt的初学者,这是我在这个论坛上的第一个问题,对我的学习过程有很大帮助 我将一些分层数据存储在QabstracteModel中,它与QTreeView配合良好。我还成功地使用QDataWidgetMapper和selectionModel.currentChanged将选定节点的数据映射到lineEdit 对于某些节点,我有4列要在条形图中绘制为条形图 我制作了一个用于硬编码集的图表视图,但是当我添加一个QHBarModelMapper将所选行的列1-4映射到条形图系列时,我得到了一个空图表Python QHBarModelMapper和QBStractItemModel行编号,python,pyside2,Python,Pyside2,我是Python和Qt的初学者,这是我在这个论坛上的第一个问题,对我的学习过程有很大帮助 我将一些分层数据存储在QabstracteModel中,它与QTreeView配合良好。我还成功地使用QDataWidgetMapper和selectionModel.currentChanged将选定节点的数据映射到lineEdit 对于某些节点,我有4列要在条形图中绘制为条形图 我制作了一个用于硬编码集的图表视图,但是当我添加一个QHBarModelMapper将所选行的列1-4映射到条形图系列时,我得
import sys
from PySide2.QtCore import (QModelIndex, Qt, QObject, QAbstractItemModel)
from PySide2.QtWidgets import (QWidget, QTreeView, QLineEdit, QVBoxLayout, QApplication, QDataWidgetMapper)
from PySide2.QtCharts import QtCharts
class CustomTreeModel(QAbstractItemModel):
def __init__(self, root, parent=None):
super(CustomTreeModel, self).__init__(parent)
self._root_node = root
def rowCount(self, parent):
if not parent.isValid():
parent_node = self._root_node
else:
parent_node = parent.internalPointer()
return parent_node.childCount()
def columnCount(self, parent):
return 5
def data(self, index, role):
if not index.isValid():
return None
node = index.internalPointer()
if role == Qt.DisplayRole or role == Qt.EditRole:
if not isinstance(node, QModelIndex):
if index.column() == 0:
return node.name
if index.column() == 1:
return node.value1
if index.column() == 2:
return node.value2
if index.column() == 3:
return node.value3
if index.column() == 4:
return node.value4
def headerData(self, section, orientation, role):
if role == Qt.DisplayRole:
if section == 0:
return self._root_node.name
if section == 1:
return "value1"
if section == 2:
return "value2"
if section == 3:
return "value3"
if section == 4:
return "value4"
def parent(self, index):
node = self.getNode(index)
parent_node = node.parent
if parent_node == self._root_node:
return QModelIndex()
return self.createIndex(parent_node.row(), 0, parent_node)
def index(self, row, column, parent):
parent_node = self.getNode(parent)
child_item = parent_node.child(row)
if child_item:
return self.createIndex(row, column, child_item)
else:
return QModelIndex()
def getNode(self, index):
if index.isValid():
node = index.internalPointer()
if node:
return node
return self._root_node
class Nodes(QObject):
def __init__(self, name, value1, value2, value3, value4, parent = QModelIndex):
self.parent = parent
self.name = name
self.value1 = value1
self.value2 = value2
self.value3 = value3
self.value4 = value4
self.children = []
def child(self, row):
return self.children[row]
def row(self):
if self.parent is not None:
return self.parent.children.index(self)
def addChild(self, child):
self.children.append(child)
def removeChild(self, position):
if position > 0 or position > len(self.children):
return False
node = self.children.pop(position)
node.parent = None
def childCount(self):
return len(self.children)
class MyWidget(QWidget):
def __init__(self):
QWidget.__init__(self)
self.line_edit = QLineEdit()
self.tree_view = QTreeView()
self.bar_chart = QtCharts.QChart()
self.bar_series = QtCharts.QBarSeries()
self.bar_chart.addSeries(self.bar_series)
categories = ["value 1", "value 2", "value 3", "value 4"]
axis_x = QtCharts.QBarCategoryAxis()
axis_x.append(categories)
self.bar_chart.addAxis(axis_x, Qt.AlignBottom)
self.bar_series.attachAxis(axis_x)
axis_y = QtCharts.QValueAxis()
self.bar_chart.addAxis(axis_y, Qt.AlignLeft)
self.bar_series.attachAxis(axis_y)
self.chart_view = QtCharts.QChartView(self.bar_chart)
self.chart_view.setMinimumSize(640, 480)
self.v_layout = QVBoxLayout(self)
self.v_layout.addWidget(self.line_edit)
self.v_layout.addWidget(self.tree_view)
self.v_layout.addWidget(self.chart_view)
self.mapper = None
self.bar_mapper = None
def set_selection(self, current, old):
parent = current.parent()
self.mapper.setRootIndex(parent)
self.mapper.setCurrentModelIndex(current)
self.bar_mapper.setFirstBarSetRow(current.row())
def set_model(self, model):
self.tree_view.setModel(model)
self.tree_view.selectionModel().currentChanged.connect(self.set_selection)
self.mapper = QDataWidgetMapper()
self.mapper.setModel(model)
self.mapper.addMapping(self.line_edit, 0)
self.bar_mapper = QtCharts.QHBarModelMapper()
self.bar_mapper.setModel(model)
self.bar_mapper.setFirstColumn(1)
self.bar_mapper.setColumnCount(4)
self.bar_mapper.setSeries(self.bar_series)
if __name__ == "__main__":
# Qt Application
app = QApplication(sys.argv)
root_node = Nodes('Data Tree', 0,0,0,0)
node1 = Nodes('node 1', 23, 54, 35 ,35, root_node)
node1_1 = Nodes('node 1.1', 23 , 24 , 25 , 26, node1)
node1_2 = Nodes('node 1.2', 24, 25, 26, 23, node1)
node2 = Nodes('node 2', 26, 27, 22, 24, root_node)
node2_1 = Nodes('node 2.1', 25, 26, 23, 24, node2)
node2_2 = Nodes('node 2.2', 26, 23, 24, 25, node2)
node1.addChild(node1_1)
node1.addChild(node1_2)
node2.addChild(node2_1)
node2.addChild(node2_2)
root_node.addChild(node1)
root_node.addChild(node2)
data_model = CustomTreeModel(root_node)
widget = MyWidget()
widget.set_model(data_model)
widget.show()
sys.exit(app.exec_())
我意识到QabstracteModel树模型的行号在树中的每个父级之后重新启动。这是否意味着我不能直接在此模型上使用QHBarModelMapper,如下所示:
self.bar_mapper.setFirstBarSetRow(current.row()).
我应该用什么来代替 不幸的是,尽管
Q{X}ModelMapper
类的文档表明它们支持作为模型的QabstracteModel,但它们只能处理列表或表类型模型或树类型模型的第一层。与QListView、QDataWidgetMapper等不同,您可以通过rootIndex属性设置迭代点,但Q{X}ModelMapper的情况并非如此
一个可能的解决方案是实现一个代理来提取一个子树,但在您的特殊情况下,我认为它是不必要的,因为它足以遍历该行:
def set_选择(自身、当前、旧):
parent=current.parent()
self.mapper.setRootIndex(父级)
self.mapper.setCurrentModelIndex(当前)
model=self.tree\u view.model()
如果isinstance(型号、CustomTreeModel):
node=model.getNode(当前)
self.bar_series.clear()
bar_set=QtCharts.QBarSet(node.name)
不幸的是,尽管Q{X}ModelMapper
类的文档表明它们支持qabstractemmodel作为模型,但它们只能处理列表或表类型模型或树类型模型的第一层。与QListView、QDataWidgetMapper等不同,您可以通过rootIndex属性设置迭代点,但Q{X}ModelMapper的情况并非如此
一个可能的解决方案是实现一个代理来提取一个子树,但在您的特殊情况下,我认为它是不必要的,因为它足以遍历该行:
def set_选择(自身、当前、旧):
parent=current.parent()
self.mapper.setRootIndex(父级)
self.mapper.setCurrentModelIndex(当前)
model=self.tree\u view.model()
如果isinstance(型号、CustomTreeModel):
node=model.getNode(当前)
self.bar_series.clear()
bar_set=QtCharts.QBarSet(node.name)
bar_set表示感谢,我现在制作了一个可复制的示例。我对您需要什么有点困惑,假设选择了node1,那么它应该显示什么?类似于node1_2。其想法是,所选节点的值1到值4应该可视化为条。有一个示例与此类似,但具有表模型和固定起始列的垂直映射。感谢您,我现在制作了一个可复制的示例。我对您需要什么有点困惑,比如说选择了节点1,那么它应该显示什么?类似于节点1_2。其想法是,所选节点的值1到值4应该可视化为条形图。有一个示例与此类似,但具有表模型和固定起始列的垂直映射。非常感谢!正如我所怀疑的那样,映射程序失败了,因为树模型中的行号与表或列表中的行号不同。Qt文档应该真正提到这一点。我想到的备选方案是代理模型或对行进行迭代。对于这种类型的绘图,我的真实模型在同一级别上始终有两个节点,因此代理模型将只有两行,而您的解决方案将是我真正需要的最佳起点。最后,根据节点在树中的位置,将有不同的绘图。非常感谢!正如我所怀疑的那样,映射程序失败了,因为树模型中的行号与表或列表中的行号不同。Qt文档应该真正提到这一点。我想到的备选方案是代理模型或对行进行迭代。对于这种类型的绘图,我的真实模型在同一级别上始终有两个节点,因此代理模型将只有两行,而您的解决方案将是我真正需要的最佳起点。最后,根据节点在树中的位置,将有不同的图。