想要在qt中加载网页到widget中,需要使用到QWebEngineView,想要和网页端通信可以使用到QWebChanel。当然还可以使用QWebSocket。
QWebEngineView使用方法如下:
m_pWebView = new QWebEngineView(this);
QString htmlPath = QApplication::applicationDirPath()+"/test.html";
QFile file(htmlPath);
if (!file.exists())
return;
m_pWebView->load(QUrl("file:///" + htmlPath));
使用QWebChanel方法如下:
m_pWebChannel = new QWebChannel(this);
m_pWebChannel->registerObject(QString("qtui"), this);//qtui这个标识是可以随意定义,只要web端中html也是使用qtui就能通讯上了。
m_pWebView->page()->setWebChannel(m_pWebChannel);
QWebChanel和web的通讯方法如下:
1、发信号,web负责连接。
2、创建槽函数,让web自己调用这个槽。
3、调用runJavaScript()这个接口,直接调用web定义的函数即可,且它支持同步异步发送。
4、头文件创建对象属性,让web端直接使用这个对象,我们就能从这个对象中拿到web赋予的值。如下:m_content。
代码示例1如下:
头文件
#ifndef WEBTEST_H
#define WEBTEST_H
#include <QtWidgets>
#include <QWebEngineView>
#include <QWebChannel>
class WebTest : public QWidget
{
Q_OBJECT
public:
WebTest(QWidget *parent = nullptr);
private:
void initUi();
void initConncetion();
// 加载html文件
void loadHtml();
// 获取js函数返回值
QString getJsRetString();
public slots:
void recieveJsMessage(const QString& jsMsg);
private:
QWebEngineView *m_pWebView;
QWebChannel* m_pWebChannel;
QPushButton* m_callJSBtn;
QPushButton* m_getJsRetBtn;
QLabel* m_lab;
};
#endif // WEBTEST_H
cpp文件
#include "webtest.h"
#include <QFile>
#include <QCoreApplication>
WebTest::WebTest(QWidget *parent) : QWidget(parent)
{
initUi();
initConncetion();
}
void WebTest::initUi()
{
m_callJSBtn = new QPushButton(QStringLiteral("调用JS"),this);
m_getJsRetBtn = new QPushButton(QStringLiteral("获取JS返回值"),this);
m_lab = new QLabel(this);
m_pWebView = new QWebEngineView(this);
m_pWebChannel = new QWebChannel(this);
QGridLayout* lay = new QGridLayout();
lay->addWidget(m_pWebView,0,0,5,5);
lay->addWidget(m_callJSBtn,0,5,1,1);
lay->addWidget(m_getJsRetBtn,1,5,1,1);
lay->addWidget(m_lab,2,5,1,1);
this->setLayout(lay);
m_callJSBtn->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
m_getJsRetBtn->setSizePolicy(QSizePolicy::Preferred,QSizePolicy::Preferred);
m_lab->setStyleSheet("background:rgba(0,0,155,100)");
loadHtml();
m_pWebChannel->registerObject(QString("qtui"), this);
m_pWebView->page()->setWebChannel(m_pWebChannel);
}
void WebTest::initConncetion()
{
// 调用JS
connect(m_callJSBtn, &QPushButton::clicked, [&]()
{
QString jsStr = QString("addCircle()");
m_pWebView->page()->runJavaScript(jsStr);//异步调用
});
// 获取JS返回值
connect(m_getJsRetBtn, &QPushButton::clicked, [&]()
{
auto str = getJsRetString();
m_lab->setText(str);
});
}
//加载地图
void WebTest::loadHtml()
{
QString htmlPath = QCoreApplication::applicationDirPath() + "/BMap.html";
QFile file(htmlPath);
if (!file.exists())
{
return;
}
m_pWebView->load(QUrl("file:///" + htmlPath));
}
//获取web端返回值
QString WebTest::getJsRetString()
{
QEventLoop loop;
QString jsStr = "getInfo();";
QString retStr{};
// 同步通过loop循环等到回调上来数据再继续
m_pWebView->page()->runJavaScript(jsStr, [&](const QVariant &v)
{
retStr = v.toString();
loop.quit();
});
loop.exec();
return retStr;
}
//接收来自webhtml的消息
void WebTest::recieveJsMessage(const QString& jsMsg)
{
m_lab->setText(jsMsg);
}
html文件
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
body, html,#allmap {width: 100%;height: 100%;overflow: hidden;margin:0;font-family:"微软雅黑";}
</style>
<script type="text/javascript" src="http://api.map.baidu.com/api?v=2.0&ak=AEdSNAu4uSOTMaQgiuFizrkNwheoSVHF"></script>
<script src="./qwebchannel.js"></script>
<title>Web测试</title>
</head>
<body>
<div id="allmap"></div>
</body>
</html>
<script type="text/javascript">
// 百度地图API功能
var map = new BMap.Map("allmap"); // 创建Map实例
map.centerAndZoom(new BMap.Point(116.404, 39.915), 11); // 初始化地图,设置中心点坐标和地图缩放级别
//添加地图类型控件
map.addControl(new BMap.MapTypeControl({
mapTypes:[
BMAP_NORMAL_MAP,
BMAP_HYBRID_MAP
]}));
map.setCurrentCity("北京"); // 设置地图显示的城市 此项是必须设置的
map.enableScrollWheelZoom(true); //开启鼠标滚轮缩放
// 添加一个圆形覆盖物
function addCircle()
{
var point = new BMap.Point(116.404, 39.915);
var circle = new BMap.Circle(point, 6000, { strokeColor: "red", strokeWeight: 5, strokeOpacity: 0.3 }); //创建圆
map.addOverlay(circle); //增加圆
// 给这个circle添加一个点击事件
circle.addEventListener("click", function (event)
{
new QWebChannel(qt.webChannelTransport, function (channel) {
var qtui = channel.objects.qtui;
qtui.recieveJsMessage("你点我干啥!");
})
});
}
// 获取字符串文本
function getInfo()
{
var textString = "HTML js返回值";
return textString;
}
</script>
代码示例2如下:
头文件
#ifndef TESTINTERFACE_H
#define TESTINTERFACE_H
#include <QObject>
#include <QMessageBox>
class testinterface : public QObject
{
Q_OBJECT
Q_PROPERTY(QString content MEMBER m_content)
public:
testinterface();
void send(int type,QString msg);
signals:
void dataChanged(QString content);
void sendData(QString content);
public slots:
void jscallme(QString msg);
private:
QString m_content;
};
#endif // TESTINTERFACE_H
cpp文件
#include "testinterface.h"
testinterface::testinterface()
{
}
void testinterface::send(int type, QString msg)
{
if (type == 0)
{
emit dataChanged(msg);
}
else if (type == 1)
{
emit sendData((msg));
}
}
void testinterface::jscallme(QString msg)
{
QMessageBox::information(NULL, "title", QString(QStringLiteral("测试传参:%1\n测试变量:%2")).arg(msg).arg(m_content));
}
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">
var recvData=function(text)
{
document.write("测试2:"+text+"</br>");
}
var updateattribute=function(text)
{
document.write("测试1:"+text+"</br>");
}
new QWebChannel(qt.webChannelTransport,
function(channel){
var testinterface = channel.objects.testinterface;
window.foo = testinterface;
testinterface.content="恭喜发财";
testinterface.jscallme("新年快乐");
testinterface.dataChanged.connect(updateattribute);
testinterface.sendData.connect(recvData);
});
</script>
</body>
</html>