数据图形化系统设计与实现

第一章 需求分析

问题描述

使用c++ 或者 java语言设计一个数据图形化系统。利用数据图形化的描述语言,显示数据。要求所开发的系统具备图形操作界面。

可以在https://gitee.com/czyt1988/data-workbench的基础上进行 定制图形界面不能调用任何第三方库或系统自身提供的绘图库API。

支持缩放、保存、鼠标悬停时提示信息。

功能需求

柱状图

描述语言例子:

option = {

xAxis: {

data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']

},

yAxis: {},

series: [

{

type: 'bar',

data: [23, 24, 18, 25, 27, 28, 25]

}

]

};

对应的柱状图:

柱状图

堆叠柱状图

堆叠柱状图就是一个系列的数值“堆叠”在另一个系列上,因而从他们的高度总和就能表达总量的变化。

option = {

xAxis: {

data: ['A', 'B', 'C', 'D', 'E']

},

yAxis: {},

series: [

{

data: [10, 22, 28, 43, 49],

type: 'bar',

stack: 'x'

},

{

data: [5, 4, 3, 5, 10],

type: 'bar',

stack: 'x'

}

]

};

对应的堆叠柱状图:

堆叠柱状图

折线图

option = {

xAxis: {

type: 'category',

data: ['A', 'B', 'C']

},

yAxis: {

type: 'value'

},

series: [

{

data: [120, 200, 150],

type: 'line'

}

]

};

对应的折线图:

折线图

在这个例子中,我们通过 xAxis 将横坐标设为类目型,并指定了对应的值;通过 type 将 yAxis 的类型设定为数值型。在 series 中,我们将系列类型设为 line,并且通过 data 指定了折线图三个点的取值。这样,就能得到一个最简单的折线图了。

平滑曲线图

option = {

xAxis: {

data: ['A', 'B', 'C', 'D', 'E']

},

yAxis: {},

series: [

{

data: [10, 22, 28, 23, 19],

type: 'line',

smooth: true

}

]

};

对应的平滑曲线图:

平滑曲线图

使用合适的平滑算法。

开发环境

Qt Creator 4.5.1(Community)

开发过程

  • 阅读实验需求,理解实验原理。
  • 设计程序框架。
  • 编写代码。

第二章 概要设计

总体设计

该系统通过 MainWidget 类提供了一个简单的用户界面,使用户能够输入数据、生成不同类型的图表并进行保存。核心功能由 ChartWidget 类实现,包括图表的绘制、缩放和交互功能。整体架构利用 Qt 的信号槽机制实现了用户操作与图表显示的关联,同时提供了良好的用户体验和操作界面。

这种设计使得用户可以方便地输入数据、生成定制化的图表,并将其保存为常见的图像格式,适用于需要展示和分析数据的应用场景。

类的定义

MainWidget 类

构造函数 MainWidget(QWidget *parent = nullptr):

初始化主窗口部件,并设置窗口初始大小为 800×600 像素。

创建 inputEdit,用于用户输入 JSON 格式的数据。

创建 generateButton 和 saveButton,分别用于生成图表和保存图表。

创建 chartWidget 对象,用于显示图表,这是 ChartWidget 类的实例。

设置各个控件的位置和大小。

析构函数 ~MainWidget():清理资源。

私有槽函数 onGenerateChart():

处理生成图表按钮 (generateButton) 的点击信号。

获取 inputEdit 中的 JSON 字符串,将其解析为 QJsonDocument 对象。

如果解析成功,调用 chartWidget 的 setChartOptions() 方法,将解析后的 QJsonObject 设置为图表的选项,从而更新图表显示。

私有槽函数 onSaveChart():

处理保存图表按钮 (saveButton) 的点击信号。

弹出文件对话框让用户选择保存路径和文件类型(PNG、JPEG、BMP)。

如果用户选择了文件路径,调用 chartWidget 的 saveImage() 方法将当前显示的图表保存为用户指定的图像文件。

ChartWidget 类

继承自 QWidget:用于显示图表的自定义窗口部件。

成员函数:

构造函数 ChartWidget(QWidget *parent = nullptr):初始化图表部件,设置鼠标跟踪。

setChartOptions(const QJsonObject &options):设置图表的选项,更新并重绘图表。

saveImage(const QString &filePath):将当前图表保存为指定路径的图像文件。

缩放相关函数:zoomIn()、zoomOut()、resetZoom(),用于放大、缩小和重置图表的缩放比例。

事件处理函数:包括 paintEvent(绘制图表)、mouseMoveEvent(处理鼠标移动事件以显示工具提示)、wheelEvent(处理鼠标滚轮事件以实现缩放)。

成员变量:

chartOptions:存储图表的选项(例如 X 轴数据、系列数据等)。

mousePos:存储当前鼠标位置,用于显示工具提示。

zoomFactor:当前的缩放因子,用于实现图表的缩放功能。

其他私有变量和方法用于具体的绘制功能和数据处理。

接口设计

输入和操作

inputEdit:用于用户输入 JSON 数据,支持任意格式的数据输入。

generateButton:生成图表按钮,点击后触发 onGenerateChart() 槽函数,根据用户输入的 JSON 数据生成并显示图表。

saveButton:保存图表按钮,点击后触发 onSaveChart() 槽函数,允许用户选择文件路径和类型保存当前显示的图表。

图表显示

chartWidget:由 ChartWidget 类负责实际的图表绘制和显示,通过调用 setChartOptions() 更新图表数据,并通过 saveImage() 方法保存图表为图像文件。

setChartOptions(const QJsonObject &options):通过传入 JSON 对象设置图表的各种选项,如 X 轴数据、系列数据等。

saveImage(const QString &filePath):将当前显示的图表保存为指定路径的图像文件。

缩放相关函数:zoomIn()、zoomOut()、resetZoom(),提供用户交互接口,支持图表的放大和缩小。

运行界面设计

图表绘制:使用 QPainter 绘制 X 轴、Y 轴、数据点、折线或柱状图。

交互功能:支持鼠标悬停显示数据点信息,支持滚轮缩放图表。

用户反馈:通过工具提示显示鼠标悬停位置的数据信息,提高用户体验。

第三章 详细设计

1. ChartWidget 类

头文件 chartwidget.h

#ifndef CHARTWIDGET_H#define CHARTWIDGET_H

#include <QWidget>

#include <QJsonObject>

#include <QMap>

class ChartWidget : public QWidget

{

Q_OBJECT

public:

explicit ChartWidget(QWidget *parent = nullptr);

void setChartOptions(const QJsonObject &options);

void saveImage(const QString &filePath);

void zoomIn();

void zoomOut();

void resetZoom();

protected:

void paintEvent(QPaintEvent *event) override;

void mouseMoveEvent(QMouseEvent *event) override;

void wheelEvent(QWheelEvent *event) override;

private:

QJsonObject chartOptions;

QString chartTitle;

QPoint mousePos;

qreal zoomFactor = 1.0;

 

void drawBarChart(QPainter &painter, const QJsonArray &data, const QString &stack, qreal xInterval, int height);

void drawLineChart(QPainter &painter, const QJsonArray &xAxisData, const QJsonArray &data, qreal xInterval, int height);

void drawSmoothLineChart(QPainter &painter, const QJsonArray &xAxisData, const QJsonArray &data, qreal xInterval, int height);

};

#endif // CHARTWIDGET_H

成员变量

  • chartOptions:存储图表选项的 JSON 对象。
  • chartTitle:存储图表标题。
  • mousePos:存储当前鼠标位置。
  • zoomFactor:当前的缩放因子,用于控制图表的缩放。

公共函数

  • ChartWidget(QWidget *parent = nullptr):构造函数,初始化图表部件。
  • void setChartOptions(const QJsonObject &options):设置图表的选项,更新并重绘图表。
  • void saveImage(const QString &filePath):将当前图表保存为指定路径的图像文件。
  • void zoomIn()、void zoomOut()、void resetZoom():分别实现放大、缩小和重置图表的缩放功能。

事件处理函数

  • void paintEvent(QPaintEvent *event):重绘事件处理函数,绘制图表内容。
  • void mouseMoveEvent(QMouseEvent *event):鼠标移动事件处理函数,用于显示数据提示。
  • void wheelEvent(QWheelEvent *event):鼠标滚轮事件处理函数,实现图表的放大和缩小。

私有函数

  • void drawBarChart(QPainter &painter, const QJsonArray &data, const QString &stack, qreal xInterval, int height):绘制柱状图。
  • void drawLineChart(QPainter &painter, const QJsonArray &xAxisData, const QJsonArray &data, qreal xInterval, int height):绘制折线图。
  • void drawSmoothLineChart(QPainter &painter, const QJsonArray &xAxisData, const QJsonArray &data, qreal xInterval, int height):绘制平滑曲线图。

实现文件 chartwidget.cpp

#include "chartwidget.h"

#include <QPainter>

#include <QPainterPath>

#include <QMouseEvent>

#include <QToolTip>

#include <QJsonArray>

#include <QtCore/qmath.h>

 

ChartWidget::ChartWidget(QWidget *parent)

: QWidget(parent)

{

setMouseTracking(true); // 开启鼠标跟踪,以便实时获取鼠标位置

}

void ChartWidget::setChartOptions(const QJsonObject &options){

chartOptions = options;

update(); // 更新图表内容

}

void ChartWidget::saveImage(const QString &filePath){

QPixmap pixmap(size());

render(&pixmap);

pixmap.save(filePath);

}

void ChartWidget::zoomIn(){

zoomFactor *= 1.1; // 每次放大10%

update(); // 更新图表内容

}

void ChartWidget::zoomOut(){

zoomFactor /= 1.1; // 每次缩小10%

update(); // 更新图表内容

}

void ChartWidget::resetZoom(){

zoomFactor = 1.0; // 重置缩放因子

update(); // 更新图表内容

}

void ChartWidget::wheelEvent(QWheelEvent *event){

if (event->angleDelta().y() > 0)

{

zoomIn(); // 向上滚动放大

}

else

{

zoomOut(); // 向下滚动缩小

}

}

void ChartWidget::paintEvent(QPaintEvent *event){

// 绘制图表的具体实现,根据 chartOptions 中的数据绘制不同类型的图表

}

void ChartWidget::mouseMoveEvent(QMouseEvent *event){

// 处理鼠标移动事件,显示数据提示信息

}

void ChartWidget::drawBarChart(QPainter &painter, const QJsonArray &data, const QString &stack, qreal xInterval, int height){

// 绘制柱状图的具体实现

}

void ChartWidget::drawLineChart(QPainter &painter, const QJsonArray &xAxisData, const QJsonArray &data, qreal xInterval, int height){

// 绘制折线图的具体实现

}

void ChartWidget::drawSmoothLineChart(QPainter &painter, const QJsonArray &xAxisData, const QJsonArray &data, qreal xInterval, int height){

// 绘制平滑折线图的具体实现

}

2. MainWidget 类

头文件 mainwidget.h

#ifndef MAINWIDGET_H#define MAINWIDGET_H

#include <QWidget>#include <QJsonObject>#include <QJsonDocument>#include <QJsonArray>#include <QVBoxLayout>#include <QLineEdit>#include <QPushButton>#include <QLabel>

class ChartWidget;

class MainWidget : public QWidget

{

Q_OBJECT

public:

MainWidget(QWidget *parent = nullptr);

~MainWidget();

private slots:

void onGenerateChart();

void onSaveChart();

private:

QLineEdit *inputEdit;

QPushButton *generateButton;

QPushButton *saveButton;

ChartWidget *chartWidget;

};

#endif // MAINWIDGET_H

成员变量

  • inputEdit:用户输入框,用于输入 JSON 数据。
  • generateButton、saveButton:生成图表和保存图表的按钮。
  • chartWidget:指向 ChartWidget类的对象指针,用于显示图表。

公共函数

  • MainWidget(QWidget *parent = nullptr):构造函数,初始化界面布局和控件。
  • ~MainWidget():析构函数,清理资源。

私有槽函数

  • onGenerateChart():处理生成图表按钮点击事件,解析用户输入的 JSON 数据,并更新 chartWidget显示对应的图表。
  • onSaveChart():处理保存图表按钮点击事件,弹出文件保存对话框,并将当前显示的图表保存为用户指定的图像文件。

实现文件 mainwidget.cpp

#include "mainwidget.h"

#include "chartwidget.h"

#include <QFileDialog>

 

MainWidget::MainWidget(QWidget *parent)

: QWidget(parent),

inputEdit(new QLineEdit(this)),

generateButton(new QPushButton("生成图表", this)),

saveButton(new QPushButton("保存图片", this)),

chartWidget(new ChartWidget(this))

{

resize(800, 600); // 设置主窗口初始大小

 

// 设置控件位置和大小

inputEdit->setGeometry(0, 0, 800, 100);

generateButton->setGeometry(0, 100, 400, 20);

saveButton->setGeometry(400, 100, 400, 20);

chartWidget->setGeometry(0, 200, 800, 400);

 

// 连接信号和槽

connect(generateButton, &QPushButton::clicked, this, &MainWidget::onGenerateChart);

connect(saveButton, &QPushButton::clicked, this, &MainWidget::onSaveChart);

}

 

MainWidget::~MainWidget()

{

// 清理资源

}

void MainWidget::onGenerateChart(){

// 处理生成图表按钮点击事件

QString jsonString = inputEdit->text(); // 获取用户输入的 JSON 字符串

QJsonDocument jsonDoc = QJsonDocument::fromJson(jsonString.toUtf8()); // 解析为 JSON 文档

if (!jsonDoc.isNull())

{

chartWidget->setChartOptions(jsonDoc.object()); // 将解析后的 JSON 对象传递给 chartWidget 显示图表

}

}

void MainWidget::onSaveChart(){

// 处理保存图表按钮点击事件

QString filePath = QFileDialog::getSaveFileName(this, "Save Chart", "", "PNG Files (*.png);;JPEG Files (*.jpg *.jpeg);;BMP Files (*.bmp)"); // 弹出文件保存对话框

if (!filePath.isEmpty())

{

chartWidget->saveImage(filePath); // 将当前图表保存为指定格式的图像文件

}

}

3. 主程序入口 main.cpp

文件 main.cpp

#include <QApplication>

#include "mainwidget.h"

int main(int argc, char *argv[]){

QApplication a(argc, argv); // 创建 Qt 应用程序对象

 

MainWidget w; // 创建主窗口对象

w.show(); // 显示主窗口

 

return a.exec(); // 进入 Qt 事件循环,等待事件发生并处理

}

函数 main():

  • int main(int argc, char *argv[]):主函数入口,负责启动应用程序。
  • QApplication a(argc, argv);:创建 QApplication对象 a,管理应用程序的整体资源和事件处理。
  • MainWidget w;:创建 MainWidget类的实例 w,即主窗口对象。
  • show();:调用 show()方法显示主窗口,使用户可以看到和操作界面。
  • return a.exec();:进入 Qt 的事件循环,等待用户操作和系统事件,保持应用程序的响应性和交互性。

第四章  测试分析

柱状图

测试用例:

{

"xAxis": {

"data": ["A", "B", "C", "D", "E"]

},

"series": [

{

"type": "bar",

"data": [30, 50, 80, 40, 70]

}

]

}

运行结果:

柱状图

堆叠柱状图

测试用例:

{

"xAxis": {

"data": ["A", "B", "C", "D", "E"]

},

"series": [

{

"type": "bar",

"stack": "stack1",

"data": [30, 50, 80, 40, 70]

},

{

"type": "bar",

"stack": "stack1",

"data": [20, 40, 60, 30, 50]

}

]

}

运行结果:

堆叠柱状图

折线图

测试用例:

{

"xAxis": {

"data": ["Jan", "Feb", "Mar", "Apr", "May"]

},

"series": [

{

"type": "line",

"smooth": false,

"data": [100, 120, 90, 150, 80]

}

]

}

运行结果:

折线图

平滑曲线图

测试用例:

{

"xAxis": {

"data": ["Jan", "Feb", "Mar", "Apr", "May"]

},

"series": [

{

"type": "line",

"smooth": true,

"data": [100, 120, 90, 150, 80]

}

]

}

运行结果:

平滑曲线图

第五章 总结和体会

这是我第一次独自完成一个完整项目的开发,内容涉及多个方面,包括窗口界面的设计,用户的输入,绘制图像,保存图片,鼠标悬停显示信息,滚轮放大缩小等内容。开发过程中遇到了很多困难。刚开始我对全新的开发环境(Qt Creator)不够熟悉,编译器始终找不到文件所在的位置。查找了很多资料,才知道文件的存储路径不能存在中文。QT提供了很多全新的函数,需要花费很多的精力去学习。在窗口界面的设计上遇到了很多不懂的问题,在这部分我请教了周围的同学,终于得到了解答。在图像的绘制部分,我刚开始把Y轴的高度固定为100,但在老师的提醒下才发现这样设计不合理。于是我修改了y轴的生成过程,通过读取数据的最大值和最小值,动态地改变Y轴的标记,使生成的图像更加合理。关于鼠标悬停显示信息的部分,我在CSDN上查阅了很多资料,找到了一些类似的案例,终于完成了这一部分。
这次开发经历让我学到了很多新的知识,包括新的开发环境的使用,全新函数的调用等等,希望这些知识能够在未来帮助到我。

作者:星尘旅人
1.本网站部分素材来源于网络,仅供大家参考学习,如有侵权,请联系博主删除处理。
2.本网站一切内容不代表本站立场,并不代表本站赞同其观点和对其真实性负责。
3.版权&许可请详阅版权声明
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇
//音乐播放