簡體   English   中英

QHBarModelMapper 和 QAbstractItemModel 行編號

[英]QHBarModelMapper and QAbstractItemModel row numbering

我是 Python 和 Qt 的初學者,這是我在這個論壇上的第一個問題,對我的學習過程有很大幫助。

我將一些分層數據存儲在 QAbstractItemModel 中,它與 QTreeView 配合得很好。 我也成功地使用 QDataWidgetMapper 和 selectionModel.currentChanged 到 map 選定節點的數據到 lineEdit。

對於某些節點,我有 4 列我想將 plot 作為條形圖中的條形。

我制作了一個適用於硬編碼集的 ChartView,但是當我將 QHBarModelMapper 添加到 map 時,將所選行的第 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_())

我意識到 QAbstractItemModel 樹 model 的行號在樹中的每個父級之后重新啟動。 這是否意味着我不能像這樣直接在這個 model 上使用 QHBarModelMapper:

self.bar_mapper.setFirstBarSetRow(current.row()). 

我應該改用什么?

不幸的是,盡管Q{X}ModelMapper類的文檔表明它們支持 QAbstractItemModel 作為 model,但它們只能處理列表或表類型 model 或樹類型 Z20F35E630DAF399D88F 的第一層與 QListView、QDataWidgetMapper 等不同,您可以通過 rootIndex 屬性設置迭代點,但Q{X}ModelMapper

一個可能的解決方案是實現一個代理來提取一個子樹,但在你的特殊情況下,我認為它是不必要的,因為它足以遍歷該行:

def set_selection(self, current, old):
    parent = current.parent()
    self.mapper.setRootIndex(parent)
    self.mapper.setCurrentModelIndex(current)

    model = self.tree_view.model()
    if isinstance(model, CustomTreeModel):
        node = model.getNode(current)
        self.bar_series.clear()
        bar_set = QtCharts.QBarSet(node.name)
        bar_set << node.value1 << node.value2 << node.value3 << node.value4
        self.bar_series.append(bar_set)
        axs = self.bar_chart.axes(Qt.Vertical, self.bar_series)
        if axs:
            axis_y = axs[0]
            axis_y.setMax(max([bar_set.at(i) for i in range(bar_set.count())]) + 10)

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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM