QT实现浏览器访问网页,使用QWebEngineView

支持访问网页,前进、后退、刷新,点击超链接自动跳转,获取网页鼠标事件,重新编译QWebEngineView库后还可以支持播放mp4等视频;
Qt在debug模式运行有时访问网页很卡,切换release版后访问速度基本正常。

目录

  • 环境说明
  • 源代码
  • 效果图
  • QWebEngineView缺点和优点

环境说明

使用QWebEngineView类实现,qt5.6及以上版本;
qt安装时需要勾选:Qt WebEngine;
由于chrome不支持mingw编译,构建套件只能选择vs的编译器;
pro工程文件添加QT += webenginewidgets

源代码

重写QWebEngineView类,主要实现两个功能:
1、QWebEngineView不支持点击超链接自动跳转,对createWindow处理后可支持跳转;
2、QWebEngineView浏览web时鼠标事件被本身的child接收了,因此浏览网页时获取不了qt的鼠标事件,这里通过QEvent::ChildPolished安装事件过滤器的方式获取鼠标事件。

qwebengineviewchw.h

#ifndef QWEBENGINEVIEWCHW_H
#define QWEBENGINEVIEWCHW_H
#include 
#include 
#include 
#include 
#include 
#include 
class QWebEngineViewChw : public QWebEngineView
{
    Q_OBJECT
public:
    explicit QWebEngineViewChw(QWidget *parent = nullptr);
    ~QWebEngineViewChw()override;
protected:
    QWebEngineView* createWindow(QWebEnginePage::WebWindowType type) override;
private slots:
    void slot_LinkHovered(const QString& url);
private:
    QUrl	url_;
    QVector<QObject * > mvchildObj;
protected:
    bool event(QEvent* evt)override;

    bool eventFilter(QObject *obj, QEvent *ev)override;
};
#endif // QWEBENGINEVIEWCHW_H

qwebengineviewchw.cpp

#include "qwebengineviewchw.h"
QWebEngineViewChw::QWebEngineViewChw(QWidget *parent) : QWebEngineView(parent)
{
    setAttribute(Qt::WA_DeleteOnClose);

    connect(this->page(), &QWebEnginePage::linkHovered, this, &QWebEngineViewChw::slot_LinkHovered);
}

QWebEngineViewChw::~QWebEngineViewChw()
{
}

QWebEngineView *QWebEngineViewChw::createWindow(QWebEnginePage::WebWindowType type)
{
    //加载链接地址
    if(!url_.isEmpty())
    {
        this->load(url_);
        emit QEvent::ChildPolished;//重新加载页面时,手动触发一个ChildPolished事件
    }
//    return this;
    return nullptr;
}

void QWebEngineViewChw::slot_LinkHovered(const QString &url)
{
    //获取视图里面点击的链接地址
//    qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<
    url_.setUrl(url);
}

bool QWebEngineViewChw::event(QEvent *evt)
{
    //每次新加载URL时手动触发该事件,生成一个QChildEvent
    if (evt->type() == QEvent::ChildPolished)
    {
        qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" ";
        QChildEvent *child_ev = static_cast<QChildEvent*>(evt);

        QObject *childObj = child_ev->child();
        mvchildObj.append(childObj);
        if (childObj)
        {
            childObj->installEventFilter(this);
        }
    }

    return QWebEngineView::event(evt);
}

bool QWebEngineViewChw::eventFilter(QObject *obj, QEvent *ev)
{
    foreach(QObject *childObj,mvchildObj)
    {
        if (obj == childObj)
        {
            if (/*obj == childObj&& */(ev->type() == QEvent::MouseButtonPress|| ev->type() == QEvent::MouseButtonDblClick))
            {
                QMouseEvent *MouseEvent = static_cast<QMouseEvent *>(ev);
                int x = MouseEvent->x();
                int y = MouseEvent->y();
                qDebug()<<"["<<__FILE__<<"]"<<__LINE__<<__FUNCTION__<<" "<<x <<y;
                return QWebEngineView::eventFilter(obj, ev);
            }
        }
    }
    return QWebEngineView::eventFilter(obj, ev);
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include 
#include 
#include "qwebengineviewchw.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private slots:
    void on_pushButton_clicked();//访问
    void on_pushButton_2_clicked();//刷新
    void on_pushButton_back_clicked();//后退
    void on_pushButton_forward_clicked();//前进
private:
    Ui::MainWindow *ui;
    QWebEngineViewChw *m_webView;
};
#endif // MAINWINDOW_H

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include 
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    this->setWindowTitle(QStringLiteral("QWebEngineView浏览器"));
//    qputenv("QTWEBENGINE_REMOTE_DEBUGGING", "7777");
    QNetworkProxyFactory::setUseSystemConfiguration(false);

    m_webView = new QWebEngineViewChw(this);
    ui->verticalLayout->addWidget(m_webView);
}

MainWindow::~MainWindow()
{
    delete ui;
}
//访问
void MainWindow::on_pushButton_clicked()
{
    QString url = ui->lineEdit->text();
    if (!url.isEmpty())
    {
        m_webView->load(url);
    }
}
//刷新
void MainWindow::on_pushButton_2_clicked()
{
    m_webView->reload();
}
//后退
void MainWindow::on_pushButton_back_clicked()
{
    m_webView->back();
}
//前进
void MainWindow::on_pushButton_forward_clicked()
{
    m_webView->forward();
}

效果图

QT实现浏览器访问网页,使用QWebEngineView_第1张图片

QWebEngineView缺点和优点

1、由于QWebEngineView没有视频解码器,无法播放mp4等视频,需要重新编译QWebEngineView库,编译过程比较复杂不建议自己尝试,可以在网上下载别人编译好的,编译库和使用库的qt版本、vs版本、位数等要保持一致;

2、点击链接不跳转,重写QWebEngineView类,自动识别鼠标放在链接上面的URL地址,但有些网页链接鼠标放上不显示URL地址,这种情况无法跳转,存在一定BUG;

总结一下:简单的浏览器可以使用QWebEngineView,比较容易实现,但是稳定性和兼容性差一些,后续会研究CEF(Chromium嵌入式框架) ,并嵌入到qt程序实现浏览器功能。

你可能感兴趣的:(QT,qt,c++)