簡體   English   中英

將數據從c ++加載到QML Scatter3d項

[英]Load data from c++ to a QML Scatter3d Item

我正在嘗試開發示例“ qmlscatter”的修改版本,可在Qt示例中使用。 我的意圖是通過修改“ Data.qml”文件的數據點來繪制3D環境中的飛行軌跡。 飛行路線的實際坐標存儲在三個不同的QVectors QVector<double> “ cogPosX _”,“ cogPosY_”和“ cogPosZ_”中,每個索引代表下一個時間步長。

正如論壇所提到的,我需要使用“ .setContextProperty”函數來更新QML文件中的數據值。 但是,我找不到真正的解決方法。 我想主要原因是我沒有引用正確的“ dataModel” ID。 這里有我的代碼:

datapointobject.h //應該定義一個通用對象,其中包含每個數據點的XY和Z坐標。

#ifndef DATAPOINTOBJECT_H
#define DATAPOINTOBJECT_H
#include <QWidget>
class DataObject : public QObject
{
    Q_OBJECT

    Q_PROPERTY(double x READ x WRITE setX)
    Q_PROPERTY(double y READ y WRITE setY)
    Q_PROPERTY(double z READ z WRITE setZ)
public:
    DataObject(QObject* parent =0);//Constructor
    DataObject(const double & x, const double & y, const double & z, QObject * parent=0);
    ~DataObject();//Destructor
    double x() const;
    double y() const;
    double z() const;
    void setX(const double &x);
    void setY(const double &y);
    void setZ(const double &z);
signals:

    void xChanged();
    void yChanged();
    void zChanged();
private:
    double m_x;
    double m_y;
    double m_z;
};
#endif // DATAPOINTOBJECT_H

datapointobject.cpp //這定義了構造函數和函數。

#include "datapointobject.h"
#include<QDebug>

DataObject::DataObject(QObject *parent)//Constructor
    : QObject(parent)
{
}
DataObject::DataObject(const double &x, const double &y, const double &z, QObject *parent)//Constructor
    :QObject(parent), m_x(x), m_y(y), m_z(z)
{

}

DataObject::~DataObject(){//Destructor

}
double DataObject::x() const
{
    return m_x;
}
double DataObject::y() const
{
    return m_y;
}
double DataObject::z() const
{
    return m_z;
}
void DataObject::setX(const double &x){
    if (x != m_x) {
        m_x = x;
        emit xChanged();
    }
}
void DataObject::setY(const double &y){
    if (y != m_y) {
        m_y = y;
        emit yChanged();
    }
}
void DataObject::setZ(const double &z){
    if (z != m_z) {
        m_z = z;
        emit zChanged();
    }
}

threeDviewer.h //此標頭定義“ Flightviewer”類,該類創建一個QQuickView實例,負責繪制3D Scatter。

#ifndef FLIGHTVIEWER_H
#define FLIGHTVIEWER_H
#include <QtWidgets>
#include <QtGui/QGuiApplication>
#include <QtCore/QDir>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlEngine>
#include "flight.h"
#include <QtQml>

class Flightviewer: public QWidget
{
  Q_OBJECT

public:
  Flightviewer(Flight displayedFlight, QString directory, QWidget *parent = 0);//Constructor
  virtual ~Flightviewer();//Destructor
  QQuickView viewer;

  void showWindow();

  void readFlightTrajectory(Flight flight);
};


#endif // FLIGHTVIEWER_H

threeDviewer.cpp //此文件配置QQuickView viewer實例。 它負責將航班數據導入QML數據文件。

#include <QtGui/QGuiApplication>
#include <QtCore/QDir>
#include <QtQuick/QQuickView>
#include <QtQml/QQmlEngine>

#include "window.h"
#include <QWidget>
#include "threeDviewer.h"
#include "datapointobject.h"
Flightviewer::Flightviewer(Flight displayedFlight, QString directory, QWidget*parent){

    // The following are needed to make examples run without having to install the module
    // in desktop environments.
#ifdef Q_OS_WIN
    QString extraImportPath(QStringLiteral("%1/../../../../%2"));
#else
    QString extraImportPath(QStringLiteral("%1/../../../%2"));
#endif
    qmlRegisterType<DataObject>();
    readFlightTrajectory(displayedFlight);
    viewer.setVisible(false);//Open only after clicked.
    viewer.engine()->addImportPath(extraImportPath.arg(QGuiApplication::applicationDirPath(),
                                  QString::fromLatin1("qml")));
    //! [4]
    QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);
    //! [4]

    viewer.setTitle(QStringLiteral("3D Flight Trajectory Visualization"));

    //! [3]
    viewer.setSource(QUrl("qrc:/qmlscatter/qml/qmlscatter/main.qml"));
    //! [3]

    viewer.setResizeMode(QQuickView::SizeRootObjectToView);

    //! [2]
    //! [2]
}
Flightviewer::~Flightviewer(){

}

void Flightviewer::showWindow(){
   viewer.showMaximized();
}
void Flightviewer::readFlightTrajectory(Flight flight){

   QList<QObject*> dataList;
   for (int i=0; i<flight.cogPosX_.size();i++){
       dataList.append(new DataObject(flight.cogPosX_.at(i),flight.cogPosY_.at(i),flight.cogPosZ_.at(i)));
   }
   QQmlContext * ctxt = viewer.rootContext();
   ctxt->setContextProperty("dataModel", QVariant::fromValue(dataList));
   viewer.update();
}

使用以下命令在外部函數中初始化“ QQuickViewer查看器”:

void Form::run3D(){
    threeDviewer= new Flightviewer(displayedFlights_[flightIndex],directory_);//initiate viewer

    threeDviewer->showWindow();//Show viewer

}

qml文件中的數據的定義與“ qmlscatter”示例中的完全相同:

Data.qml:

import QtQuick 2.1
Item {

property alias model: dataModel

ListModel {
    id: dataModel
    //ListElement{ xPos: -1000.0; yPos: 500.0; zPos: -5.0 }
} 
}

數據由main.qml文件訪問,該文件定義了Scatter3D項:

main.qml

    //! [0]
import QtQuick 2.1
import QtQuick.Layouts 1.0
import QtDataVisualization 1.0
import "."
//! [0]

//! [1]
Rectangle {
    id: mainView
    //! [1]
    width: 500
    height: 500

    //! [4]
    Data {
        id: seriesData
    }
    //! [4]

    //! [13]
    Theme3D {
        id: themeIsabelle
        type: Theme3D.ThemeIsabelle
        font.family: "Lucida Handwriting"
        font.pointSize: 40
    }
    //! [13]

    Theme3D {
        id: themeArmyBlue
        type: Theme3D.ThemeArmyBlue
    }

    //! [8]
    //! [9]
    Item {
        id: dataView
        anchors.bottom: parent.bottom
        //! [9]
        width: parent.width
        height: parent.height - buttonLayout.height
        //! [8]

        //! [2]
        Scatter3D {
            id: scatterGraph
            width: dataView.width
            height: dataView.height
            //! [2]
            //! [3]
            theme: themeIsabelle
            shadowQuality: AbstractGraph3D.ShadowQualitySoftLow
            //! [3]
            //! [6]
            axisX.segmentCount: 3
            axisX.subSegmentCount: 2
            axisX.labelFormat: "%.2f"
            axisZ.segmentCount: 2
            axisZ.subSegmentCount: 2
            axisZ.labelFormat: "%.2f"
            axisY.segmentCount: 2
            axisY.subSegmentCount: 2
            axisY.labelFormat: "%.2f"
            //! [6]
            //! [5]
            Scatter3DSeries {
                id: scatterSeries
                //! [5]
                //! [10]
                itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel"
                //! [10]

                //! [11]
                ItemModelScatterDataProxy {
                    itemModel: seriesData.model
                    xPosRole: "xPos"
                    yPosRole: "yPos"
                    zPosRole: "zPos"
                }
                //! [11]
            }
        }
    }

    RowLayout {
        id: buttonLayout
        Layout.minimumHeight: cameraToggle.height
        width: parent.width
        anchors.left: parent.left
        spacing: 0
        //! [7]
        NewButton {
            id: shadowToggle
            Layout.fillHeight: true
            Layout.fillWidth: true
            text: scatterGraph.shadowsSupported ? "Hide Shadows" : "Shadows not supported"
            enabled: scatterGraph.shadowsSupported
            onClicked: {
                if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
                    scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualitySoftLow;
                    text = "Hide Shadows";
                } else {
                    scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
                    text = "Show Shadows";
                }
            }
        }
        //! [7]

        NewButton {
            id: smoothToggle
            Layout.fillHeight: true
            Layout.fillWidth: true
            text: "Use Smooth for Series One"
            onClicked: {
                if (scatterSeries.meshSmooth === false) {
                    text = "Use Flat for Series One";
                    scatterSeries.meshSmooth = true;
                } else {
                    text = "Use Smooth for Series One"
                    scatterSeries.meshSmooth = false;
                }
            }
        }

        NewButton {
            id: cameraToggle
            Layout.fillHeight: true
            Layout.fillWidth: true
            text: "Change Camera Placement"
            onClicked: {
                if (scatterGraph.scene.activeCamera.cameraPreset === Camera3D.CameraPresetFront) {
                    scatterGraph.scene.activeCamera.cameraPreset =
                            Camera3D.CameraPresetIsometricRightHigh;
                } else {
                    scatterGraph.scene.activeCamera.cameraPreset = Camera3D.CameraPresetFront;
                }
            }
        }

        NewButton {
            id: themeToggle
            Layout.fillHeight: true
            Layout.fillWidth: true
            text: "Change Theme"
            onClicked: {
                if (scatterGraph.theme.type === Theme3D.ThemeArmyBlue) {
                    scatterGraph.theme = themeIsabelle
                } else {
                    scatterGraph.theme = themeArmyBlue
                }
                if (scatterGraph.theme.backgroundEnabled === true) {
                    backgroundToggle.text = "Hide Background";
                } else {
                    backgroundToggle.text = "Show Background";
                }
            }
        }

        NewButton {
            id: backgroundToggle
            Layout.fillHeight: true
            Layout.fillWidth: true
            text: "Hide Background"
            onClicked: {
                if (scatterGraph.theme.backgroundEnabled === true) {
                    scatterGraph.theme.backgroundEnabled = false;
                    text = "Show Background";
                } else {
                    scatterGraph.theme.backgroundEnabled = true;
                    text = "Hide Background";
                }
            }
        }

        NewButton {
            id: exitButton
            Layout.fillHeight: true
            Layout.fillWidth: true
            text: "Quit"
            onClicked: Qt.quit(0);
        }
    }
}

如果您能給我一些如何正確編程的提示,我將不勝感激。 預先感謝!

這是從C ++向Scatter3D提供數據的簡單示例:

首先,我們定義一個從QAbstractListModel派生的模型類。 在這種情況下,我們必須僅提供3種方法的實現。

FlightModel.h

#ifndef FLIGHTMODEL_H
#define FLIGHTMODEL_H

#include <QAbstractListModel>
#include <QList>
#include <QVector3D>

class FlightModel : public QAbstractListModel
{
    Q_OBJECT
public:
    FlightModel(QObject *parent = Q_NULLPTR);
    int rowCount(const QModelIndex &parent = QModelIndex()) const override;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
    QHash<int, QByteArray> roleNames() const override;

private:
    QList<QVector3D> m_innerData;
};

#endif // FLIGHTMODEL_H

FlightModel.cpp

#include "flightmodel.h"

FlightModel::FlightModel(QObject *parent) : QAbstractListModel(parent)
{
    qsrand(time(NULL));
    int count = 100 + qrand() % 100;
    for(int i = 0;i < count;i ++) {
        double x = (double)(qrand() % 1000);
        double y = (double)(qrand() % 1000);
        double z = (double)(qrand() % 1000);
        m_innerData.append(QVector3D(x, y, z));
    }
}

int FlightModel::rowCount(const QModelIndex &parent) const
{
    return m_innerData.count();
}

QVariant FlightModel::data(const QModelIndex &index, int role) const
{
    if(!index.isValid())
        return QVariant();

    QVector3D point = m_innerData[index.row()];
    switch(role) {
        case Qt::UserRole + 1: return point.x(); break;
        case Qt::UserRole + 2: return point.y(); break;
        case Qt::UserRole + 3: return point.z(); break;
    }
    return QVariant();
}

QHash<int, QByteArray> FlightModel::roleNames() const
{
    QHash<int, QByteArray> roles;
       roles[Qt::UserRole + 1] = "x";
       roles[Qt::UserRole + 2] = "y";
       roles[Qt::UserRole + 3] = "z";
       return roles;
}

構造函數創建100-200個隨機3D點的數組作為我們的數據源。

要在QML中使用模型,我們應該使用qmlRegisterTypesetContextProperty 在這種情況下,我使用第一個。

QQmlApplicationEngine engine;
qmlRegisterType<FlightModel>("mytest", 1, 0, "FlightModel");
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));

因此,現在我們可以在QML中使用該模型:

main.qml

import QtQuick 2.9
import QtQuick.Window 2.0
import QtDataVisualization 1.2
import mytest 1.0

Window {
    id: window
    width: 600
    height: 400
    visible: true

    FlightModel {
        id: dataModel
    }

    Scatter3D {
        anchors.fill: parent
        Scatter3DSeries {
            ItemModelScatterDataProxy {
                itemModel: dataModel

                xPosRole: "x"
                yPosRole: "y"
                zPosRole: "z"
            }
        }
    }
}

暫無
暫無

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

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