目录
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 函数,感觉应该是这个函数中的一些操作造成的,但还需要在研究,还有别的事情,先到者吧
如果你知道准确答案,烦请告诉我!!!!