在之前的一篇博客《EChart配置方法(数据可视化解决方案)》已经很详细的介绍了 EChart,这篇我给大家介绍一下再Qt5中使用QChart进行数据可视化显示,并通过截图的方式保存显示图片。
Qt作为一款广泛应用的图形化API在工程性和可移植性上做得非常好,其自身自带的QChart(QCart模块在Qt5中才开始配置到免费版本)也能做一部分的数据可视化,但相对于EChart来说简直是小巫见大巫了。(QChart应用示意如图1所示,ECahrt实例直接去官网看:https://www.echartsjs.com/examples/)而EChart作为JS库在跨平台上也毫不逊色于Qt,所以不用担心在其他平台的配置。将EChart嵌入到Qt5中可使项目更有工程性(画个图还要打开个网页或运行个黑框?)。
Qt中有Web显示控件QWebEngineView,而EChart只作为一个本地网页载入到QWebEngineView中就行。
Qt的QWebEngineView中有QWebEngineView->page()->runJavaScript(“function(data)”)对Js函数进行调用。
数据可以用Json格式传参方式到data中。(Json处理Qt中有QJsonObject等处理类)
EChart在网页显示上其实是有图像保存按钮的,但是它是以下载方式将图片进行保存的,而Qt5中响应网页中的下载Url需要用到WebChannel(反正比截图麻烦)。
5.1编写Html文件
方法和配置项都已经解释得非常清楚了这里就不再赘述了。直接上代码:(如果你直接复制记得将src=""改为自己的库路径)
EChartTest.html
ECharts
5.2构建框架
如图2所示,这个Demo有导入TXT文件、显示折线图、曲线图、柱状图、保存图像、设置保存路径功能。
5.3构建代码框架并编写(直接上代码了)
EchartInQt5.h
#pragma once
#include
#include "ui_EchartInQt5.h"
#include
#include
#include
#include
#include
#include
#include
class EchartInQt5 : public QMainWindow
{
Q_OBJECT
public:
EchartInQt5(QWidget *parent = Q_NULLPTR);
public slots:
void on_inputDataBtn_clicked(); //导入数据槽函数
void on_lineChartBtn_clicked(); //折线图显示槽函数
void on_curvChartBtn_clicked(); //曲线图显示槽函数
void on_barChartBtn_clicked(); //柱状图显示槽函数
void on_saveImgBtn_clicked(); //保存图片槽函数
void on_browseBtn_clicked(); //设置图片保存路径槽函数
private:
Ui::EchartInQt5Class ui;
QWebEngineView *pEngView; //Web显示引擎
QJsonArray dataLine; //传入Json数据
QString saveImgName; //图片保存名称
};
EchartInQt5.cpp
#include "EchartInQt5.h"
EchartInQt5::EchartInQt5(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); //设置应用程序用高分辨率显示
this->setWindowTitle(QString::fromLocal8Bit("Qt5中用EChart进行数据可视化Demo"));
//设置应用标题
pEngView = new QWebEngineView(); //创建QWebEngineView实例
ui.webLayout->addWidget(pEngView); //将QWebEngineView加入到Layout中
pEngView->load(QUrl(QString::fromLocal8Bit("E:/C++/EchartInQt5/Win32/Debug/EChartTest.html"))); //载入EChart测试网页
pEngView->show(); //显示网页
ui.pathLEdt->setText(QCoreApplication::applicationDirPath()); //设置保存位置为项目所在位置
ui.lineChartBtn->setDisabled(true); //设置折线图按钮不可按
ui.curvChartBtn->setDisabled(true); //设置曲线图按钮不可按
ui.barChartBtn->setDisabled(true); //设置柱状图按钮不可按
}
/****************************************************
*函数名:导入数据槽函数
*功 能:将稳步数据导入内存
*输 入:无
*输 出:无
*****************************************************/
void EchartInQt5::on_inputDataBtn_clicked()
{
//打开文件
ui.lagLab->clear(); //清空日志输出显示栏
QString path = QFileDialog::getOpenFileName(this, "Open File", "", "TXT File(*.txt)");
QFile textData(path); //数据文件
QString lineStr; //读取行
QStringList dataTemp; //临时数据
if (!textData.open(QIODevice::ReadOnly))
{
ui.lagLab->setText(QString::fromLocal8Bit("导入文件失败!"));
return;
}
while (!textData.atEnd())
{
lineStr = textData.readLine(); //按行读取数据
dataTemp = lineStr.split(' ', QString::SplitBehavior::SkipEmptyParts);
if (dataTemp.count() > 0)
{
dataLine.append(dataTemp.at(0).toFloat()); //将读取到的数据转为float加入到Json中
}
}
textData.close(); //关闭文件
ui.lineChartBtn->setDisabled(false); //设置折线图按钮可按
ui.curvChartBtn->setDisabled(false); //设置曲线图按钮可按
ui.barChartBtn->setDisabled(false); //设置柱状图按钮可按
ui.lagLab->setText(QString::fromLocal8Bit("导入文件成功!"));
}
/****************************************************
*函数名:折线图显示槽函数
*功 能:将数据以Json格式传入JS函数并显示折线图
*输 入:无
*输 出:无
*****************************************************/
void EchartInQt5::on_lineChartBtn_clicked()
{
ui.lagLab->clear(); //清空日志输出显示栏
QJsonObject jsonObject; //构建用于传输数据的json对象
saveImgName = QString::fromLocal8Bit("折线图"); //设置保存图片名称
jsonObject.insert("lineData", dataLine); //传入读取数据
QString str = QString(QJsonDocument(jsonObject).toJson()); //将Json格式转为QString
str = str.remove("\t").remove('\n'); //移除多余的制表和换行
str.replace(QRegExp("\""), "\\\""); //因为转为字符串后需要两次转译
QString strVal = QString("lineChart(\"%1\");").arg(str); //转为标准字符串
pEngView->page()->runJavaScript(strVal); //调用js中的函数
pEngView->show(); //显示网页
}
/****************************************************
*函数名:曲线图显示槽函数
*功 能:将数据以Json格式传入JS函数并显示曲线图
*输 入:无
*输 出:无
*****************************************************/
void EchartInQt5::on_curvChartBtn_clicked()
{
ui.lagLab->clear(); //清空日志输出显示栏
QJsonObject jsonObject; //构建用于传输数据的json对象
saveImgName = QString::fromLocal8Bit("曲线图"); //设置保存图片名称
jsonObject.insert("lineData", dataLine); //传入读取数据
QString str = QString(QJsonDocument(jsonObject).toJson()); //将Json格式转为QString
str = str.remove("\t").remove('\n'); //移除多余的制表和换行
str.replace(QRegExp("\""), "\\\""); //因为转为字符串后需要两次转译
QString strVal = QString("curvChart(\"%1\");").arg(str); //转为标准字符串
pEngView->page()->runJavaScript(strVal); //调用js中的函数
pEngView->show(); //显示网页
}
/****************************************************
*函数名:柱状图显示槽函数
*功 能:将数据以Json格式传入JS函数并显示柱状图
*输 入:无
*输 出:无
*****************************************************/
void EchartInQt5::on_barChartBtn_clicked()
{
ui.lagLab->clear(); //清空日志输出显示栏
QJsonObject jsonObject; //构建用于传输数据的json对象
saveImgName = QString::fromLocal8Bit("柱状图"); //设置保存图片名称
jsonObject.insert("lineData", dataLine); //传入读取数据
QString str = QString(QJsonDocument(jsonObject).toJson()); //将Json格式转为QString
str = str.remove("\t").remove('\n'); //移除多余的制表和换行
str.replace(QRegExp("\""), "\\\""); //因为转为字符串后需要两次转译
QString strVal = QString("barChart(\"%1\");").arg(str); //转为标准字符串
pEngView->page()->runJavaScript(strVal); //调用js中的函数
pEngView->show(); //显示网页
}
/****************************************************
*函数名:保存图片槽函数
*功 能:以截图方式保存图片
*输 入:无
*输 出:无
*****************************************************/
void EchartInQt5::on_saveImgBtn_clicked()
{
ui.lagLab->clear();
QPixmap p = this->grab(QRect(30, 70, 661, 441)); //设置为Web显示位置geometry位置对于Layout并不好用哪位网友发现了解决方法请在下方评论中给出
saveImgName = ui.pathLEdt->text() + "/" + saveImgName + ".png"; //设置保存位置
QFile file(saveImgName); //如果存在文件则删除原有文件
if (file.exists())
file.remove();
file.close();
if (p.save(saveImgName, "png")) //保存截图
{
ui.lagLab->setText(QString::fromLocal8Bit("保存成功!"));
}
else
{
ui.lagLab->setText(QString::fromLocal8Bit("保存失败!"));
}
}
/****************************************************
*函数名:浏览文件夹槽函数
*功 能:选择保存图片的位置(默认路径为工程路径)
*输 入:无
*输 出:无
*****************************************************/
void EchartInQt5::on_browseBtn_clicked()
{
QString path = QFileDialog::getExistingDirectory(this, QString::fromLocal8Bit("选择保存路径"), "/");
if (path != NULL)
{
ui.pathLEdt->setText(path);
}
}
测试数据.txt
12.5
13.6
11.2
10.5
8.3
7.2
9.5
10.6
11.2
12.6
14.6
12.3
11.2
15.6
11.3
10.2
16.5
15.3
16.3
17.5
19.5
显示结果:
工程下载地址:https://github.com/HuangYudong/EChartInQt5