tags: Qt javascript qwebchannel QWebEngineView
由来
在Qt平台上有很多很棒的图表控件,比如QWT,QCustomPlot,以及Qt5.5以后自带的QChart,但与JS网页端的各种绚丽效果控件比,还是差了不少。这次就是打算把百度出品的EChart控件应用在Qt端。
而在这样的跨平台调用中,很多文章都写的含糊其词,让人晕头转向,于是写一篇记录下最清晰最简单的调用过程。
工具
Qt5.5以上,在安装时选择上QWebEngine
同时必须选择基于VS编译器的Qt版本,基于MinGW的编译不能通过,原因可能是GCC不支持QWebEngine。
工程配置
1.新建基于Widget的工程
2..pro
里加入
QT += core gui webenginewidgets webchannel
.h
里引用头文件
#include <QWebEngineView>
#include <QtWebChannel>
3.从QObjec派生一个类
class WebClass : public QObject
{
Q_OBJECT
public slots:
void jscallme()
{
QMessageBox::information(NULL, "jscallme", "jscallme");
}
};
MainWindow
的类里声明变量
QWebEngineView *webView = nullptr;
QWebChannel *webChannel = nullptr;
MainWindow
的.cpp
里初始化变量
webView = new QWebEngineView(parent);
webView->load(QUrl::fromLocalFile("D:\\Code\\EChartTest\\test.html"));
mainLayout->addWidget(webView);
webChannel = new QWebChannel;
WebClass *webobj = new WebClass();
webChannel->registerObject("webobj", webobj);
webView->page()->setWebChannel(webChannel);
4.用文本编辑器新建一个test.html
文件,内容写:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title></title>
</head>
<body>
<script src="qwebchannel.js"></script>
<script type="text/javascript">
new QWebChannel(qt.webChannelTransport,
function(channel){
var webobj = channel.objects.webobj;
window.foo = webobj;
webobj.jscallme();
});
</script>
</body>
</html>
5.将Qt目录"C:\Qt\Qt5.12.1\Examples\Qt-5.12.1\webchannel\shared"
下的qwebchannel.js
文件拷贝到上面的test.html
目录下
6.好了,Qt端 运行程序。
7.结果为HTML的程序调用了C++的函数。
JS传递给C++
再进一步吧/
1.修改
void jscallme()
为
void jscallme(const QString &text)
{
QMessageBox::information(NULL, "jscallme", text);
}
2.HTML端修改webobj.jscallme();
为webobj.jscallme('中文调用');
3.右键点击下Qt端的程序,reload后,弹出结果
4.每次都这样通过C++端函数赋值太麻烦了,可以直接在JS里给C++端变量赋值就好了。也简单,修改派生的类。
class WebClass : public QObject
{
Q_OBJECT
Q_PROPERTY(QString content MEMBER m_content)
public slots:
void jscallme()
{
QMessageBox::information(NULL, "jscallme", m_content);
}
private:
QString m_content;
}
5.修改HTML端
new QWebChannel(qt.webChannelTransport,
function(channel){
var webobj = channel.objects.webobj;
window.foo = webobj;
webobj.content = 'sdfef中文';
webobj.jscallme();
});
6.reload下Qt端程序,结果符合预期
c++传递到JS
1.修改派生类
Q_PROPERTY(QString content MEMBER m_content NOTIFY contentChanged)
2.修改HTML端
<script type="text/javascript">
var updateattribute=function(text)
{
document.write(text);
}
new QWebChannel(qt.webChannelTransport,
function(channel){
var webobj = channel.objects.webobj;
window.foo = webobj;
webobj.contentChanged.connect(updateattribute);
});
</script>
3.Qt程序上放个按钮,按钮按下事件里写:
webobj->setProperty("content", "453453453");
4.Qt程序上的webview会刷新出结果.
传递自定义结构数据
上面的例子里都是传递基本类型,如果我自己定义的数据类型怎么办呢?比如
struct Data
{
int a;
double b;
QString str;
};
可惜花了一整天也没搞清楚怎么传递这样的结构,各种宏绕的头晕,有明白的同学请留言指教。
不过我却发现了通过QJsonObject
来传递的简单方法,将上面的结构用QJSonObject
重写就可以了,具体代码如下
Qt端类声明
class WebClass : public QObject
{
Q_OBJECT
Q_PROPERTY(QJsonObject jsonData MEMBER m_jsonData NOTIFY dataChanged)
public:
signals:
void dataChanged(const QJsonObject &jsonData);
private:
QJsonObject m_jsonData;
};
Qt端主函数
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent)
{
btn = new QPushButton("..");
connect(btn, &QPushButton::clicked, this,
[&]()
{
QJsonObject json;
json["a"] = 2;
json["b"] = 3.336;
json["c"] = "sdef";
webobj->setProperty("jsonData", json);
});
QVBoxLayout *layout = new QVBoxLayout;
layout->addWidget(btn, 1, Qt::AlignLeft);
webView = new QWebEngineView(parent);
webView->load(QUrl::fromLocalFile("D:\\Code\\JS\\test.html"));
layout->addWidget(webView);
QWidget *w = new QWidget;
w->setLayout(layout);
setCentralWidget(w);
webChannel = new QWebChannel;
webobj = new WebClass();
webChannel->registerObject("webobj", webobj);
webView->page()->setWebChannel(webChannel);
setMinimumSize(800, 600);
}
HTML端代码如下
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<!-- 引入 ECharts 文件 -->
<script src="D:/Code/JS/Echart/echarts.min.js"></script>
</head>
<p id="x">x:</p>
<p id="y">y:</p>
<body>
<script src="qwebchannel.js"></script>
<script type="text/javascript">
new QWebChannel(qt.webChannelTransport, function (channel) {
var webobj = channel.objects.webobj;
webobj.dataChanged.connect(function (arg) {
x.innerHTML = "x:" + arg.x ;
y.innerHTML = "y:" + arg.y.toFixed(4);
});
});
</script>
</body>
</html>
好了,自定义结构传递效果如下
更进一步
在下一步里直接用Qt生成随机数,通过QWebChannel发送到JS端,调用echarts控件显示曲线。
Qt调用Echarts显示动态过程曲线