文章目录
一、图表操作示例图
1.图表选择示例
- 一、图表操作示例图
- 1.图表选择示例
- 2.视角选项操作
- 3.样式选项操作
- 4.其他选项操作
- 二、QtDataVisualization(个人理解)
- 三、自定义槽函数的添加(UI界面)
- 四、源码
- CMainWindow.h
- CMainWindow.cpp
- CMainWindow.ui
- main.cpp
- 总结
- 相关文章
下图演示了通过下拉列表框切换三维图表的操作。
下图演示了自动切换、通过spinBox控件切换和slider控件的缩放功能(三维图表自带有鼠标滚轮缩放功能)。
下图演示了主题奇幻,系列样式切换,选择模式切换的效果
下图演示了显示背景、显示网格、显示倒影和二维显示等功能。 二维显示截图
提示:不会使用Qt设计师设计界面的小伙伴点击这里
二、QtDataVisualization(个人理解)- 使用前需要在pro文件中添加“QT += datavisualization”;
- 和QChart类似,导入头文件后还需通过“using namespace QtDataVisualization;”代码使用对应的命名空间;
- 其数据的存储方式也和QChart来说大同小异,有分装格式的,如:QWidget->Graph->Series->Proxy,QWidget为通过createWindowContainer()函数返回的容器对象,其中包含对应的图形对象(Graphi),三维图形也包括系列对象(series),并且系列对象中包含数据代理(Proxy,用于数据管理等),数据代理中也包括不同的数据对象,记住这个顺序,大体也是没问题的。
在QChart文章中涉及到了槽函数添加的几种方式,现在再演示一种,操作流程如下:
- 按F4键,进入信号槽编辑模式;
- 选中按钮拖动会出现红色的关联线(需要连接哪个控件只需将关联线拖到到对应的控件上即可,本文为连接this,所以拖到了外边);
- 弹出配置连接后,选择信号,点击槽函数下方的编辑按钮,在信号槽界面添加自定义槽函数,然后确定,则成功绑定信号槽。
本文中和QChart一样也包含动态属性、按钮组,在此就不再介绍,想要了解的小伙伴点击这里QChart图表的简单使用,在该文的“部分源码讲解”内容中。
(因为本文ui中包含动态属性,所以本文会留下ui代码,可复制粘贴到ui文件使用)
CMainWindow.h#ifndef CMAINWINDOW_H
#define CMAINWINDOW_H
#include
#include
// 导入数据可视化头文件
#include
//! 和QChart一样是要使用对应的命名空间
using namespace QtDataVisualization;
namespace Ui {
class CMainWindow;
}
//! 设置一个模板函数
template
void setSeriesStyle(T graphi, int index);
class CMainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit CMainWindow(QWidget *parent = nullptr);
~CMainWindow();
/**
* @brief create3DBarGraph 创建三维柱状图
* @return 返回三维柱状图指针
*/
QAbstract3DGraph * create3DBarGraph();
/**
* @brief create3DScatterGraph 创建三维散点图
* @return 返回散点图指针
*/
QAbstract3DGraph * create3DScatterGraph();
/**
* @brief create3DSurfaceGraph 创建三维曲面图
* @return 返回三维曲面图指针
*/
QAbstract3DGraph * create3DSurfaceGraph();
/**
* @brief createValue3DAxis 创建值坐标轴
* @param axisTitle 坐标轴标题
* @param titleVisible 是否显示标题
* @param min 坐标轴最小值
* @param max 坐标轴最大值
* @return 返回值坐标轴指针
*/
QValue3DAxis *createValue3DAxis(QString axisTitle, bool titleVisible = true, float min = 0, float max = 100);
/**
* @brief createCategory3DAxis 创建文本坐标轴
* @param axisTitle 坐标轴标题
* @param titleVisible 是否显示坐标轴
* @param labList 坐标轴标签
* @return 返回值坐标轴指针
*/
QCategory3DAxis *createCategory3DAxis(QString axisTitle, bool titleVisible = true, QStringList labList = QStringList());
// QObject interface
protected:
/**
* @brief timerEvent 定时器时间
* @param event 定时器对象
*/
void timerEvent(QTimerEvent *event);
private slots:
/**
* @brief on_angleValueChange 视角改变槽函数
* @param val 角度值
*/
void on_angleValueChange(int val);
/**
* @brief on_otherOptionGroup_buttonClicked 其他选项按钮组槽函数
* @param button 点击的按钮指针
*/
void on_otherOptionGroup_buttonClicked(QAbstractButton *button);
/**
* @brief on_seriesStyleComboBox_currentIndexChanged 系列样式设置槽函数
* @param index 样式索引值
*/
void on_seriesStyleComboBox_currentIndexChanged(int index);
/**
* @brief on_themeComboBox_currentIndexChanged 主题选择槽函数
* @param index 主题索引值
*/
void on_themeComboBox_currentIndexChanged(int index);
/**
* @brief on_selectModeComboBox_currentIndexChanged 选择模式槽函数
* @param index 选择模式索引值
*/
void on_selectModeComboBox_currentIndexChanged(int index);
/**
* @brief on_scaleSlider_sliderMoved 缩放功能槽函数
* @param position 缩放值
*/
void on_scaleSlider_sliderMoved(int position);
/**
* @brief on_autoSwitchAngleBtn_clicked 自动切换视角按钮槽函数
* @param checked 按钮选中状态
*/
void on_autoSwitchAngleBtn_clicked(bool checked);
/**
* @brief on_typeComboBox_currentIndexChanged 图表类型选选择槽函数
* @param index 类型索引值
*/
void on_typeComboBox_currentIndexChanged(int index);
private:
Ui::CMainWindow *ui; // ui对象指针
QList m_graphLsit; // 图表容器指针
int m_timer; // 定时器对象
};
#endif // CMAINWINDOW_H
CMainWindow.cpp
#include "CMainWindow.h"
#include "ui_CMainWindow.h"
#include
CMainWindow::CMainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::CMainWindow)
{
ui->setupUi(this);
// 设置标题
this->setWindowTitle("三维图形的简单使用");
// 创建三维柱状图
m_graphLsit.append(create3DBarGraph());
// 创建三维散点图
m_graphLsit.append(create3DScatterGraph());
// 创建三维曲面图
m_graphLsit.append(create3DSurfaceGraph());
// 重置随机数种子
srand(QDateTime::currentSecsSinceEpoch() % 1000000);
// ui->otherOptionGroup->setExclusive(false); // 设置按钮组可多选(ui界面已设置)
}
CMainWindow::~CMainWindow()
{
// 遍历删除图表对象
for(int index = m_graphLsit.count() - 1; index != -1; --index)
{
// 释放图表
delete m_graphLsit.at(index);
}
// 删除ui对象
delete ui;
}
QAbstract3DGraph *CMainWindow::create3DBarGraph()
{
// 创建三维柱状图对象
Q3DBars *bars = new Q3DBars;
// 创建三维柱状图容器
QWidget *container = QWidget::createWindowContainer(bars);
// 将当前容器添加到栈窗口对象中,并设置容器为栈窗口当前窗口
ui->stackedWidget->addWidget(container);
ui->stackedWidget->setCurrentWidget(container);
// 创建三维柱状图坐标轴对象
bars->setValueAxis(createValue3DAxis("Value Axis", true, 0, 10));
// 创建坐标轴标签容器并添加到坐标轴中
// 列坐标轴
QStringList colLabs;
colLabs addSeries(series);
// 创建三维曲面图数据容器
QSurfaceDataArray *array = new QSurfaceDataArray;
// 创建三维曲面图数据
for(int index = 0; index != 5; ++index)
{
// 创建三维曲面图行数据容器
QSurfaceDataRow *dataRow = new QSurfaceDataRow;
// 遍历添加数据到行容器
for(int valIdx = 0; valIdx != 3; ++valIdx)
{
// 随机数添加数据
dataRow->append(QVector3D(rand() % 100, rand() % 100, rand() % 100));
}
// 将行容器添加到array中
array->append(dataRow);
}
// 将数据添加到系列对象中
series->dataProxy()->resetArray(array);
//! 因为曲面图是面,所以切换系列类型没有变化
//! 若要设置面的样式可像下方一样调用setDrawMode函数
//! surface->seriesList()[0]->setDrawMode(QSurface3DSeries::DrawFlag(vlaue));
//! value:枚举值 其中枚举值如下
//! QSurface3DSeries::DrawWireframe 仅绘制网格。
//! QSurface3DSeries::DrawSurface 仅绘制曲面。
//! QSurface3DSeries::DrawSurfaceAndWireframe 绘制曲面和栅格。
//! 设置动态属性(类型,作用为在设置系列样式槽函数中区分)
surface->setProperty("Type", -1);
// 返回三维曲面图对象
return surface;
}
QValue3DAxis *CMainWindow::createValue3DAxis(QString axisTitle, bool titleVisible, float min, float max)
{
// 创建值坐标轴对象
QValue3DAxis *axis = new QValue3DAxis;
axis->setTitle(axisTitle); // 设置坐标轴标题
axis->setTitleVisible(titleVisible); // 设置标题是否显示
axis->setRange(min, max); // 设置坐标轴取值范围
// 返回坐标轴对象
return axis;
}
QCategory3DAxis *CMainWindow::createCategory3DAxis(QString axisTitle, bool titleVisible, QStringList labList)
{
// 创建文本坐标轴对象
QCategory3DAxis *axis = new QCategory3DAxis;
axis->setTitle(axisTitle); // 设置坐标轴标题
axis->setTitleVisible(titleVisible); // 设置标题是否显示
axis->setLabels(labList); // 设置坐标轴标签
// 返回坐标轴对象
return axis;
}
void CMainWindow::on_angleValueChange(int val)
{
// 拿到信号发送者
QSpinBox *spinBox = dynamic_cast(sender());
// 若当前为定时改变视角则不设置活动摄像角度,并将动态属性值设置为false
if(spinBox->property("RotationFlag").toBool())
{
spinBox->setProperty("RotationFlag", false);
return;
}
// 拿到视角类型
int type = spinBox->property("DirectionType").toInt();
// 判断当前方向类型,并将角度赋到对应位置
if(0 == type)
{
// 遍历设置所有三维图的X轴视角
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 获取图表的视图->活动摄像头->设置角度
graph->scene()->activeCamera()->setXRotation(val);
}
}
else if(1 == type)
{
// 遍历设置所有三维图的Y轴视角
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 获取图表的视图->活动摄像头->设置角度
graph->scene()->activeCamera()->setYRotation(val);
}
}
}
void CMainWindow::on_otherOptionGroup_buttonClicked(QAbstractButton *button)
{
// 将按钮对象转为复选框对象
QCheckBox *curBox = dynamic_cast(button);
// 获取当前按钮的类型
int type = curBox->property("OptionType").toInt();
// 获取按钮选择状态
bool checkedStatus = curBox->isChecked();
switch (type)
{
case 0:
{
// 循环设置图表状态
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 设置背景可用
graph->activeTheme()->setBackgroundEnabled(checkedStatus);
// 标签可用
graph->activeTheme()->setLabelBackgroundEnabled(checkedStatus);
}
break;
}
case 1:
{
// 循环设置图表状态
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 设置显示网格
graph->activeTheme()->setGridEnabled(checkedStatus);
}
break;
}
case 2:
{
// 循环设置图表状态
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 设置显示倒影
graph->setReflection(checkedStatus);
}
break;
}
case 3:
{
// 循环设置图表状态
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 设置正交投影显示(偏二维)
graph->setOrthoProjection(checkedStatus);
}
break;
}
default:
break;
}
}
void CMainWindow::timerEvent(QTimerEvent *event)
{
Q_UNUSED(event);
// 创建当前摄像头对象
Q3DCamera *curCamera;
// 循环设置相机视角
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
// 获取当前视图视角
curCamera = graph->scene()->activeCamera();
// 获取当前视角值
int curCameraPreset = curCamera->cameraPreset();
// 判断获取下一是视角值
int cameraPreset = curCameraPreset == 21? 1: curCameraPreset + 1;
// 设置相机视角
curCamera->setCameraPreset(Q3DCamera::CameraPreset(cameraPreset));
}
// 设置水平视角控件值
ui->horAngleSpinBox->setValue(curCamera->xRotation());
// 设置水平动态属性
ui->horAngleSpinBox->setProperty("RotationFlag", true);
// 设置垂直视角控件值
ui->verAngleSpinBox->setValue(curCamera->yRotation());
// 设置水平动态属性
ui->verAngleSpinBox->setProperty("RotationFlag", true);
}
void CMainWindow::on_seriesStyleComboBox_currentIndexChanged(int index)
{
// 循环设置图表系列状态
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
int type = graph->property("Type").toInt();
// 获取当前图表类型
switch (type)
{
case 0:
{
// 调用样式模板函数
setSeriesStyle(dynamic_cast(graph), index);
break;
}
case 1:
{
// 调用样式模板函数
setSeriesStyle(dynamic_cast(graph), index);
break;
}
default:
break;
}
}
}
void CMainWindow::on_themeComboBox_currentIndexChanged(int index)
{
// 循环设置图表主题
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
graph->activeTheme()->setType(Q3DTheme::Theme(index));
}
}
void CMainWindow::on_selectModeComboBox_currentIndexChanged(int index)
{
// 设置柱状图的选择模式
m_graphLsit.first()->setSelectionMode(QAbstract3DGraph::SelectionFlag(index));
}
void CMainWindow::on_scaleSlider_sliderMoved(int position)
{
// 循环设置图表缩放
foreach(QAbstract3DGraph *graph, m_graphLsit)
{
graph->scene()->activeCamera()->setZoomLevel(position);
}
}
void CMainWindow::on_autoSwitchAngleBtn_clicked(bool checked)
{
// 根据状态做出相应操作
if(checked)
{
// 改变按钮文本
ui->autoSwitchAngleBtn->setText("停止");
// 启动定时器
m_timer = startTimer(750);
}
else
{
// 改变按钮文本
ui->autoSwitchAngleBtn->setText("开始");
// 终止定时器
killTimer(m_timer);
}
}
template
void setSeriesStyle(T graphi, int index)
{
// 循环设置图表样式
foreach(QAbstract3DSeries *series, graphi->seriesList())
{
//! 设置样式
//! 索引值加1是防止设置值为0的Mesh,未作出对应操作设置该值的样式会导致程序崩溃
//! 帮助中这样形容(翻译):用户定义网格,通过QAbstract3DSeries::userDefinedMesh属性设置。
series->setMesh(QAbstract3DSeries::Mesh(index + 1));
}
}
void CMainWindow::on_typeComboBox_currentIndexChanged(int index)
{
// 设置当前显示的图表
ui->stackedWidget->setCurrentIndex(index);
//! 判断选择模式禁用,仅在三维柱状图下可用
//! 因为在测试时发现本文中的三维散点图仅支持“无”和单项选择模式,三维曲面图不支持选择模式
ui->selectModeComboBox->setEnabled(0 == index);
//! 判断显示倒影禁用,仅在三维柱状图下可用
//! 因为在测试时发现本文中的三维散点图、三维曲面图并无倒影显示
ui->showReflectionCheckBox->setEnabled(0 == index);
//! 判断设置系列样式禁用
//! 三维曲面图设置Mesh无效,则禁用
ui->seriesStyleComboBox->setEnabled(2 != index);
}
CMainWindow.ui
CMainWindow
0
0
720
466
CMainWindow
0
0
0
0
0
10
7
5
10
5
5
5
5
5
三维(图)类型:
三维柱状图
三维散点图
三维曲面图
视角选项
5
5
5
5
5
自动切换视角:
100
16777215
开始
true
0
水平视角:
°
-180
180
5
0
Qt::Horizontal
40
20
垂直视角:
°
90
5
1
缩放:
10
500
100
Qt::Horizontal
样式选项
0
10
5
5
5
5
主题:
ThemeQt
ThemePrimaryColors
ThemeDigia
ThemeStoneMoss
ThemeArmyBlue
ThemeRetro
ThemeEbony
ThemeIsabelle
ThemeUserDefined
系列样式:
MeshBar
MeshCube
MeshPyramid
MeshCone
MeshCylinder
MeshBevelBar
MeshBevelCube
MeshSphere
MeshMinimal
MeshArrow
MeshPoint
选择模式:
SelectionNone
SelectionItem
SelectionRow
SelectionItemAndRow
SelectionColumn
SelectionItemAndColumn
SelectionRowAndColumn
SelectionItemRowAndColumn
SelectionSlice
SelectionMultiSeries
其他选项
5
5
5
5
0
显示背景
true
0
otherOptionGroup
显示网格
true
1
otherOptionGroup
显示倒影
2
otherOptionGroup
二维显示
3
otherOptionGroup
0
0
720
23
horAngleSpinBox
valueChanged(int)
CMainWindow
on_angleValueChange(int)
110
130
-83
239
verAngleSpinBox
valueChanged(int)
CMainWindow
on_angleValueChange(int)
273
131
-157
269
on_angleValueChange(int)
false
main.cpp
#include "CMainWindow.h"
#include
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CMainWindow w;
w.show();
return a.exec();
}
总结
由于三图存在于同一个简单的Demo中,功能不是很完善,和QChart一样,各个图表的选项独立最好(就是说每次点击按钮只改变当前图表的属性),有兴趣的伙伴可以优化此功能; 在开发过程中,多多少少还是会有碰壁,另外其实还有许多BUG都没有正面处理,原本想多种函数通用实现样式,最后发现样式多多少少有些差别,不得不限制某些控件在不同图表中的状态;除此之外还有很多值得我们去发掘的功能和BUG,学无止境,冲鸭😆。 现在也是很晚了,那就休息了,晚安吧😁。
相关文章Qt之QChart各个图表的简单使用(含源码+注释)
友情提示——哪里看不懂可私哦,让我们一起互相进步吧 (创作不易,请留下一个免费的赞叭 谢谢 ^o^/)
注:文章为作者编程过程中所遇到的问题和总结,内容仅供参考,若有错误欢迎指出。 注:如有侵权,请联系作者删除