QWebengineView和js交互

1、通过使用QtWebEngine加载相关页面,然后用QtWebChannel作为Qt与Javascript交互通讯的通道
1)pro中添加对应模块

QT += webenginewidgets webchannel

2)demo组成:QT界面+html5+qwebchannel.js(Qt官方自带)
2、相关伪代码
1)Qt窗口业务实现

void MainWindow::setupUI()
{
    if (m_pContentTextEdit == Q_NULLPTR)
    {
        m_pContentTextEdit = new QPlainTextEdit(this);
        m_pContentTextEdit->setMidLineWidth(400);
        m_pContentTextEdit->setReadOnly(true);
    }

    if (m_pSendLineEdit == Q_NULLPTR)
    {
        m_pSendLineEdit = new QLineEdit(this);
    }
    QPushButton *pSendBtnByJavaScript  = new QPushButton("SendToJS", this);

    QHBoxLayout *pQtSendHLayout = new QHBoxLayout;
    pQtSendHLayout->setMargin(0);
    pQtSendHLayout->setSpacing(0);
    pQtSendHLayout->addWidget(m_pSendLineEdit);
    pQtSendHLayout->addSpacing(5);
    pQtSendHLayout->addWidget(pSendBtnByJavaScript);

    QVBoxLayout *pTotalVLayout = new QVBoxLayout;
    pTotalVLayout->setMargin(5);
    pTotalVLayout->setSpacing(0);
    pTotalVLayout->addWidget(m_pContentTextEdit);
    pTotalVLayout->addSpacing(5);
    pTotalVLayout->addLayout(pQtSendHLayout);

    if (m_pJSWebView == Q_NULLPTR)
    {
        m_pJSWebView = new QWebEngineView(this);
        m_pJSWebView->setFixedSize(600,650);
        InjectJsFile(QApplication::applicationDirPath() + "/qwebchannel.js");
        InjectJsFile(QApplication::applicationDirPath() + "/bridge.js");//web js接口
        m_pJSWebView->page()->load(QUrl::fromLocalFile(QApplication::applicationDirPath() + "/JSTest.html"));
        m_pJSWebView->show();
    }
    QWebChannel *pWebChannel   = new QWebChannel(m_pJSWebView->page());
    JSBridge *pJSBridge = new JSBridge(this);
    pWebChannel->registerObject(QStringLiteral("jsBridgeObj"), pJSBridge);//注册Qt对象
    m_pJSWebView->page()->setWebChannel(pWebChannel);

    QVBoxLayout *pJSTotalVLayout = new QVBoxLayout();
    pJSTotalVLayout->setMargin(0);
    pJSTotalVLayout->setSpacing(0);
    pJSTotalVLayout->addWidget(m_pJSWebView);

    QHBoxLayout *mainLayout = new QHBoxLayout;
    mainLayout->setMargin(5);
    mainLayout->setSpacing(0);
    mainLayout->addLayout(pTotalVLayout);
    mainLayout->addSpacing(5);
    mainLayout->addLayout(pJSTotalVLayout);
    setLayout(mainLayout);
    this->setFixedSize(1000, 700);

    connect(pSendBtnByJavaScript,  &QPushButton::clicked,  this,  &MainWindow::OnSendMessageByJavaScript);

    connect(pJSBridge, &JSBridge::sigRecvMsgFromJS,this,[&](QString strMsg){
        m_pContentTextEdit->appendPlainText(strMsg);
    });
    connect(this, &MainWindow::sigSendMessageToJS,
            pJSBridge, &JSBridge::sigSendMessageToJS);
}

void MainWindow::OnSendMessageByJavaScript()
{
    QString strMessage = m_pSendLineEdit->text().trimmed();
    if (strMessage.isEmpty())
    {
        return;
    }
    //直接运行js
    m_pJSWebView->page()->runJavaScript(QString("jsBridgeAnswerHtml.output('%1');").arg(QString("Received Msg from Qt: %1").arg(strMessage)));

    //通过信号方式发消息
    emit sigSendMessageToJS(QString("Received Msg from Qt Sig: %1").arg(strMessage));
    m_pSendLineEdit->clear();
}

bool MainWindow::InjectJsFile(const QString &strFileName) {
    QFile file(strFileName);
    if (file.open(QFile::ReadOnly | QFile::Text)) {
        QTextStream in(&file);
        QWebEngineScript script;
        script.setSourceCode(in.readAll());
        script.setInjectionPoint(QWebEngineScript::DocumentCreation);
        script.setRunsOnSubFrames(true);
        script.setWorldId(QWebEngineScript::MainWorld);
        m_pJSWebView->page()->scripts().insert(script);
        file.close();
        return true;
    }
    return false;
}

2)Qt和h5交互注册类

#ifndef JSBRIDGEBASE_H
#define JSBRIDGEBASE_H

#include <QObject>
class JSBridge : public QObject
{
    Q_OBJECT
public:
    explicit JSBridge(QObject *parent = nullptr);
    virtual ~JSBridge();
    //web 页面调用Qt公共函数
    Q_INVOKABLE void sendMsg(QString strMsg);
signals:
    void sigRecvMsgFromJS(QString strMsg);
    void sigSendMessageToJS(QString strMsg);

public slots:
    void request(QString strMsg);
};

#endif // JSBRIDGEBASE_H

void JSBridge::sendMsg(QString strMsg)
{
    emit sigRecvMsgFromJS("Received Msg from JS.sendMsg: "+strMsg);
}

void JSBridge::request(QString strMsg) {
    emit sigRecvMsgFromJS("Received Msg from JS.slot: "+strMsg);
}

3)html代码

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <script type="text/javascript" src="./test.js"></script>
        <script type="text/javascript">
        //---Web show receive message---
                        function Test() {
                    var input = document.getElementById("input");
                    if (!input.value) {
                        return;
                    }

                    //Web use the interface of Qt
                    jsBridgeAnswerCef.sendMsgToQt(input.value);
                    input.value = "";
                }
        </script>
        <style type="text/css">
            html {
                height: 100%;
                width: 100%;
            }
            #input {
                width: 650px;
                margin: 0 10px 0 0;
            }
            #send {
                width: 90px;
                margin: 0;
            }
            #output {
                width: 770px;
                height: 550px;
            }
        </style>
    </head>
    <body>
        <textarea id="output" readonly="readonly"></textarea><br />
        <input id="input" />
        <input type="submit" id="send" value="SendToQt" onclick="Test()" />
    </body>
</html>

4)bridge.js和test.js
bridge.js:

var jsBridgeAnswerCef = {};
window.onload = function(){
    new QWebChannel(qt.webChannelTransport, function(channel)
    {
        var obj = channel.objects.jsBridgeObj;
        jsBridgeAnswerCef.sendMsgToQt = function (data)
        {
            obj.request(data);
            obj.sendMsg(data);
        }
        obj.sigSendMessageToJS.connect(function(str) {
        jsBridgeAnswerHtml.output(str);
        });
    });
}

test.js:

var jsBridgeAnswerHtml = {};
jsBridgeAnswerHtml.output = function (message)       
  {  
      var output = document.getElementById("output");  
      output.innerHTML = output.innerHTML + message + "\n"; 
  }  

3、运行效果
在这里插入图片描述
4、代码链接
https://download.csdn.net/download/qqzhaojianbiao/19058964

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
QWebEngineView 是 Qt 提供的一个用于显示 Web 内容的组件,它基于 Chromium 内核,支持现代 Web 技术和 HTML5 标准。 如果要在 QWebEngineView 中与 Qt 进行交互,可以通过以下几个步骤实现: 1. 创建一个 QWebEnginePage 子类,重写其 createWindow 方法,用于拦截新窗口的打开。 2. 在 QWebEngineView 中设置该 QWebEnginePage 子类的实例,以便在浏览器中打开链接时能够被拦截。 3. 使用 Qt 的信号和槽机制,在 QWebEnginePage 子类中处理与 Qt 的交互事件。 下面是一个简单的例子,演示如何在 QWebEngineView 中与 Qt 进行交互: ```python from PyQt5.QtCore import QUrl, pyqtSlot from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEnginePage from PyQt5.QtWidgets import QApplication import sys class MyWebEnginePage(QWebEnginePage): def __init__(self, parent=None): super().__init__(parent) def createWindow(self, QWebEnginePage_WebWindowType): new_page = MyWebEnginePage(self) new_view = QWebEngineView() new_view.setPage(new_page) new_view.show() return new_page @pyqtSlot(str) def js_callback(self, result): print(result) if __name__ == '__main__': app = QApplication(sys.argv) view = QWebEngineView() page = MyWebEnginePage(view) view.setPage(page) view.load(QUrl("https://www.baidu.com")) # 注册一个 JavaScript 回调函数 page.runJavaScript("window.my_callback = function(result) {pyjsqt.js_callback(result)}") sys.exit(app.exec_()) ``` 在这个例子中,我们创建了一个名为 MyWebEnginePage 的 QWebEnginePage 子类,它重写了 createWindow 方法,用于在打开新窗口时拦截并创建新的 QWebEnginePage 实例。 同时,我们在 MyWebEnginePage 中注册了一个名为 js_callback 的 Python 回调函数,在 JavaScript 中可以通过 window.my_callback 来调用该回调函数,并传递一个字符串参数。 在主程序中,我们创建了一个 QWebEngineView 实例,并使用 MyWebEnginePage 的实例作为其页面。然后,我们通过 QWebEnginePage 的 runJavaScript 方法注册了一个 JavaScript 回调函数,并在其中调用了 MyWebEnginePage 中的 Python 回调函数。 当在浏览器中打开一个链接时,如果该链接指向一个新的窗口,MyWebEnginePage 的 createWindow 方法将会被触发,我们将会创建一个新的 QWebEngineView 实例,并将其设置为新的 QWebEnginePage 的页面,从而达到在同一个程序中打开新窗口的效果。 当 JavaScript 回调函数被触发时,它将会调用 MyWebEnginePage 的 Python 回调函数,从而实现了在 QWebEngineView 中与 Qt 的交互
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值