簡単な散布図

QMLアプリケーションでScatter3D

Simple Scatter Graphでは、Scatter3D と QML を使って簡単な散布図グラフを視覚化する方法を示しています。

グラフの操作方法については、このページを参照してください。

新しい Qt Quick アプリケーションを作成する方法については、Qt Creator のヘルプを参照してください。

サンプルを実行する

Qt Creator からサンプルを実行するには、Welcome モードを開き、Examples からサンプルを選択します。詳細については、Building and Running an Example を参照してください。

アプリケーションの基本

QML コードに入る前に、アプリケーションmain.cpp を見てください。

このアプリケーションはUIに'Quit'ボタンを実装しているので、QQmlEngine::quit()シグナルをアプリケーションのQWindow::close()スロットに接続します:

QObject::connect(viewer.engine(), &QQmlEngine::quit, &viewer, &QWindow::close);

デプロイを少し簡単にするために、アプリケーションの.qml ファイルをすべてリソースファイル (qmlscatter.qrc) に集めてください:

<RCC>
    <qresource prefix="/">
        <file>qml/qmlscatter/Data.qml</file>
        <file>qml/qmlscatter/main.qml</file>
    </qresource>
</RCC>

また、main.qml をリソースから読み込むように設定する必要があります (qrc:):

viewer.setSource(QUrl("qrc:/qml/qmlscatter/main.qml"));

qmakeの代わりにcmakeを使う場合、.qml ファイルはCMakeLists.txt のQMLモジュールに追加されます:

qt6_add_qml_module(qmlscatter
    URI Scatter
    VERSION 1.0
    NO_RESOURCE_TARGET_PATH
    QML_FILES
        qml/qmlscatter/Data.qml
        qml/qmlscatter/main.qml
)

最後に、アプリケーションを最大化されたウィンドウで実行するようにします:

viewer.showMaximized();

グラフのセットアップ

まず、必要なQMLモジュールをすべてインポートします:

import QtQuick
import QtQuick.Controls
import QtDataVisualization

次に、メインのItem を作成し、mainView と呼びます:

Item {
    id: mainView

次に、メインのItem の中にもう一つItem を追加し、dataView と呼びます。これがScatter3D グラフを保持するアイテムとなります。これを親の下にアンカーします:

Item {
    id: dataView
    anchors.bottom: parent.bottom

次に、Scatter3D グラフそのものを追加する。これをdataView の中に追加し、名前をscatterGraph とします。dataView を埋めるようにします:

Scatter3D {
    id: scatterGraph
    anchors.fill: parent

これでグラフは使えるようになったが、データはない。また、デフォルトの軸とビジュアル・プロパティを持っています。

次に、scatterGraph の中に以下を追加して、まずいくつかのビジュアル・プロパティを変更します:

theme: themeQt
shadowQuality: AbstractGraph3D.ShadowQualityHigh
scene.activeCamera.cameraPreset: Camera3D.CameraPresetFront

カスタマイズしたテーマを追加し、影の質を変更し、カメラの位置を調整しました。他のビジュアルプロパティは問題ないので、変更する必要はありません。

カスタム・テーマは事前定義されたテーマTheme3D.ThemeQt をベースにしていますが、その中のフォントは変更されています:

Theme3D {
    id: themeQt
    type: Theme3D.ThemeQt
    font.pointSize: 40
}

次に、グラフにデータを与え始めます。

グラフへのデータの追加

mainView の中にData アイテムを作成し、seriesData と名づける:

Data {
    id: seriesData
}

seriesData 項目には、この例で使用する3つの系列すべてのデータモデルが含まれています。

これは、Data.qml のデータを保持するコンポーネントです。Item をメイン・コンポーネントとして持ちます。

メイン・コンポーネントのListModel にデータそのものを追加し、dataModel と名付けます:

ListModel {
    id: dataModel
    ListElement{ xPos: -10.0; yPos: 5.0; zPos: -5.0 }
    ...

他の2つの系列にもこれを追加し、dataModelTwodataModelThree と名付ける。

そして、main.qml から使えるようにデータモデルを公開する。これは、メインのデータ・コンポーネントでエイリアスとして定義することで行います:

property alias model: dataModel
property alias modelTwo: dataModelTwo
property alias modelThree: dataModelThree

これで、Data.qml のデータをscatterGraph と一緒にmain.qml で使うことができます。まず、Scatter3DSeries を追加し、scatterSeries と呼びます:

Scatter3DSeries {
    id: scatterSeries

次に、シリーズの選択ラベル・フォーマットを設定する:

itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel"

そして最後に、ItemModelScatterDataProxy に系列1のデータを追加する。プロキシ用のitemModel として、データそのものを設定する:

ItemModelScatterDataProxy {
    itemModel: seriesData.model
    xPosRole: "xPos"
    yPosRole: "yPos"
    zPosRole: "zPos"
}

他の2つの系列も同じように追加するが、系列固有の詳細を少し修正する:

Scatter3DSeries {
    id: scatterSeriesTwo
    itemLabelFormat: "Series 2: X:@xLabel Y:@yLabel Z:@zLabel"
    itemSize: 0.05
    mesh: Abstract3DSeries.MeshCube
    ...

それから、scatterGraph のデフォルト軸のプロパティを少し修正する:

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"

その後、mainView にグラフをコントロールするためのボタンをいくつか追加する:

Button {
    id: shadowToggle
    width: mainView.buttonWidth // Calculated elsewhere based on screen orientation
    anchors.left: parent.left
    anchors.top: parent.top
    anchors.margins: 5
    text: scatterGraph.shadowsSupported ? "Hide Shadows" : "Shadows not supported"
    enabled: scatterGraph.shadowsSupported
    onClicked: {
        if (scatterGraph.shadowQuality === AbstractGraph3D.ShadowQualityNone) {
            scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityHigh;
            text = "Hide Shadows";
        } else {
            scatterGraph.shadowQuality = AbstractGraph3D.ShadowQualityNone;
            text = "Show Shadows";
        }
    }
}

次に、dataView を修正し、上部にボタン用のスペースを作る:

Item {
    id: dataView
    anchors.bottom: parent.bottom
    width: parent.width
    // Adjust the space based on screen orientation:
    // If we're in portrait mode, we have 3 rows of buttons, otherwise they are all in one row.
    height: parent.height - (mainView.portraitMode ? shadowToggle.implicitHeight * 3 + 25
                                                   : shadowToggle.implicitHeight + 10)
    ...

これで完成だ!

コンテンツ例

サンプルプロジェクト @ code.qt.io

©2024 The Qt Company Ltd. 本書に含まれるドキュメントの著作権は、それぞれの所有者に帰属します。 ここで提供されるドキュメントは、Free Software Foundation が発行したGNU Free Documentation License version 1.3に基づいてライセンスされています。 Qtおよびそれぞれのロゴは、フィンランドおよびその他の国におけるThe Qt Company Ltd.の 商標です。その他すべての商標は、それぞれの所有者に帰属します。