QT----------QT Data Visualzation
实现思路:
- 配置项目:在
.pro
文件中添加QT += datavisualization
以引入 QT Data Visualization 模块。 - 创建主窗口:使用
QMainWindow
作为主窗口,添加Q3DScatter
、Q3DBars
和Q3DSurface
等三维视图组件。 - 初始化和创建三维图表:分别为每种类型的图表(柱状图、散点图、曲面图)创建数据集、系列和轴,并将它们添加到相应的三维视图中。
- 其他功能实现:根据需要添加一些自定义功能,如调整视角、添加数据操作等。
代码示例:
#include <QtWidgets/QApplication>
#include <QtWidgets/QMainWindow>
#include <QtDataVisualization/Q3DScatter>
#include <QtDataVisualization/Q3DBars>
#include <QtDataVisualization/Q3DSurface>
#include <QtDataVisualization/QBar3DSeries>
#include <QtDataVisualization/QScatter3DSeries>
#include <QtDataVisualization/QSurface3DSeries>
#include <QtDataVisualization/QValue3DAxis>
#include <QtDataVisualization/QCustom3DItem>
#include <QtCore/QRandomGenerator>
#include <QtWidgets/QVBoxLayout>
#include <QtWidgets/QWidget>
QT_USE_NAMESPACE
using namespace QtDataVisualization;
// 辅助函数:生成随机数
float randomFloat(float min, float max) {
return QRandomGenerator::global()->bounded(min, max);
}
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
// 创建主窗口
QMainWindow mainWindow;
QWidget *centralWidget = new QWidget(&mainWindow);
mainWindow.setCentralWidget(centralWidget);
QVBoxLayout *layout = new QVBoxLayout(centralWidget);
// 三维柱状图
Q3DBars *bars = new Q3DBars();
QBar3DSeries *barSeries = new QBar3DSeries();
QBarDataRow *dataRow1 = new QBarDataRow();
QBarDataRow *dataRow2 = new QBarDataRow();
for (int i = 0; i < 5; ++i) {
*dataRow1 << randomFloat(0, 10);
*dataRow2 << randomFloat(0, 10);
}
barSeries->dataProxy()->addRow(dataRow1);
barSeries->dataProxy()->addRow(dataRow2);
bars->addSeries(barSeries);
QValue3DAxis *barAxisX = new QValue3DAxis();
barAxisX->setTitle("X Axis");
barAxisX->setRange(0, 4);
bars->setValueAxisX(barAxisX);
QValue3DAxis *barAxisY = new QValue3DAxis();
barAxisY->setTitle("Y Axis");
barAxisY->setRange(0, 1);
bars->setValueAxisY(barAxisY);
QValue3DAxis *barAxisZ = new QValue3DAxis();
barAxisZ->setTitle("Z Axis");
barAxisZ->setRange(0, 10);
bars->setValueAxisZ(barAxisZ);
QWidget *barsContainer = QWidget::createWindowContainer(bars);
layout->addWidget(barsContainer);
// 三维散点图
Q3DScatter *scatter = new Q3DScatter();
QScatter3DSeries *scatterSeries = new QScatter3DSeries();
for (int i = 0; i < 100; ++i) {
scatterSeries->dataProxy()->addItem(new QScatterDataItem(QVector3D(randomFloat(0, 10), randomFloat(0, 10), randomFloat(0, 10)));
}
scatter->addSeries(scatterSeries);
QValue3DAxis *scatterAxisX = new QValue3DAxis();
scatterAxisX->setTitle("X Axis");
scatterAxisX->setRange(0, 10);
scatter->setValueAxisX(scatterAxisX);
QValue3DAxis *scatterAxisY = new QValue3DAxis();
scatterAxisY->setTitle("Y Axis");
scatterAxisY->setRange(0, 10);
scatter->setValueAxisY(scatterAxisY);
QValue3DAxis *scatterAxisZ = new QValue3DAxis();
scatterAxisZ->setTitle("Z Axis");
scatterAxisZ->setRange(0, 10);
scatter->setValueAxisZ(scatterAxisZ);
QWidget *scatterContainer = QWidget::createWindowContainer(scatter);
layout->addWidget(scatterContainer);
// 三维曲面图
Q3DSurface *surface = new Q3DSurface();
QSurface3DSeries *surfaceSeries = new QSurface3DSeries();
QSurfaceDataArray *dataArray = new QSurfaceDataArray();
int size = 50;
for (int i = 0; i < size; ++i) {
QSurfaceDataRow *dataRow = new QSurfaceDataRow();
for (int j = 0; j < size; ++j) {
float x = (float)i / (size - 1) * 10;
float y = (float)j / (size - 1) * 10;
float z = sin(sqrt(x * x + y * y));
*dataRow << QVector3D(x, y, z);
}
*dataArray << dataRow;
}
surfaceSeries->dataProxy()->resetArray(dataArray);
surface->addSeries(surfaceSeries);
QValue3DAxis *surfaceAxisX = new QValue3DAxis();
surfaceAxisX->setTitle("X Axis");
surfaceAxisX->setRange(0, 10);
surface->setValueAxisX(surfaceAxisX);
QValue3DAxis *surfaceAxisY = new QValue3DAxis();
surfaceAxisY->setTitle("Y Axis");
surfaceAxisY->setRange(0, 10);
surface->setValueAxisY(surfaceAxisY);
QValue3DAxis *surfaceAxisZ = new QValue3DAxis();
surfaceAxisZ->setTitle("Z Axis");
surface->setValueAxisZ(surfaceAxisZ);
QWidget *surfaceContainer = QWidget::createWindowContainer(surface);
layout->addWidget(surfaceContainer);
mainWindow.show();
return a.exec();
}
代码解释:
-
三维柱状图:
Q3DBars
是三维柱状图的视图组件。QBar3DSeries
是柱状图的数据系列,使用QBarDataRow
存储数据行。QValue3DAxis
用于设置 x、y 和 z 轴的范围和标题。QWidget::createWindowContainer
将三维视图组件包装成一个QWidget
,以便添加到布局中。
-
三维散点图:
Q3DScatter
是三维散点图的视图组件。QScatter3DSeries
是散点图的数据系列,使用QScatterDataItem
添加数据点。
-
三维曲面图:
Q3DSurface
是三维曲面图的视图组件。QSurface3DSeries
是曲面图的数据系列,使用QSurfaceDataArray
和QSurfaceDataRow
存储数据点。- 在示例中,使用
sin(sqrt(x * x + y * y))
生成一个简单的曲面形状。
配置 .pro
文件:
确保在 .pro
文件中添加以下内容:
QT += datavisualization widgets
CONFIG += c++11
使用说明:
- 将上述代码保存为一个
.cpp
文件,例如main.cpp
。 - 创建一个
.pro
文件,添加上述配置。 - 编译并运行程序,你将看到一个包含三维柱状图、三维散点图和三维曲面图的主窗口。
其他功能的实现:
- 调整视角:可以使用
bars->scene()->activeCamera()->setCameraPosition
等方法调整三维视图的视角。 - 添加交互功能:可以通过重写
Q3DScatter
、Q3DBars
或Q3DSurface
的鼠标事件函数,实现数据点的选择、高亮显示等交互功能。 - 三维地形图:对于三维地形图,可以使用高度图数据替换
QSurface3DSeries
的数据,通过读取地理信息系统(GIS)数据或生成地形数据文件来实现。例如,使用QSurfaceDataArray
存储地形的高程信息,以x
和y
表示位置,z
表示高度。