Qt與QWebEngineView交互完整參考示例代碼
前言
最近剛好需要做一個(gè)Qt與Webview的交互,順便寫(xiě)下整個(gè)的交互流程,給需要的各位參考學(xué)習(xí)。后面會(huì)補(bǔ)充,Qt上應(yīng)用其他Web上的開(kāi)源圖標(biāo)類(lèi)的組件js庫(kù),例如EChart,vis.js等,通過(guò) Qt+ +JavaScript+ QWebChannel +QWebEngineView 的組合,很多酷炫的效果都可以很方便的做出來(lái)。
1:Qt的Web 引擎與 WebView交互歷史變更
Qt 5.6 引入了 Qt WebEngine 模塊:
在過(guò)去,Qt 使用的是 Qt WebKit 作為其 Web 引擎。但自 Qt 5.6 版本開(kāi)始,Qt 引入了基于 Chromium 的新的 Web 引擎,稱(chēng)為 Qt WebEngine。這個(gè)改變帶來(lái)了更好的性能、更好的 HTML5 和 CSS3 支持以及更好的安全性。
QWebView 被 QWebEngineView 替代:
在使用 Qt WebKit 時(shí),開(kāi)發(fā)者使用 QWebView 類(lèi)來(lái)顯示 Web 內(nèi)容。但是隨著 Qt WebEngine 的引入,Qt 引入了 QWebEngineView 類(lèi)來(lái)取代 QWebView。QWebEngineView 基于新的 Web 引擎,并提供了更現(xiàn)代化的 API 和功能。
引入了新的通信機(jī)制 - QWebChannel:
在 Qt WebEngine 中,引入了 QWebChannel 作為一種新的機(jī)制,用于在 C++ 代碼和 JavaScript 代碼之間進(jìn)行通信。通過(guò) QWebChannel,可以將 C++ 對(duì)象暴露給 JavaScript,使得它們可以相互調(diào)用和交互。
更好的擴(kuò)展性和性能:
由于 Qt WebEngine 基于 Chromium,因此具有更好的性能和擴(kuò)展性。它可以使用 Chromium 提供的各種功能和特性,包括先進(jìn)的渲染引擎、多線程支持、GPU 加速等。
更新的 HTML5 和 CSS3 支持:
Qt WebEngine 提供了更現(xiàn)代化的 HTML5 和 CSS3 支持,使得開(kāi)發(fā)者可以更輕松地創(chuàng)建豐富、交互性強(qiáng)的 Web 應(yīng)用程序。
這些是 Qt 的 Web 引擎與 WebView 交互方面的一些主要變化??偟膩?lái)說(shuō),隨著 Qt WebEngine 的引入,Qt 在 Web 開(kāi)發(fā)領(lǐng)域取得了重大進(jìn)步,為開(kāi)發(fā)者提供了更好的工具和功能來(lái)創(chuàng)建高性能的 Web 應(yīng)用程序。
2:示例展示
示例是完整Qt代碼和Html文件,可以直接測(cè)試,注釋也寫(xiě)了一些
通過(guò)QWebChannel進(jìn)行注冊(cè)和調(diào)用:
這種方法是在Qt中注冊(cè)QObject對(duì)象,使其可以在JavaScript中調(diào)用。使用QWebChannel類(lèi)來(lái)建立Qt與JavaScript之間的通信橋梁。
在Qt代碼中,通過(guò)registerObject方法將QObject對(duì)象注冊(cè)到QWebChannel中,然后在JavaScript中使用該對(duì)象??梢远x槽函數(shù)和屬性,這些槽函數(shù)和屬性可以在JavaScript中直接調(diào)用和訪問(wèn)。在JavaScript中調(diào)用這些槽函數(shù)來(lái)執(zhí)行特定的操作,或者讀取和設(shè)置屬性。
這種方法適用于在Web頁(yè)面中需要與Qt代碼進(jìn)行交互的場(chǎng)景,需要從Web頁(yè)面中觸發(fā)特定操作,并且在Qt代碼中執(zhí)行相應(yīng)的處理時(shí),或者需要在Web頁(yè)面中顯示Qt代碼中的數(shù)據(jù)時(shí)這樣做很方便。
如果想要簡(jiǎn)單的Qt調(diào)用JavaScript函數(shù)的話,就使用runJavaScript方法就行
總的來(lái)說(shuō),如果需要頻繁地進(jìn)行 C++ 和 JavaScript 之間的通信,使用連接信號(hào)與槽會(huì)更加方便和高效。而如果只是偶爾需要執(zhí)行一些 JavaScript 代碼,使用 `runJavaScript` 也是一個(gè)不錯(cuò)的選擇。
#pragma once
#include <QWidget>
#include <QJsonObject>
class QWebEngineView;
class QWebChannel;
class frmgplot : public QWidget
{
Q_OBJECT
/*Q_PROPERTY 定義了一個(gè)名為 jsonData 的屬性,
其類(lèi)型為 QJsonObject,并將其與一個(gè)名為 qtjsonData 的成員變量關(guān)聯(lián)起來(lái)。
當(dāng)qtjsonData改變時(shí),會(huì)自動(dòng)觸發(fā)qtdataChanged信號(hào)
要在類(lèi)中聲明好 信號(hào)(qtdataChanged) 和 成員(qtjsonData)
*/
Q_PROPERTY(QJsonObject jsonData MEMBER qtjsonData NOTIFY qtdataChanged)
public:
frmgplot(QWidget *parent);
~frmgplot();
void initfrm();
void setQtjsonData(const QJsonObject & jsonData);
public slots:
//js 調(diào)用qt函數(shù),注意類(lèi)型必須要是public slots:
void jscallQt(const QString &str);
private slots:
void onPageLoadFinished(bool success);
signals:
//當(dāng)qtjsonData改變時(shí),會(huì)自動(dòng)觸發(fā)qtdataChanged信號(hào)
void qtdataChanged(const QJsonObject &jsonData);
private:
QWebEngineView *m_webView;
QWebChannel *m_webChannel;
QJsonObject qtjsonData;
};
#include "frmgplot.h"
#include <QWebEngineView>
#include <QWebChannel>
#include <QFileInfo>
#include <QDir>
#include <QApplication>
#include <QVBoxLayout>
#include <qmessagebox.h>
#include <QTimer>
frmgplot::frmgplot(QWidget *parent)
: QWidget(parent)
{
//拿到示例后,別忘了在合適的時(shí)候 初始化initfrm
}
frmgplot::~frmgplot()
{
}
void frmgplot::initfrm()
{
QVBoxLayout *layout = new QVBoxLayout(this);
setLayout(layout);
// 創(chuàng)建 Web 視圖
m_webView = new QWebEngineView(this);
layout->addWidget(m_webView);
// 創(chuàng)建 Web 通道
m_webChannel = new QWebChannel(this);
// 注冊(cè)到 Web 頁(yè)面,使 JavaScript 能夠調(diào)用 Qt類(lèi)里面的 槽函數(shù)
m_webChannel->registerObject("frmplot", this);
m_webView->page()->setWebChannel(m_webChannel);//設(shè)備交互通道
// 加載 HTML 頁(yè)面
QString filePath = QFileInfo(QApplication::applicationDirPath() + "/web/gplot/js/index.html").absoluteFilePath();
m_webView->load(QUrl::fromLocalFile(filePath));
// 連接信號(hào)槽以在通道初始化后調(diào)用 JavaScript 函數(shù)
connect(m_webView, &QWebEngineView::loadFinished, this, &frmgplot::onPageLoadFinished);
}
void frmgplot::onPageLoadFinished(bool success)
{
if (success) {
// 頁(yè)面加載完成后調(diào)用 JavaScript 函數(shù)
// 創(chuàng)建定時(shí)器,延遲3秒后執(zhí)行
QTimer::singleShot(3000, this, [=]() {
// 頁(yè)面加載完成后調(diào)用 JavaScript 函數(shù)
m_webView->page()->runJavaScript(QString("qtcalljsfunc('%1');").arg("qt call to js"));
});
}
}
void frmgplot::jscallQt(const QString &str)
{
QMessageBox::warning(this, QString::fromLocal8Bit("title"), str);
/*示例:
js 調(diào)用 qt 后,
qt再次設(shè)置
屬性jsonData 的qtjsonData成員,
讓其改變 然后 觸發(fā)信號(hào)qtdataChanged,從而讓web 捕捉到qtdataChanged信號(hào)*/
QJsonObject json;
json["obj1"] = 1;
json["obj2"] = 666.666;
json["obj3"] = "this objstr";
this->setProperty("jsonData", json);
setQtjsonData(json);
}
void frmgplot::setQtjsonData(const QJsonObject &jsonData)
{
//if (qtjsonData != jsonData)
{
qtjsonData = jsonData;//會(huì)自動(dòng)觸發(fā)qtdataChanged
}
}<!doctype html>
<html>
<head>
<title>Network</title>
<script src="qwebchannel.js"></script>
<style type="text/css">
#mynetwork {
width: 80vw; /* 設(shè)置為全屏寬度的 80% */
height: 80vh; /* 設(shè)置為全屏高度的 80% */
border: 1px solid lightgray;
}
/* 設(shè)置 body 和 html 的寬度和高度為100%,以使 #mynetwork 占據(jù)整個(gè)屏幕 */
body, html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
}
</style>
</head>
<body>
<button id="jscallqtbutton">js call qt</button>
/*定義一個(gè)按鈕*/
<p>
</p>
<div id="mynetwork"></div>
<script type="text/javascript">
//----------- webchannel qt js 交互
var updatejson=function(text){
// 使用JSON.stringify將QJsonObject轉(zhuǎn)換為字符串,然后再輸出
alert(JSON.stringify(text));
}
var webObject;
// Connect to the QWebChannel
new QWebChannel(qt.webChannelTransport, function(channel) {
webObject = channel.objects.frmplot;
window.foo = webObject;//對(duì)象賦值給了全局對(duì)象 window 的屬性 foo
//qt信號(hào){qtdataChanged}與js函數(shù)連接,就像 qt的信號(hào)槽一樣
webObject.qtdataChanged.connect(updatejson);
// 1: web view -> qt :web上按鈕(jscallqtbutton)按下后,調(diào)用qt函數(shù)jscallQt
document.getElementById("jscallqtbutton").onclick = function() {
webObject.jscallQt("jscall-qt");
alert("jscallQt");
};
//2:qt -> web js
// 示例:在頁(yè)面上顯示jsonData的內(nèi)容
/* jsonDataDisplay = document.getElementById("jsonDataDisplay");
jsonDataDisplay.innerHTML = JSON.stringify(jsonData);*/
});
//--------
function qtcalljsfunc(text) {
alert((text));
}
</script>
</body>
</html>
3:項(xiàng)目注意事項(xiàng)
3.1 :Qt WebEngine locales directory not found at location 錯(cuò)誤
這個(gè)警告是因?yàn)?Qt WebEngine 在運(yùn)行時(shí)需要一些 ICU 數(shù)據(jù)文件,這些文件通常位于 Qt 的安裝目錄中。警告消息顯示 Qt WebEngine 在指定的目錄下找不到 ICU 數(shù)據(jù)文件,因此它會(huì)嘗試從其他位置加載
在 Qt WebEngine 中,ICU 數(shù)據(jù)文件主要用于處理文字排版、文字渲染、國(guó)際化以及本地化等任務(wù)。因此,運(yùn)行 Qt WebEngine 應(yīng)用程序時(shí),它會(huì)嘗試加載這些 ICU 數(shù)據(jù)文件,以確保在不同地區(qū)和語(yǔ)言環(huán)境下能夠正確地顯示和處理文本。
icudtl.dat 是 Qt 框架使用的 ICU(International Components for Unicode)數(shù)據(jù)文件之一。
icudtl.dat 是在Qt的安裝目錄中的,在安裝目錄中搜索并且incudtl.dat和這些pak文件 復(fù)制到 執(zhí)行文件相同層級(jí)目錄下就可以了。*.pak 是 Qt WebEngine 中的資源文件,它們包含了用于支持開(kāi)發(fā)者工具和其他功能所需的資源。注意拷貝時(shí),要區(qū)分 對(duì)應(yīng)版本 。

3.2 運(yùn)行時(shí) 崩潰例如:m_webView->page()->setWebChannel(m_webChannel);或者其他地方莫名崩潰
QtWebEngineProcess.exe 是 Qt WebEngine 模塊的一個(gè)子進(jìn)程,用于在 Qt 應(yīng)用程序中執(zhí)行 Web 頁(yè)面的渲染和相關(guān)任務(wù)。通常情況下,QtWebEngineProcess.exe 被設(shè)計(jì)為與主應(yīng)用程序(.exe 文件)放置在同一目錄下,這是為了便于它與主應(yīng)用程序之間共享資源和進(jìn)行通信,否則會(huì)出現(xiàn)各種莫名崩潰問(wèn)題
總結(jié)
到此這篇關(guān)于Qt與QWebEngineView交互的文章就介紹到這了,更多相關(guān)Qt與QWebEngineView交互內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語(yǔ)言?超詳細(xì)總結(jié)講解二叉樹(shù)的概念與使用
二叉樹(shù)可以簡(jiǎn)單理解為對(duì)于一個(gè)節(jié)點(diǎn)來(lái)說(shuō),最多擁有一個(gè)上級(jí)節(jié)點(diǎn),同時(shí)最多具備左右兩個(gè)下級(jí)節(jié)點(diǎn)的數(shù)據(jù)結(jié)構(gòu)。本文將詳細(xì)介紹一下C++中二叉樹(shù)的概念和結(jié)構(gòu),需要的可以參考一下2022-04-04
C++指針作為函數(shù)的參數(shù)進(jìn)行傳遞時(shí)需要注意的一些問(wèn)題
當(dāng)指針作為函數(shù)的參數(shù)進(jìn)行傳遞的時(shí)候,本質(zhì)上還是進(jìn)行的“值傳遞”,也就是復(fù)制了一個(gè)新的指向該地址的指針變量2013-10-10
解析設(shè)計(jì)模式中的Prototype原型模式及在C++中的使用
這篇文章主要介紹了設(shè)計(jì)模式中的Prototype原型模式及在C++中的使用,需要的朋友可以參考下2016-03-03
C語(yǔ)言實(shí)現(xiàn)大學(xué)生考勤管理系統(tǒng)
這篇文章主要為大家詳細(xì)介紹了C語(yǔ)言實(shí)現(xiàn)大學(xué)生考勤管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-12-12
C++實(shí)現(xiàn)職工工資管理系統(tǒng)課程設(shè)計(jì)
這篇文章主要為大家詳細(xì)介紹了C++實(shí)現(xiàn)職工工資管理系統(tǒng)課程設(shè)計(jì),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-03-03

