QT 使用 QWebChannel 与 html 通信

    想在 widget 里直接使用  QWebChannel ,可以直接编译通过。想使用自定义类,例如这里面的 qwebchannelclass ,可以把里面的注释掉的取消注释,该注释的注释掉,就可以编译通过。

    html可以是任何名字,扔在编译后的 exe 同文件夹里的名字为 html 的文件夹中,名字为 html 的文件夹里也要扔进去 qt 自带的 qwebchannel.js ,这个 js 文件在 qt 安装文件夹中找。

    点击按钮后,网页给程序发送 123456 ,程序收到后返回 fromLocalToWebPage 。

流程介绍: 

       一、实现一个继承于QObject的类(以下简称通信类)此类包含本地应用与网页端通信的所有方法

       二、给本地应用的网页载体QWebEnginePage对象注册通信类对象

       三、网页实现中引入qwebchannel.js,创建网页端的QWebChannel对象并与本地应用的通信类对像进行关联,最终实现网页端能够直接访问通信类的方法与本地应用进行通讯

详细介绍:

       一、自实现一个继承于QObject的类,注意,要继承于QObject,因为需要用到信号槽,这个类的主要作用是实现本地应用与网页端通信的方法,这个就时上面步骤介绍中所说的通讯类,无论本地应用还是网页端都是直接调用这个通讯类的方法来实现两者之间的通讯的。例如下面例子中的QWebChannelClass类。重点:本地应用与网页端之间的通讯过程,是通过信号和槽函数实现的,本地应用通过发送信号达到把信息发送到网页端,而网页端通过直接调用槽函数实现把信息传到本地应用。很简单,就是本地应用通过发送通讯类的信号通知网页端,网页端通过直接调用通讯类的槽函数来通知本地应用。网页端对本地应用的操作一定要调用槽函数,写在public slots 限定符下面的槽函数,不能是普通的public函数。

#ifndef QWEBCHANNELCLASS_H
#define QWEBCHANNELCLASS_H
#include <QObject>
class QWebChannelClass : public QObject
{  
  Q_OBJECT
public:   
 explicit QWebChannelClass(QObject *parent = nullptr);
signals:   
 void fromLocalToWebPage(const QString& strTemp);     //信号,发送这个信号就会把信息发送到网页端
public slots:  
  void fromWebPageToLocal(const QString& strTemp)
  {
      qDebug()<<QString("string from WebPage:%1").arg(strTemp);    
      emit fromLocalToWebPage("fromLocalToWebPage");
  }    //槽函数,网页端将通过这个函数把信息传回本地应用。
};
#endif // QWEBCHANNELCLASS_H

     二、注册通讯类,这个更简单,创建一个QWebChannel类对象,然后将步骤一中实现的通信类对象通过void QWebChannel::registerObject(const QString &id, QObject *object)注册到QWebChannel对象中,其中参数一是一个字符串,这个很重要,这个id将作为一个标识符参与网页端QWebChannel对象的创建,网页端通过这个id创建的对象将可以直接访问通信类的方法实现通信,注册好后将这个QWebChannel对象设置到即将加载我们指定网页的QWebEnginePage中(至于这个是什么原理实现的,暂时也没有研究,哪天弄明白了再更上来),下面看代码(完整代码看后面的Widget类:

QWebChannel *pChannel=new QWebChannel(this);    //创建一个Qwebchannel对象
pChannel->registerObject(QStringLiteral("channelObject"),m_pWebChannelClass); //注册通信类对像
m_pWebEngineView->page()->setWebChannel(pChannel);//将QWebChannel 对象设置到网页载体QWebEnginePage中

三、引入qwebchannel.js,创建网页端通信对象,qwebchannel.js在QtCreator安装目录下可以找到(直接在安装目录下检索就好了),下面代码中标黑的两行中第一行是固定的写法,第二行的可以理解为将本地通信类与网页端的对象关联起来使得网页端的对象可以像本地通信类对象那样使用通信类的信号和槽实现通信,

var bridge;
window.onload=function init()
{
  if (typeof qt != 'undefined')
  {
  <!-- 初始化时创建了一个QWebChannel对象,里面的第一个参数qt.webChannelTransport,只有Qt端正确地向页面设置了webchannel才能取到,否则会是undefined。-->
    new QWebChannel(qt.webChannelTransport,function (channel) 
    {
     <!-- channelObject 是步骤二中注册qwebchannle对象中的标识符-->
	 <!--QWebChannel对象里的channel.objects对应了上面Qt实现里向webchannel注册的对象表,channel.objects.context即为从表中取出名为"context"的对象。-->
      bridge = channel.objects.channelObject;      
      <!--fromLocalToWebPage是cpp端声明的信号 response是信号带过来的参数 ,跟qt信号一样理解-->
      bridge.fromLocalToWebPage.connect(function (response) 
      {
        alert("received message from local:"+response);
      });
    });
  }
  else
  {
    alert("error2");
  }
}


function fromWebToCpp()
{     
  if(typeof bridge == 'undefined')
  {
      alert("error1");
  }
  else
  {
      <!-- fromWebPageToLocal是cpp端实现的槽函数 ,这里的123456将作为参数传递到本地应用中-->
      bridge.fromWebPageToLocal("123456");
  }
}

详细代码 

//QtWevChannelDemon.pro
QT       += core gui

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++11
QT +=webenginewidgets
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    qwebchannelclass.cpp \
    widget.cpp

HEADERS += \
    qwebchannelclass.h \
    widget.h

FORMS += \
    widget.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

//qwebchannelclass.h
#ifndef QWEBCHANNELCLASS_H
#define QWEBCHANNELCLASS_H

#include <QObject>

class QWebChannelClass : public QObject
{
    Q_OBJECT
public:
    explicit QWebChannelClass(QObject *parent = nullptr);

signals:
    void fromLocalToWebPage(const QString& strTemp);//和html交互的函数要写成 信号 槽 方式
public slots:
    void fromWebPageToLocal(const QString& strTemp);//和html交互的函数要写成 信号 槽 方式
};

#endif // QWEBCHANNELCLASS_H
//widget.h
#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QWebEngineView>
#include <QHBoxLayout>
//#include "qwebchannelclass.h"
#include <QList>
#include <QDir>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT
signals:
    void fromLocalToWebPage(const QString& strTemp);//使用qwebchannelclass,注释这函数
//和html交互的函数要写成 信号 槽 方式
public slots:
    void fromWebPageToLocal(const QString& strTemp);//使用qwebchannelclass,注释这函数
//和html交互的函数要写成 信号 槽 方式

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

private:
    Ui::Widget *ui;

    QStringList fileList;

    QWebEngineView* m_pWebEngineView;
    QHBoxLayout*    m_pHBoxLayout;
    //QWebChannelClass* m_pWebChannelClass;
};
#endif // WIDGET_H
//qwebchannelclass.cpp
#include "qwebchannelclass.h"
#include <QDebug>

QWebChannelClass::QWebChannelClass(QObject *parent) : QObject(parent)
{

}

void QWebChannelClass::fromWebPageToLocal(const QString& strTemp)
{
    qDebug()<<QString("string from WebPage:%1").arg(strTemp);
    emit fromLocalToWebPage("fromLocalToWebPage");
}
//widget.cpp
#include "widget.h"
#include "ui_widget.h"
#include "widget.h"
#include <QUrl>
#include <QWebChannel>


void Widget::fromWebPageToLocal(const QString &strTemp)   //使用qwebchannelclass,注释这函数
{
    qDebug()<<QString("string from WebPage:%1").arg(strTemp);
    emit fromLocalToWebPage("fromLocalToWebPage");
}

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QString path=QCoreApplication::applicationDirPath()+"/html";
    QDir dir(path);
    if(dir.exists())
    {
        QFileInfoList file_list = dir.entryInfoList(QDir::Files | QDir::Hidden | QDir::NoSymLinks);
        QString filter;
        foreach(QFileInfo fileinfo, file_list)
        {
            filter = fileinfo.suffix();
            if( (filter != "html"))
            {
                continue;
            }
            fileList.append(fileinfo.absoluteFilePath());
        }
        m_pHBoxLayout=new QHBoxLayout(this);
        //m_pWebChannelClass =new QWebChannelClass(this);   
        m_pHBoxLayout->setContentsMargins(0,0,0,0);
        m_pWebEngineView=new QWebEngineView(this);      
        m_pHBoxLayout->addWidget(m_pWebEngineView);
        QWebChannel *pChannel=new QWebChannel(this);     //1.创建QWebChannel对象;
        //pChannel->registerObject(QStringLiteral("channelObject"),m_pWebChannelClass);
        pChannel->registerObject(QStringLiteral("channelObject"),this); 
        //向QWebChannel对象注册Qt对象。 例子里的Qt对象就是上面实现的 自定义QWebChannelClass对象。这里使用的是 widget实例自己
        //注意:这里注册时所用的名字“channelObject”,就是js获取qt对象时所使用的索引名。
        m_pWebEngineView->page()->setWebChannel(pChannel);
        //将设置好的QWebChannel对象设置为当前页面的通道。即调用setWebChannel方法。
        //注意:如果没有正确注册webchannel,在js调用qt对象时会出现qt对象为undefined的情况。
        m_pWebEngineView->load(QUrl(fileList[0]));  //在WebEngineView中加载网页
    }
}

Widget::~Widget()
{
    delete ui;
}


<!doctype html>
<html lang="en">
<meta charset="utf-8">
<head>
<script src="./qwebchannel.js"></script><!--引入qwebchannel.js-->
</head>
<body>
  <script>
  var bridge;
window.onload=function init()
{
  if (typeof qt != 'undefined')
  {
  <!-- 初始化时创建了一个QWebChannel对象,里面的第一个参数qt.webChannelTransport,只有Qt端正确地向页面设置了webchannel才能取到,否则会是undefined。-->
    new QWebChannel(qt.webChannelTransport,function (channel) 
    {
     <!-- channelObject 是步骤二中注册qwebchannle对象中的标识符-->
	 <!--QWebChannel对象里的channel.objects对应了上面Qt实现里向webchannel注册的对象表,channel.objects.context即为从表中取出名为"context"的对象。-->
      bridge = channel.objects.channelObject;      
      <!--fromLocalToWebPage是cpp端声明的信号 response是信号带过来的参数 ,跟qt信号一样理解-->
      bridge.fromLocalToWebPage.connect(function (response) 
      {
        alert("received message from local:"+response);
      });
    });
  }
  else
  {
    alert("error2");
  }
}


function fromWebToCpp()
{     
  if(typeof bridge == 'undefined')
  {
      alert("error1");
  }
  else
  {
      <!-- fromWebPageToLocal是cpp端实现的槽函数 ,这里的123456将作为参数传递到本地应用中-->
      bridge.fromWebPageToLocal("123456");
  }
}


  </script>
  <body>
  <input id="add" type="button" value="msFromWebToCpp" class="button" onclick="fromWebToCpp()"/>
  </body>
</body>
</html>

参考:https://blog.csdn.net/Y_Bingo/article/details/82954940

QWebChannel是一种用于Qt应用程序和嵌入式Web页面之间进行互操作的通信机制。它允许Qt应用程序向Web页面暴露对象,并允许Web页面访问这些对象的属性和方法。同时,也允许Web页面向Qt应用程序发送消息和调用Qt应用程序的函数。 使用QWebChannel进行Qt和JavaScript之间的交互,需要遵循以下步骤: 1. 在Qt应用程序创建一个QWebChannel对象,并将其绑定到一个QWebEngineView或QWebEnginePage对象上。 2. 在Qt应用程序创建一个QObject的子类,该子类将作为Qt对象被暴露给Web页面。 3. 在Qt应用程序将QObject对象注册到QWebChannel对象。 4. 将QWebChannel对象传递Web页面,通过JavaScript代码将其绑定到Web页面的window对象上。 5. 在JavaScript代码可以通过window对象访问到Qt应用程序注册的QObject对象,调用其属性和方法。 6. 在Qt应用程序可以通过QWebChannel对象接收Web页面发送的消息,以及调用Web页面的JavaScript函数。 下面是一个简单的例子,演示了如何使用QWebChannel进行Qt和JavaScript之间的交互: Qt代码: ```c++ // 创建一个QObject的子类,作为Qt对象被暴露给Web页面 class MyObject : public QObject { Q_OBJECT public: MyObject(QObject *parent = nullptr) : QObject(parent) {} public slots: void showMessage(const QString &message) { qDebug() << "Received message from web page:" << message; } }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // 创建一个QWebChannel对象,并将其绑定到一个QWebEngineView对象上 QWebEngineView view; QWebChannel channel; view.page()->setWebChannel(&channel); // 创建MyObject对象,并将其注册到QWebChannel对象 MyObject obj; channel.registerObject("myObject", &obj); // 加载Web页面 view.load(QUrl("qrc:/index.html")); view.show(); return app.exec(); } ``` JavaScript代码: ```javascript // 将QWebChannel对象绑定到window对象上 new QWebChannel(qt.webChannelTransport, function(channel) { window.myObject = channel.objects.myObject; }); // 调用MyObject对象的showMessage函数 myObject.showMessage("Hello from web page!"); ``` 在上面的例子,我们创建了一个名为MyObject的QObject子类,并将其注册到了QWebChannel对象。在JavaScript代码,我们通过调用QWebChannel构造函数,将QWebChannel对象绑定到window对象上,并通过window对象访问了MyObject对象的showMessage函数。当Web页面调用showMessage函数时,它将向Qt应用程序发送一个消息,Qt应用程序将通过QWebChannel对象接收到该消息,并调用MyObject对象的showMessage函数。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值