简单的散点图
在 QML 应用程序中使用Scatter3D 。
Simple Scatter Graph展示了如何使用Scatter3D 和 QML 制作简单的散点图可视化。
有关如何与图形交互的说明,请参阅本页。
有关如何创建新的Qt Quick 应用程序的说明,请参阅Qt Creator 帮助。
运行示例
运行示例 Qt Creator,打开Welcome 模式,然后从Examples 中选择示例。更多信息,请参阅Qt Creator: 教程:构建并运行。
设置布局
在深入学习 QML 代码之前,main.cpp
设置应用程序。main.qml
文件是从资源 (qrc:
) 中读取的。
viewer.setSource(QUrl("qrc:/qml/scatter/main.qml"));
该main.qml
文件是应用程序 QML 代码的起点。首先,导入所有需要的 QML 模块:
import QtQuick import QtQuick.Controls import QtQuick.Layouts import QtGraphs
然后,创建一个Data
项目,该项目将保存图表数据。
Data { id: seriesData }
接下来,创建两个GraphsTheme 项,为图形定义两个不同的主题,一个是 Qt Green 主题,另一个是 Qt Neon Green 主题。
GraphsTheme { id: themeQt theme: GraphsTheme.Theme.QtGreen labelFont.pointSize: 40 } GraphsTheme { id: themeQtNeonGreen theme: GraphsTheme.Theme.QtGreenNeon colorScheme: GraphsTheme.ColorScheme.Dark }
此应用程序的布局将由五个不同的按钮组成,用于切换图形的不同可视化选项,当然还有图形本身。有许多方法可以组织这些按钮,其中一种方法是在GridLayout
中包含四个按钮、Graph
以及第五个按钮,所有按钮都出现在ColumnLayout
中。
ColumnLayout { id: mainLayout anchors.fill: parent anchors.margins: margin spacing: spacing
GridLayout
是响应式的。这意味着使用的列数取决于应用程序窗口的宽度。这可以通过给columns
属性分配一个三元运算符来实现,根据窗口宽度,解析为 1、2 或 4。
GridLayout { Layout.fillWidth: true rowSpacing: spacing columnSpacing: spacing columns: mainView.width < mainView.buttonMinWidth * 2 + mainView.spacing + mainView.margin * 2 // width of 2 buttons ? 1 : (mainView.width < mainView.buttonMinWidth * 4 + mainView.spacing * 3 + mainView.margin * 2 // width of 4 buttons ? 2 : 4)
在本GridLayout
中,实例化了四个RoundButton
。一个用于切换阴影,一个用于网格平滑,一个用于摄像机位置,最后一个用于更改图形背景。所有按钮都遵循相同的结构。与其为所有按钮重新定义这种结构,不如制作一个自定义组件。
component CustomButton : RoundButton { id: buttonRoot
CustomButtom
自定义组件扩展了 类型,但增加了一些内容。设置了 , , 和 等属性。这些属性定义了按钮的样式和布局。RoundButton
Layout.minimumWidth
Layout.FillWidth
radius
background
property alias source: iconImage.source Layout.minimumWidth: buttonMinWidth Layout.fillWidth: true radius: mainView.radius background: Rectangle { radius: mainView.radius color: "white" border.color: "black" }
而contentItem
则定义了按钮的内容,在本例中是一个包含图标和一些文本的Row
类型。图标通过Image
类型导入,并设置source
属性。文本使用Label
类型创建,并使用其text
属性进行设置。在自定义组件的顶部为这两个属性创建了两个联盟,这样就可以在创建CustomButton
实例时设置这两个属性。
contentItem: Row { id: content Image { id: iconImage } Label { text: buttonRoot.text horizontalAlignment: Text.AlignLeft anchors.verticalCenter: parent.verticalCenter } }
在GridLayout
中,创建了四个CustomButton
。需要设置三个属性,即图标图像和文本的两个联例,以及信号onClicked
。
CustomButton { id: shadowButton text: graph.shadowQuality === Graphs3D.ShadowQuality.None ? qsTr("Show Shadows") : qsTr("Hide Shadows") source: graph.shadowQuality === Graphs3D.ShadowQuality.None ? "qrc:/images/shadow.svg" : "qrc:/images/shadow_hide.svg" onClicked: { graph.shadowQuality = graph.shadowQuality === Graphs3D.ShadowQuality.None ? Graphs3D.ShadowQuality.High : Graphs3D.ShadowQuality.None } }
例如,阴影按钮设置onClicked
符号来切换阴影的开和关。
设置图表
布局的下一步是Graph
,它在自己的 QML 文件Graph.qml
中定义,实例化如下:
Graph { id: graph Layout.fillWidth: true Layout.fillHeight: true }
从Graph.qml
中的实现来看,图形属于Scatter3D
类型,嵌套在Item
类型中。
Scatter3D { id: 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"
设置数据
图表显示三个数据集,代表Data.qml
中给出的数据。数据集存储在ListModel
类型中。
ListModel { id: dataModel ListElement{ xPos: -10.0; yPos: 5.0; zPos: -5.0 } ... ListElement{ xPos: -7.54 ; yPos: 2.8 ; zPos: -3.68 } } ListModel { id: dataModelTwo ListElement{ xPos: 2.25 ; yPos: 1.36 ; zPos: -1.3 } ... ListElement{ xPos: -3.4 ; yPos: 0.6 ; zPos: 0.9 } } ListModel { id: dataModelThree ListElement{ xPos: 8.0; yPos: -2.0; zPos: 4.0 } ... ListElement{ xPos: 5.66 ; yPos: -4.98 ; zPos: 3.72 } }
中,并通过property alias
es 与其他文件连接。
property alias model: dataModel property alias modelTwo: dataModelTwo property alias modelThree: dataModelThree
在使用这些别名之前,请创建一个Scatter3DSeries
类型,其中包含ItemModelScatterDataProxy
项。
Scatter3DSeries { id: scatterSeries itemLabelFormat: "Series 1: X:@xLabel Y:@yLabel Z:@zLabel" ItemModelScatterDataProxy { itemModel: seriesData.model xPosRole: "xPos" yPosRole: "yPos" zPosRole: "zPos" } }
该数据代理使用其itemModel
属性引用Data.qml
中的数据集。上述别名通过Data
类型的id
访问,该 类型实例化为main.qml
,seriesData
。
itemModel: seriesData.model
对其余两个数据集重复上述操作。
Scatter3DSeries { id: scatterSeriesTwo ... ItemModelScatterDataProxy { itemModel: seriesData.modelTwo ... } } Scatter3DSeries { id: scatterSeriesThree ... ItemModelScatterDataProxy { itemModel: seriesData.modelThree ... } }
很好,现在散点图已经指向了三个数据集。
剩下要做的就是将剩下的按钮theme button
添加到我们的ColumnLayout
中。这个按钮的唯一不同之处在于它位于布局的左侧。这是通过将Layout.alignment
属性定义为Qt.AlignLeft
,将Layout.fillWidth
定义为false
来设置的。
CustomButton { id: themeButton Layout.alignment: Qt.AlignLeft Layout.fillWidth: false
示例内容
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.