QWebEngine 初探 显示并跳转页面(QWebEngineView 二级页面 关闭程序时报错)

3 篇文章 0 订阅

目录

1、前言

2、环境

3、实现

3.1 准备

3.2 显示页面

3.2 显示页面并根据点击跳转

4. 关闭程序时是崩溃


1、前言

今天尝试使用Qt的WebEngine模块来在窗口中显示一个网页并跳转链接,着这个过程中遇到一些坑,写在这里吧~

如果只是碰到关闭时报错的问题,请跳到文章 4. 节

2、环境

系统:ubuntu 16.04

Qt版本:5.14.2

IDE:QtCreator (需要安装 QWebEngine 模块)

编译模式:Debug

3、实现

3.1 准备

1. 创建一个Qt Widget Appliciation 项目

2. 在pro文件中:在 QT  += core gui widgets  添加 webenginewidgets 添加之后 QT  += core gui widgets webenginewidgets

3.2 显示页面

在Qt中显示一个网页很容易,只需要在 MainWindow中,创建一个 QWebEngineView 即可,代码如下

mainwindow.cpp

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWebEngineView>
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    QWebEngineView *view = new QWebEngineView(this);
    view->load(QUrl("https:www.baidu.com")); // 设置目标网页
    this->setCentralWidget(view); // 设置为中心窗口
}

mainwindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include "webbrowser.h"

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    WebBrowser* web;
};
#endif // MAINWINDOW_H

编译运行即可,效果如图:

此时点击图中的一些需要在新窗口显示的链接是没有作用的,我们往下走,

在新窗口显示的连接指的是点击后会跳转到一个新窗口中显示,就像我们在浏览器中点击这个连接会新建一个标签一样;对于有些网页中的有些按钮是直接在当前页跳转,这种按钮点击是有效的。

3.2 显示页面并根据点击跳转

Qt 已经帮我们在 QWebEngineView 中预留创建窗口的接口 QWebEngineView * createWindow(QWebEnginePage::WebWindowType type); 所以需要我们从 QWebEngineView 派生自己的类并重写该函数;通过这个函数我们决定如何创建新的窗口,注意在创建的时候指定 父类指针!!! 这里我创建了一个名为 WebBrowser的类,代码如下:

头文件 webbrowser.h

#ifndef WEBBROWSER_H
#define WEBBROWSER_H
#pragma once
#include <QWebEngineView>

class WebBrowser : public QWebEngineView
{
    Q_OBJECT
public:
    explicit WebBrowser(QWidget* parent = nullptr);
    ~WebBrowser();
protected:
    QWebEngineView * createWindow(QWebEnginePage::WebWindowType type) override;

private slots:
    void OnUrlChanged(QUrl url); // 测试 urlChanged信号,该信号由 load(QUrl) 触发

};

#endif // WEBBROWSER_H

cpp文件 webbrowser.cpp     注意:在代码中位置指定父指针,如果你这里不像我一样创建一个窗口,则 QWebEngineView 对象必须指定父类指针

#include "webbrowser.h"

#include <QMainWindow>
#include <QDebug>
#include <QWebEngineSettings>
#include <QWebEngineProfile>

WebBrowser::WebBrowser(QWidget* parent):QWebEngineView(parent)
{
    connect(this,&QWebEngineView::urlChanged,this,&WebBrowser::OnUrlChanged);
}
WebBrowser::~WebBrowser(){
}
QWebEngineView * WebBrowser::createWindow(QWebEnginePage::WebWindowType type){
   Q_UNUSED(type)

    QWebEngineView *webbrowser = new QWebEngineView();

    connect(webbrowser,&QWebEngineView::urlChanged,this,&WebBrowser::OnUrlChanged);
    QMainWindow *dialog = new QMainWindow(window()); // 指定父窗口指针!!!
    dialog->setWindowTitle("SubWindow");
    dialog->setCentralWidget(webbrowser);
    dialog->show();

    return webbrowser;
}

void WebBrowser::OnUrlChanged(QUrl url){
    qDebug()<<"url changed "<<url;
}

mainwindow.cpp 

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWebEngineView>
#include "webbrowser.h"
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    auto widget = new WebBrowser();
    widget->load(QUrl("https://www.baidu.com"));
    this->setCentralWidget(widget);
}

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

编译运行效果如图,我们在显示出页面之后点击 新闻 会触发新窗口请求,更精细的控制请查阅 QWebEnginePage::WebWindowType 

4. 关闭程序时是崩溃

在我实现代码的时候碰到了这样的问题: 我可以在点击后跳转到新的窗口,但是在我关闭所有窗口的时候报错,如图

原因:我们在createWindow函数中创建新窗口时没有指定父窗口指针,此时的代码是这样的:

QWebEngineView * WebBrowser::createWindow(QWebEnginePage::WebWindowType type){
   Q_UNUSED(type)

    QWebEngineView *webbrowser = new QWebEngineView();

    connect(webbrowser,&QWebEngineView::urlChanged,this,&WebBrowser::OnUrlChanged);
    QMainWindow *dialog = new QMainWindow(); // 没有指定父窗口指针
    dialog->setWindowTitle("SubWindow");
    dialog->setCentralWidget(webbrowser);
    dialog->show();

    return webbrowser;
}

猜测(如果你能解答一定要告诉我!!!非常感谢!!!):应该是和Qt的对象树管理有关系,在我们不指定父窗口的时候,这个对象会被分配到两个对象树当中,这样关闭的时候就会出问题,而在指定父对象之后同属一个对象树;

我的经历:碰到问题后,网上没能查到想要的资料,所以我尝试看了一下源代码,在createWindow 之后会调用 QWebEngineView::load()函数,该函数会跳转到 WebContentsAdapter::load 函数,感觉应该是这个函数中的一些操作造成的,但还需要在研究,还有别的事情,先到者吧

如果你知道准确答案,烦请告诉我!!!!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值