您现在的位置是:网站首页> C/C++
Qt浏览器相关编程收集
- C/C++
- 2024-12-15
- 1152人已阅读
Qt浏览器相关编程收集
Qt加载QWebEngineView和js交互
Qt5之后竟然集成了chromium;测试验证技术是否可用,目前除了http音频无法播放,CPP和JS交互,包括网页调试,已完全OK;顺便吐槽一下“百度”,搜的都是一样,多少都少点东西,不是缺 qwebchannel.js 就是少了jquery-3.1.1.min.js,一般情况下肯定在本地调试! 少了jquery,本地测试js无法调用Qt提供的方法(也是公共槽的方法);
下面是主要代码 和 注意事项:
1.必须加载qwebchannel.js, 如果是本地调试还需要jquery-3.1.1.min.js;
2.打开本地调试:http://127.0.0.1:9999(Remote debugging server started successfully. Try pointing a Chromium-based browser to http://127.0.0.1:9999)
定义更新属性:
#ifndef JSCPP_H
#define JSCPP_H
#include <QObject>
#include <QMessageBox>
class JsCpp : public QObject
{undefined
Q_OBJECT
Q_PROPERTY(QString name MEMBER m_name NOTIFY sigNameChanged)
Q_PROPERTY(int age MEMBER m_age NOTIFY sigAgeChanged)
public:
JsCpp(QObject *parent = 0);
~JsCpp();
public:
void SetName(const QString name);
void SetAge(const int age);
public slots:
void ShowMsg(const QString& param1, const QString& param2);
signals:
void sigNameChanged(const QString& name);
void sigAgeChanged(int age);
private:
QString m_name;
int m_age;
};
#endif // JSCPP_H、
//>>>>>>>>>>>>>>>>>>......提供方法....的文件....................
#include "JsCpp.h"
JsCpp::JsCpp(QObject *parent)
: QObject(parent)
{undefined
m_name = "a_hua";
m_age = 16;
}
JsCpp::~JsCpp()
{undefined
}
void JsCpp::SetName(const QString name)
{undefined
m_name = name;
emit sigNameChanged(name);
}
void JsCpp::SetAge(const int age)
{undefined
m_age = age;
emit sigAgeChanged(age);
}
void JsCpp::ShowMsg(const QString& param1, const QString& param2)
{undefined
QMessageBox::information(nullptr, "Hello " + param1, "I'm here! " + param2, QMessageBox::Ok);
}
///主类中的方法///
####构造 ---- 初始化------
//打开调试..
qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "9999");
m_pWebView = new QWebEngineView(ui.widget);//
connect(m_pWebView, SIGNAL(loadFinished(bool)), this, SLOT(webLoadFinished(bool)));
//打开本地缓存.
QString _strStoreage = QString("%1/local_storage").arg(QCoreApplication::applicationDirPath());
QDir _dir(_strStoreage);
if (!_dir.exists())
_dir.mkpath(_strStoreage);
m_pWebView->page()->profile()->setPersistentStoragePath(_strStoreage);
//提供的方法类
m_pJsCpp = new JsCpp();
//创建。。。。。。调用......
m_pWebChannel = new QWebChannel();
m_pWebChannel->registerObject("js_cpp", m_pJsCpp);//注册对象
//必须设置,否则无法调用方法....
m_pWebView->page()->setWebChannel(m_pWebChannel);
//加载页面
QString _testPath = QString("%1/HtmlTest/test.html").arg(QCoreApplication::applicationDirPath());
m_pWebView->load(QUrl(_testPath));、
###调用js
m_pWebView->page()->runJavaScript("showMessage()");
==================测试页面=====================
<!DOCTYPE html>
<html>
<head>
<title>测试页面</title>
<script type="text/javascript" src="./jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="./qwebchannel.js"></script>
<meta charset="utf-8" />
<div>
<span>name:</span><input type="text" id="name"/>
<br/>
<span>age:</span><input type="text" id="age"/>
</div>
</head>
<body bgcolor="#c1d1d1">
<input type="button" value="Click" οnclick="showMessage()" ID="Button">
<input type="button" value="QtMethod" οnclick="showMessage()" ID="Button">
</body>
<script>
function showMessage()
{undefined
QtCpp.ShowMsg("111", "2222");
}
var updateName = function(text)
{undefined
$("#name").val(text);
}
var updateAge = function(text)
{undefined
$("#age").val(text);
}
new QWebChannel(qt.webChannelTransport, function(channel){undefined
var _obj = channel.objects.js_cpp;
window.QtCpp = _obj;
updateName(_obj.name);
updateAge(_obj.age);
_obj.sigNameChanged.connect(updateName);
_obj.sigAgeChanged.connect(updateAge);
});
</script>
</html>
VS中添加QWebEngineVie模块
开发环境: Qt 5.7.0 VS2015
VS2015 在生成新的工程时,会默认带了一些模块。
如果添加新的模块如何操作呢?
目前就添加 [QWebEngineView] 模块为例。
在生成新的工程时默认带的模块:
图一
第一步:
代码中添加 [QWebEngineView] 代码 然后编译
代码1
#include <QtWidgets/QMainWindow>
#include "ui_qttest001.h"
#include <QWebEngineView>
class QtTest001 : public QMainWindow
{
Q_OBJECT
public:
QtTest001(QWidget *parent = 0);
~QtTest001();
void resizeEvent(QResizeEvent*);
private:
Ui::QtTest001Class ui;
QWebEngineView* view;
};
#endif // QTTEST001_H
代码2
#include "qttest001.h"
QtTest001::QtTest001(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
view = new QWebEngineView(this);
view->load(QUrl("https://www.baidu.com/"));
view->show();
}
QtTest001::~QtTest001()
{
}
void QtTest001::resizeEvent(QResizeEvent*)
{
view->resize(this->size());
}
当编译出现错误:
如图2
此问题是没添加 WebEngineView 文件路径
$(QTDIR)\include\QtWebEngineWidgets
按照下图的步骤添加WebEngineView 就可以啦
图3
图4
第二步: 添加lib 库文件
Qt5WebEngined.lib
Qt5WebEngineWidgetsd.lib
图5
然后编译运行。
Qt使用miniblink
用Qt做项目过程中,遇到需要用到浏览器控件的项目,可能都会绕不开一个问题,那就是从Qt5.6版本开始mingw编译器的Qt构建套件,不再提供浏览器控件了,之前还可以用webkit控件,这下很多项目要么选择5.6以下版本,要么选择msvc的构建套件,而且大部分的msvc构建套件还不自带浏览器控件,也需要自己编译,只有原配的构建套件比如Qt5.9+VS2015、Qt5.12+VS2017这种搭配才可能有浏览器控件,不然就算你勾选了浏览器控件也不会安装,这样就使得很多依赖浏览器控件的项目比较被动,于是必须寻找一个轻量级的浏览器控件来替代,比如cef、miniblink,个人更倾向于miniblink,用法极其简单,依赖极其精简就一个dll,在linux和mac系统上本来qt就一直会有浏览器控件,所以也就不涉及到跨平台的问题,所以miniblink暂支持windows的缺点也就不算缺点了。
miniblink是一个追求极致小巧的浏览器内核项目,全世界第三大流行的浏览器内核控件。其基于chromium最新版内核,去除了chromium所有多余的部件,只保留最基本的排版引擎blink。miniblink保持了10M左右的极简大小,是所有同类产品最小的体积,同时支持windows
qt+miniblink用法步骤:
- 第一步:调用wkeSetWkeDllPath函数加载dll文件路径,一个项目只需要执行一次。
- 第二步:调用wkeInitialize初始化动态库,一个项目只需要执行一次。
- 第三步:调用wkeCreateWebWindow创建一个浏览器控件,传入句柄。
- 第四步:调用wkeOnLoadingFinish注册回调加载完成信号,有需要才注册。
- 第五步:调用wkeJsBindFunction注册回调接收数据的方法,一定要放在这里在网页加载前执行。
- 第六步:调用wkeLoadURL加载网址、wkeLoadFile加载网页文件、wkeLoadHtmlWithBaseUrl加载网页内容。
- 第七步:调用wkeRunJS执行js函数,超级简单。
- 第八步:调用wkeFinalize释放资源,只要执行一次,在整个项目结束的时候。
qt+miniblink完整demo开源地址:
https://gitee.com/feiyangqingyun/QWidgetDemo/tree/master/miniblink
https://github.com/feiyangqingyun/QWidgetDemo/tree/master/miniblink
相关代码
#ifndef MINIBLINK_H
#define MINIBLINK_H
#include <QWidget>
#include "wke.h"
class miniblink : public QWidget
{
Q_OBJECT
public:
explicit miniblink(QWidget *parent = 0);
//初始化资源
static void init();
//释放资源
static void release();
protected:
//设置浏览器控件自动适应大小
void resizeEvent(QResizeEvent *);
private:
//浏览器控件对象
wkeWebView webView;
signals:
//网页载入完成
void loadFinished(bool ok);
//收到网页发出来的数据
void receiveDataFromJs(const QString &type, const QVariant &data);
public:
//给回调用的函数
void loadFinish(bool ok);
void receiveData(const QString &type, const QVariant &data);
public slots:
//加载网址或者本地文件
void load(const QString &url, bool file = false);
//加载html内容
void setHtml(const QString &html, const QString &baseUrl);
//执行js函数
void runJs(const QString &js);
};
#endif // MINIBLINK_H
#include "miniblink.h"
#include "qapplication.h"
#include "qdebug.h"
void onLoadingFinish(wkeWebView, void *param, const wkeString, wkeLoadingResult result, const wkeString)
{
//qDebug() << "onLoadingFinish" << result;
//在注册函数的地方就已经传入了类指针
miniblink *widget = (miniblink *)param;
//0 = WKE_LOADING_SUCCEEDED, 1 = WKE_LOADING_FAILED, 2 = WKE_LOADING_CANCELED
widget->loadFinish(result == 0);
}
jsValue WKE_CALL_TYPE objName_receiveData(jsExecState es, void *param)
{
if (0 == jsArgCount(es)) {
return jsUndefined();
}
//挨个取出参数,设定的通用方法,只有两个参数
jsValue arg0 = jsArg(es, 0);
jsValue arg1 = jsArg(es, 1);
if (!jsIsString(arg0)) {
return jsUndefined();
}
//在注册函数的地方就已经传入了类指针
miniblink *widget = (miniblink *)param;
QString type = QString::fromStdString(jsToString(es, arg0));
QVariant data = QString::fromStdString(jsToString(es, arg1));
widget->receiveData(type, data);
return jsUndefined();
}
miniblink::miniblink(QWidget *parent) : QWidget(parent)
{
//第一步先初始化动态库
init();
//第二步初始化浏览器控件
//创建一个浏览器控件,放入句柄
webView = wkeCreateWebWindow(WKE_WINDOW_TYPE_CONTROL, (HWND)this->winId(), 0, 0, this->width(), this->height());
//关联完成信号
wkeOnLoadingFinish(webView, onLoadingFinish, this);
//设置浏览器控件可见
wkeShowWindow(webView, TRUE);
//注册通用的接收数据的方法,一定要放在这里在网页加载前执行
wkeJsBindFunction("objName_receiveData", objName_receiveData, this, 2);
}
void miniblink::init()
{
//全局只需要初始化一次
static bool isInit = false;
if (!isInit) {
isInit = true;
//不同的构建套件位数加载不同的动态库
#ifdef Q_OS_WIN64
QString file = qApp->applicationDirPath() + "/miniblink_64.dll";
#else
QString file = qApp->applicationDirPath() + "/miniblink.dll";
#endif
const wchar_t *path = reinterpret_cast<const wchar_t *>(file.utf16());
wkeSetWkeDllPath(path);
bool ok = wkeInitialize();
qDebug() << QString("init miniblink %1").arg(ok ? "ok" : "error");
}
}
void miniblink::release()
{
wkeFinalize();
}
void miniblink::resizeEvent(QResizeEvent *)
{
wkeResize(webView, this->width(), this->height());
}
void miniblink::loadFinish(bool ok)
{
emit loadFinished(ok);
}
void miniblink::receiveData(const QString &type, const QVariant &data)
{
emit receiveDataFromJs(type, data);
}
void miniblink::load(const QString &url, bool file)
{
const char *temp = url.toLocal8Bit().data();
if (file) {
wkeLoadFile(webView, temp);
} else {
wkeLoadURL(webView, temp);
}
}
void miniblink::setHtml(const QString &html, const QString &baseUrl)
{
wkeLoadHtmlWithBaseUrl(webView, html.toLocal8Bit().data(), baseUrl.toLocal8Bit().data());
}
void miniblink::runJs(const QString &js)
{
wkeRunJS(webView, js.toLocal8Bit().data());
}
C++调用JavaScript
和wke一样,wkexe也可以通过相同的wkeRunJS函数调用JavaScript代码,但不同的是,如果C++代码想要获得JavaScript的返回值,需要在调用的JS代码前加上return:
jsRet = wkeRunJS(gWkeWebView, "return funcforcplusplus(\"\xe4\xbd\xa0\xe5\xa5\xbd ABCDEFG\")");
jsRetStr = jsToStringW(wkeGlobalExec(gWkeWebView), jsRet);
MessageBox(hWnd, jsRetStr, L"runJS返回", 0);
JavaScript调用C++
同wke一样,JS调用C++代码也需要绑定,在RunApplication函数中CreateWebWindow之前添加如下代码:
jsBindFunction("msgBox", js_msgBox, 2);//JS调用C++
1
同时在app.cpp文件中添加:
//JS调用C++
jsValue JS_CALL js_msgBox(jsExecState es)
{
const wchar_t* text = jsToStringW(es, jsArg(es, 0));
const wchar_t* title = jsToStringW(es, jsArg(es, 1));
MessageBox(NULL, text, title, 0);
return jsStringW(es, L"C++返回字符串");
}
这里有个BUG需要注意,miniblink的jsToStringW函数目前只能处理JavaScript传入的字符串参数(作者将在下步更新代码时修正),如果前端msgBox函数传入的参数不是字符串类型,那么会得到空值
附上前端测试用的HTML代码如下:
<!DOCTYPE html>
<html xmlns="/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>WKE Test Web Page</title>
<script>
function funcforcplusplus(instr){
document.getElementById('result').value=instr;
return navigator.userAgent;
//return "JavaScript Return 返回啦";
}
</script>
</head>
<body>
<p>WKE Test Web Page</p>
<a href='#' onclick="document.getElementById('result').value=msgBox('TEST Function from JS to Cpp','来自Javascript的调用');">LINK</a>
<textarea rows='6' cols='36' id='result'>hello</textarea>
</body>
</html>
QT5.5老版本使用webview
.pro添加
QT += core gui webkitwidgets
添加头文件
#include <QtWebKitWidgets/QWebView>
QT使用webengineview
可能是由于内容开始是网络地址(http://...)完整的英文词截取后不能换行造成 为避免代码造成手机端排版的混乱,可适当增加文字描述,将代码往后推移
添加Debug需要的库:qtmaind.lib;Qt5Cored.lib;Qt5Guid.lib;Qt5Widgets.lib;Qt5WebViewd.lib;Qt5WebEngineWidgetsd.lib;%(AdditionalDependencies)
包含的目录
.\GeneratedFiles;.;$(QTDIR)\include;.\GeneratedFiles\$(ConfigurationName);$(QTDIR)\include\QtCore;$(QTDIR)\include\QtGui;$(QTDIR)\include\QtWidgets;%(AdditionalIncludeDirectories)
附加库目录:$(QTDIR)\lib;%(AdditionalLibraryDirectories)
上一篇:Qt Creator添加第三方头文件和类库MQTT(经验篇)
下一篇:QT学习总结