【问题标题】:How to use the VXYModelMapper with QStandardItemModel?如何将 VXYModelMapper 与 QStandardItemModel 一起使用?
【发布时间】:2021-06-10 20:03:51
【问题描述】:

我想为基于 C++ 模型的 QML ChartView 添加线条和点。

在 QML 中我做了以下事情:

ChartView {
    id: chart

    DateTimeAxis {
        id: axisX
        format: "HH:mm:ss"
        min: new Date()
    }

    ValueAxis {
        id: axisY
        min: 0
        max: 200
    }

    VXYModelMapper {
        id: modelMapper
        model: lineModel // QStandardModel in C++
        series: line
        firstRow: 1
        xColumn: 1 
        yColumn: 2
    }
}

在 C++ 中,我做了以下事情:

lineModel = new QStandardItemModel;
static const QHash< int, QByteArray > lineRoles {
    { 0, "id" },
    { 100, "x" },
    { 101, "y" }
};
lineModel->setItemRoleNames( lineRoles );

QStandardItem *line = new QStandardItem("Temp");
lineModel->appendRow(line);
line->setData(100, 10);
line->setData(101, 50);

重点永远不会出现。是不是因为ChartView的xColumn和yColumn不对?还是我在模型中添加点错误?

【问题讨论】:

    标签: c++ qt charts qml


    【解决方案1】:

    VXYModelMapper 要求模型有几列,例如,在您的情况下,您设置属性 xColumn: 1 表示它是第二列,yColumn: 2 是第三列,但您的模型只有一列(模型中的索引从 0 开始。)。

    一个例子:

    ma​​in.cpp

    #include <QApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include <QStandardItemModel>
    #include <QDateTime>
    
    int main(int argc, char *argv[])
    {
    #if defined(Q_OS_WIN)
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    #endif
    
        QApplication app(argc, argv);
    
        QStandardItemModel lineModel(100, 3);// 100 rows and 3 columns
    
        for (int row = 0; row < lineModel.rowCount(); row++) {
            QStandardItem *item1 = new QStandardItem(QString::number(row));
            QDateTime time = QDateTime::currentDateTime().addSecs(row);
            QStandardItem *item2 = new QStandardItem(QString::number(time.toMSecsSinceEpoch()));
            QStandardItem *item3 = new QStandardItem(QString::number(row*row));
            lineModel.setItem(row, 0, item1);
            lineModel.setItem(row, 1, item2);
            lineModel.setItem(row, 2, item3);
        }
    
        QQmlApplicationEngine engine;
        engine.rootContext()->setContextProperty("lineModel", &lineModel);
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    

    ma​​in.qml

    import QtQuick 2.9
    import QtQuick.Window 2.2
    import QtCharts 2.2
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Hello World")
    
        ChartView {
            anchors.fill: parent
            id: chart
    
            DateTimeAxis {
                id: axisX
                format: "HH:mm:ss"
            }
    
            ValueAxis {
                id: axisY
                min: 0
                max: 10000
            }
    
            LineSeries{
                id: line
                axisX: axisX
                axisY: axisY
            }
    
            VXYModelMapper {
                id: modelMapper
                model: lineModel // QStandardModel in C++
                series: line
                firstRow: 1
                xColumn: 1
                yColumn: 2
            }
        }
    }
    

    您可以在以下链接中找到完整的example


    PySide2:

    import os
    import sys
    from PySide2 import QtCore, QtGui, QtWidgets, QtQml
    
    if __name__ == '__main__':
        app = QtWidgets.QApplication(sys.argv)
        lineModel = QtGui.QStandardItemModel(100, 3)
    
        for row in range(lineModel.rowCount()):
            item1 = QtGui.QStandardItem()
            item1.setData(row, QtCore.Qt.DisplayRole)
            time = QtCore.QDateTime.currentDateTime().addSecs(row)
            item2 = QtGui.QStandardItem()
            item2.setData(time.toMSecsSinceEpoch(), QtCore.Qt.DisplayRole)
            item3 = QtGui.QStandardItem()
            item3.setData(row**2, QtCore.Qt.DisplayRole)
            lineModel.setItem(row, 0, item1)
            lineModel.setItem(row, 1, item2)
            lineModel.setItem(row, 2, item3)
    
        engine = QtQml.QQmlApplicationEngine() ;
        engine.rootContext().setContextProperty("lineModel", lineModel);
        engine.load(QtCore.QUrl.fromLocalFile(os.path.join(os.path.dirname(__file__), "main.qml")))
        if not engine.rootObjects():
            sye.exit(-1)
        sys.exit(app.exec_())
    

    【讨论】:

    • 这是否意味着每条生产线都需要一个新模型?
    • 每一列可以是一行,也可以创建多个模型,随心所欲。
    • @eyllanesc:转换成字符串new QStandardItem(QString::number(row*row));有必要吗?
    • @tauran 不,但如果你意识到它与根本问题无关:-)
    • @tauran 这不是直接的错误,因为文档:doc.qt.io/qtforpython/PySide2/QtGui/… 没有表明这种行为,而是有一个限制,无论如何我已经在 PySide2 中添加了适当的方法。以上是针对 PySide2 的,但说到 C++ 也不是低效的,因为转换并不繁重,而且如果你从 C++ 发送数据,QML 中总会有数据转换。
    最近更新 更多