QWebEngineView简单使用,QWebEngineView显示网页点击链接无法跳转,Qt利用QWebEngine与网页混合编程,JS同步调用Qt获取数据,Qt调用JS函数

本文介绍了如何使用Qt的QWebEngineView组件显示网页并实现点击链接的页面跳转。通过继承QWebEngineView并重写createWindow函数,使得可以打开新链接。此外,还展示了如何利用QWebChannel实现Qt与JavaScript之间的双向通信,通过CccJsContext类创建C++对象并注册到WebChannel,允许JS调用C++的方法获取用户信息。
摘要由CSDN通过智能技术生成

Qt利用QWebEngineView,QWebChannel与JS通信

1、简单展示如何用QWebEngieView 显示百度网页

CccTestWebView.h

#ifndef CCCTESTWEBVIEW_H
#define CCCTESTWEBVIEW_H

#include <QWidget>

class QWebEngineView;
class CccTestWebView : public QWidget
{
    Q_OBJECT

public:
    explicit CccTestWebView(QWidget *parent = nullptr);
    ~CccTestWebView();

    void initWidget();

private:
    QWebEngineView* m_pWebView = nullptr;
};

#endif // FORM_H

CccTestWebView.cpp

#include "CccTestWebView.h"
#include <QWebEngineView>
#include <QVBoxLayout>

CccTestWebView::CccTestWebView(QWidget *parent)
    :QWidget(parent)
{
    initWidget();
}

CccTestWebView::~CccTestWebView()
{

}

void CccTestWebView::initWidget()
{
    resize(420,680);
    auto mainLayout = new QVBoxLayout(this);
    mainLayout->setSpacing(0);
    mainLayout->setMargin(0);

    m_pWebView = new QWebEngineView(this);

    m_pWebView->load(QUrl("http://www.baidu.com"));

    mainLayout->addWidget(m_pWebView);
}

main.cpp

#include <QApplication>
#include "CccTestWebView.h"
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    CccTestWebView w;
    w.show();
    return a.exec();
}

结果

在这里插入图片描述编译顺利的话你会正确的下显示百度的网页,如果报错看是不是事没有把webenginewidgets加入到.pro项目配置文件中去。但是此时你点击任何一个链接是不可以跳转到二级网页链接中去的。你需要自定义webengineview.

2、继承QWebEngineView,实现createWindow函数

CccWebEngineView.h

#ifndef CCCWEBENGINEVIEW_H
#define CCCWEBENGINEVIEW_H

#include <QObject>
#include <QWidget>
#include <QWebEngineView>

class CccWebEngineView : public QWebEngineView
{
    Q_OBJECT
public:
    explicit CccWebEngineView(QWidget* parent = nullptr);
    ~CccWebEngineView();

     virtual QWebEngineView* createWindow(QWebEnginePage::WebWindowType type) override;

private:
    QUrl m_url;
};

#endif // CCCWEBENGINEVIEW_H

CccWebEngineView.cpp

#include "CccWebEngineView.h"


CccWebEngineView::CccWebEngineView(QWidget *parent)
    :QWebEngineView(parent)
{
    //TODO: 链接hover时改变m_url的值
    connect(this->page(), &QWebEnginePage::linkHovered, this, [this](const QString &url){
        m_url.setUrl(url);
    });
    connect(this->page(), &QWebEnginePage::urlChanged, this, [this](const QUrl &url){
        m_url = url;
    });
}

CccWebEngineView::~CccWebEngineView()
{

}

QWebEngineView *CccWebEngineView::createWindow(QWebEnginePage::WebWindowType type)
{
    Q_UNUSED(type);
    if(!m_url.isEmpty())
    {
        this->load(m_url);//加载新的url
    }
    return nullptr;
}

CccTestWebView.h

#ifndef CCCTESTWEBVIEW_H
#define CCCTESTWEBVIEW_H

#include <QWidget>

class CccWebEngineView;
class CccTestWebView : public QWidget
{
    Q_OBJECT

public:
    explicit CccTestWebView(QWidget *parent = nullptr);
    ~CccTestWebView();

    void initWidget();

private:
    //QWebEngineView* m_pWebView = nullptr;
    CccWebEngineView* m_pWebView = nullptr;
};

#endif // CCCTESTWEBVIEW_H

CccTestWebView.cpp

#include "CccTestWebView.h"
#include "CccWebEngineView.h"
#include <QWebEngineView>
#include <QVBoxLayout>

CccTestWebView::CccTestWebView(QWidget *parent)
    :QWidget(parent)
{
    initWidget();
}

CccTestWebView::~CccTestWebView()
{

}

void CccTestWebView::initWidget()
{
    resize(420,680);
    auto mainLayout = new QVBoxLayout(this);
    mainLayout->setSpacing(0);
    mainLayout->setMargin(0);

    //m_pWebView = new QWebEngineView(this);
    m_pWebView = new CccWebEngineView(this);//换成自实现的

    m_pWebView->load(QUrl("http://www.baidu.com"));

    mainLayout->addWidget(m_pWebView);
}

这时候就可以点击链接跳到相应的链接的页面去了

3、Qt如何跟JS之间进行互相通信呢?

CccJsContext.h

#ifndef CCCJSCONTEXT_H
#define CCCJSCONTEXT_H

#include <QObject>
#include <QtWebEngineWidgets/QWebEnginePage>

class CccJsContext : public QObject
{
    Q_OBJECT
    Q_PROPERTY(QString userId READ  getUserId WRITE setUserId NOTIFY sigUserIdChange)
    Q_PROPERTY(QString userToken READ getUserToken WRITE setUserToken NOTIFY sigUserTokenChange)
    Q_PROPERTY(QString userInfo READ getUserInfo WRITE setUserInfo NOTIFY sigUserInfoChange)

public:
    explicit CccJsContext(QObject *parent = nullptr);
    void createConnections();
    
    void setUserId(const QString& paramUserId);
    QString getUserId()const;

    void setUserToken(const QString& paramUserToken);
    QString getUserToken()const;

    void setUserInfo(const QString& paramUserInfo);
    QString getUserInfo()const;

signals:
    void sigUserIdChange();
    void sigUserTokenChange();
    void sigUserInfoChange();

public:
    void sendMsg(QWebEnginePage* page, const QString& msg);

private:
    QString userId = "123456";
    QString userToken = "e9eo98kkkjj";
    QString userInfo = "this is a test";
};

#endif // CccJsContext

CccJsContext.cpp

#include "CccJsContext.h"

#include <QDebug>
#include <string>
#include <QThread>
#include <QDir>
#include <QFileDialog>

CccJsContext::CccJsContext(QObject *parent)
    :QObject(parent)
{
    createConnections();
}

void CccJsContext::createConnections()
{

}

void CccJsContext::sendMsg(QWebEnginePage *page, const QString &msg)
{
    page->runJavaScript(msg,[](const QVariant& v)
    {
        Q_UNUSED(v);
    });
}

void CccJsContext::setUserId(const QString &paramUserId)
{
    userId = paramUserId;
    emit sigUserIdChange();
}

QString CccJsContext::getUserId() const
{
    return userId;
}

void CccJsContext::setUserToken(const QString& paramUserToken)
{
    userToken = paramUserToken;
    emit sigUserTokenChange();
}

QString CccJsContext::getUserToken()const
{
    return userToken;
}

void CccJsContext::setUserInfo(const QString& paramUserInfo)
{
    userInfo = paramUserInfo;
    emit sigUserInfoChange();
}

QString CccJsContext::getUserInfo()const
{
    return userInfo;
}

CccTestWebView.h CccTestWebView.cpp修改

#ifndef CCCTESTWEBVIEW_H
#define CCCTESTWEBVIEW_H

#include <QWidget>

class CccWebEngineView;
class QWebChannel;
class CccJsContext;
class CccTestWebView : public QWidget
{
    Q_OBJECT

public:
    explicit CccTestWebView(QWidget *parent = nullptr);
    ~CccTestWebView();

    void initWidget();

private:
    //QWebEngineView* m_pWebView = nullptr;
    CccWebEngineView* m_pWebView = nullptr;
    QWebChannel*      m_pWebChannel = nullptr;
    CccJsContext*     m_pJsContext = nullptr;
};

#endif // CCCTESTWEBVIEW_H

#include "CccTestWebView.h"
#include "CccWebEngineView.h"
#include "CccJsContext.h"
#include <QWebEngineView>
#include <QVBoxLayout>
#include <QWebChannel>

CccTestWebView::CccTestWebView(QWidget *parent)
    :QWidget(parent)
{
    initWidget();
}

CccTestWebView::~CccTestWebView()
{

}

void CccTestWebView::initWidget()
{
    resize(420,680);
    auto mainLayout = new QVBoxLayout(this);
    mainLayout->setSpacing(0);
    mainLayout->setMargin(0);

    //m_pWebView = new QWebEngineView(this);
    m_pWebView = new CccWebEngineView(this);

    m_pWebChannel = new QWebChannel(this);
    m_pJsContext = new CccJsContext(this);
    m_pWebChannel->registerObject("CccJsBridge", m_pJsContext);
    m_pWebView->page()->setWebChannel(m_pWebChannel);
    
    QString htmlPath = "file:///";
    htmlPath.append("/Users/myname/Desktop/htmltest/test.html");
    m_pWebView->load(QUrl(htmlPath));
	    //Qt调用js函数例子
    //QString jsFun = "QtCallJsFun()";
    //m_pJsContext->sendMsg(m_pWebView->page(),jsFun);
    
    mainLayout->addWidget(m_pWebView);
}

结果在这里插入图片描述

test.html

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <script src = "js/qwebchannel.js" type="text/javascript"></script>
  <script src = "js/msgutils.js" type="text/javascript"></script>
</head>
<body>
	<div id="app" style="width: 195px;height: 175px;">
	</div>
	 <button onclick="getUserId()">获取用户Id</button>
	 <button onclick="getUserToken()">获取用户Token</button>
	 <button onclick="getUserInfo()">获取用户信息(json)</button>
</body>

<script type="text/javascript">
	function getUserId()
	{
		var userId = CccJsBridge.userId;
		alert("userId:" + userId);
	}
	function getUserToken()
	{
		var userToken = CccJsBridge.userToken;
		alert("userToken:" + userToken);
	}
	function getUserInfo()
	{
		var jsonUserInfo = CccJsBridge.userInfo;
		var userInfoObj = JSON.parse(jsonUserInfo);
		//判null
		alert("userId:" + userInfoObj.userId + " userToken:" + userInfoObj.userToken);
	}
	
</script>

在这个Demo里面JS是通过同步的方式获取C++中CccJsBridge中的值的,也可以通过在CccJsContext加上槽函数给JS调用
qwebchannel.js 在Qt安装目录下搜索找下
msgutls.js代码为

var CccJsBridge;
function init()
{
    if (typeof qt != 'undefined')
    {
        new QWebChannel(qt.webChannelTransport, function(channel)
        {
			CccJsBridge = channel.objects.CccJsBridge;		
        }
        );
    }
    else
    {
        alert("qt对象获取失败!");
    }
}
// 向qt发送消息
function sendMessage(msg)
{
    if(typeof CccJsBridge == 'undefined')
    {
        alert("context对象获取失败!");
    }
    else
    {
        CccJsBridge.onMsg(msg);
    }
}
// 控件控制函数
function onBtnSendMsg()
{
    var cmd = document.getElementById("待发送消息").value;
    sendMessage(cmd);   
}

function recvMessage(msg)
{
   alert("接收到Qt消息:" + msg);
}
init();

  • 5
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值