QT+ECharts实现绘图

(QT+Web使用摸索记录)

2019年11月8日 09点55分,这是我第一次在csdn写东西,肯定有很多逻辑问题,但是没关系,我就当这是写给我自己看的,(这就是写给我自己看的)。。。

为什么使用Qt+web

之前一直在qt环境中绘制2d的图表,包括折线图、柱状图等,控件也使用过qwt、qcustomplot、qtchart等,它们之间的优劣不做阐述,不是本次的重点。
目前的项目使用qwt绘制频谱图和曲线图,但客户突然又要3d的频谱图,并且是要那种不停累加的效果,有点像海浪的样子。因为之前从来没有接触过3d,就在所有已知的控件中查找方法,qwt使用起来总感觉不好用,或许是我技术不行吧;qcustomplot则直接就不支持3d绘图;qtchart效率低是出了名的。这时候突然想起之前看到过的一个叫highcharts的控件(大概是一年前),当时就觉得很厉害,对比这前的控件,简直无敌,不仅优美而且功能齐全。
遂去百度搜索相关资料,卧槽,js+html是什么鬼???从来没有接触过(看题目就知道,我是qt c++啊),不仅资料少还是英语,摊牌了,不装了,真的不会!!但是在我搜索的过程中,发现了另一个神器,就是今天的主角《ECharts》,百度开源、中文文档、大量示例,爷笑了,这就是我要的呀!!!

怎么用

在使用过程中,发现了两种使用方法:
第一种:通过信号槽连接qt与js,使用QWebEngineView+QWebChannel+QObject实现:

  1. 第一步 ,在qt的pro文件中添加QT += webenginewidgets webchannel这两个模块;
  2. 第二步,添加继承于QObject的类,该类用于html中的js与qt后端数据的交互:
class WebClass : public QObject
{
	Q_OBJECT

public:
	WebClass(QObject *parent);
	~WebClass();
	void setoption(qreal x, qreal y)//qt端调用
	{
		emit sig_option(x, y);//将信号发送给html
	}
signals:
	void sig_option(qreal x, qreal y);//发送给html的信号

private:
};
  1. 第三步,在qt界面中,实例化QWebChannel和QWebEngineView对象:
头文件
class charts : public QMainWindow
{
	Q_OBJECT

public:
	charts(QWidget *parent = Q_NULLPTR);
	~charts()
	{
	}
protected:
private:
	WebClass* m_WebClass = nullptr;
	QWebChannel* m_WebChannel = nullptr;
	QWebEngineView* m_View = nullptr;
};
源文件
charts::charts(QWidget *parent)
	: QMainWindow(parent)
{
	m_View = new QWebEngineView(this);	//构建视图
	this->setMinimumSize(500, 350);
	this->setCentralWidget(m_View);
	m_WebChannel = new QWebChannel(this);//构建通道
	m_WebClass = new WebClass(this);//构建传输方法
	m_WebChannel->registerObject(QStringLiteral("WebClass"), m_WebClass);//将方法添加到管道中
	m_View->page()->setWebChannel(m_WebChannel);//将管道设置到页面里
	m_View->setQUrl(QUrl(QStringLiteral("qrc:/Resources/echarts.html")));//在视图中,加载网页
}

4.第四步,从Echart官网下载echarts.js文件,在qt的安装路径中,找到qwebchannel.js文件。并将这两个文件添加进qt的资源文件中。
5. 第五步,修改html文件,最重要的一步就是获取管道中的方法对象:




    
    
    			//资源文件路径
    


    

自此,所有工作已经完成。完整代码,后续给出。

第二种:由于在使用过程中,需要一次性,向图表中加入大量数据,使用信号槽难免会有性能影响,经过查找,发现了一种,更加简单的方法:直接在qt端,调用js中的函数进行数据交互:
1.第一步,修改qt文件,去除WebClass方法类和QWebChannel管道类

头文件:

class charts : public QMainWindow
{
	Q_OBJECT

public:
	charts(QWidget *parent = Q_NULLPTR);
	~charts()
	{
		this->disconnect();
	}
protected:
	void resizeEvent(QResizeEvent* event);
private:
	QWebEngineView* m_View = nullptr;
};

2.第二步,将数据转化为json字符串,进行传输:
源文件:

charts::charts(QWidget *parent)
	: QMainWindow(parent)
{
	m_View = new QWebEngineView(this);
	this->setMinimumSize(500, 350);
	this->setCentralWidget(m_View);
	m_View->load(QUrl(QStringLiteral("qrc:/Resources/echarts.html")));

	//通过序列化,将数据转换为json字符串,在通过调用js脚本,进行数据传输
	QJsonObject seriesData;
	QJsonArray x,y;
	for (int index = 0; index < 10000; ++index)
	{
		x.append(index);
		y.append(qrand()%100);
	}
	seriesData.insert("x", x);
	seriesData.insert("y", y);
	QString optionStr = QJsonDocument(seriesData).toJson();
	QString js = QString("update(%1)").arg(optionStr);//”update“ -- js中的函数名称
	m_View->page()->runJavaScript(js);
}

3.第三步,修改html文件,在js中实现update方法:




    
    
    
    


    

完事!!!

特别注意!!!特别注意!!!特别注意!!!,上述所有功能均能在Debug模式下实现,但是在release模式下,js脚本文件会被自动编译为.cpp文件,导致html无法获取js正确路径,通过查阅大量资料,发现在qt官方文档中给出了解决方案
JavaScript Files in Qt Resource Files
If your WebEngine application is built using the Qt Quick Compiler, and the application ships JavaScript files inside .qrc resources, and these files are supposed to be loaded from inside HTML pages, make sure to specify the resource files in a QTQUICK_COMPILER_SKIPPED_RESOURCES qmake variable inside your project. This prevents the Qt Quick Compiler from trying to generate C++ code for the corresponding JavaScript code, as well as removing the original JavaScript code from the Qt resources file, which would lead to broken HTML pages. For example:
在pro资源文件中,添加这一行:
QTQUICK_COMPILER_SKIPPED_RESOURCES += xxxx.qrc

你可能感兴趣的:(qt)