WebEngine内容操作示例

演示如何加载和操作网页内容。

内容操作展示了如何使用JQuery结合Qt WebEngine Widgets创建带特殊效果和内容操作的网页浏览器。

在应用程序中,我们调用QWebEnginePage::runJavaScript()来执行jQuery JavaScript代码。我们实现一个包含QWebEngineViewQMainWindow作为主控件来构建浏览器本身。

运行示例

要从Qt Creator运行示例,打开欢迎模式并从示例中选择示例。有关更多信息,请访问构建和运行示例

MainWindow类定义

MainWindow类继承自QMainWindow。它实现了一系列槽以在应用程序和网页内容上执行操作

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(const QUrl& url);

protected slots:

    void adjustLocation();
    void changeLocation();
    void adjustTitle();
    void setProgress(int p);
    void finishLoading(bool);

    void viewSource();

    void highlightAllLinks();
    void rotateImages(bool invert);
    void removeGifImages();
    void removeInlineFrames();
    void removeObjectElements();
    void removeEmbeddedElements();

private:
    QString jQuery;
    QWebEngineView *view;
    QLineEdit *locationEdit;
    QAction *rotateAction;
    int progress;
};

我们还声明了一个包含jQuery的QString,一个显示网页内容的QWebEngineView,以及一个作为地址栏的QLineEdit

MainWindow类实现

我们首先实现构造函数。构造函数的第一部分将progress的值设置为0。这个值将在代码中稍后用于可视化加载网页

MainWindow::MainWindow(const QUrl& url)
{
    setAttribute(Qt::WA_DeleteOnClose, true);
    progress = 0;

接下来,通过QFile读取文件内容使用QFile加载jQuery库。jQuery库是一个提供用于操作HTML的不同功能的JavaScript库。

    QFile file;
    file.setFileName(":/jquery.min.js");
    file.open(QIODevice::ReadOnly);
    jQuery = file.readAll();
    jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };");
    file.close();

构建函数的第二部分创建一个QWebEngineView并将槽连接到视图的信号

    view = new QWebEngineView(this);
    view->load(url);
    connect(view, &QWebEngineView::loadFinished, this, &MainWindow::adjustLocation);
    connect(view, &QWebEngineView::titleChanged, this, &MainWindow::adjustTitle);
    connect(view, &QWebEngineView::loadProgress, this, &MainWindow::setProgress);
    connect(view, &QWebEngineView::loadFinished, this, &MainWindow::finishLoading);

此外,我们创建一个作为浏览器地址栏的QLineEdit。然后我们将垂直QSizePolicy设置为始终填充浏览器中的可用区域。我们将QLineEdit添加到一个包含来自QWebEngineView::pageAction()的导航操作的QToolBar

    locationEdit = new QLineEdit(this);
    locationEdit->setSizePolicy(QSizePolicy::Expanding, locationEdit->sizePolicy().verticalPolicy());
    connect(locationEdit, &QLineEdit::returnPressed, this, &MainWindow::changeLocation);

    QToolBar *toolBar = addToolBar(tr("Navigation"));
    toolBar->addAction(view->pageAction(QWebEnginePage::Back));
    toolBar->addAction(view->pageAction(QWebEnginePage::Forward));
    toolBar->addAction(view->pageAction(QWebEnginePage::Reload));
    toolBar->addAction(view->pageAction(QWebEnginePage::Stop));
    toolBar->addWidget(locationEdit);

构建函数的第三部分实现了两个QMenu小部件并将一系列操作分配给它们

    QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
    QAction *viewSourceAction = new QAction(tr("Page Source"), this);
    connect(viewSourceAction, &QAction::triggered, this, &MainWindow::viewSource);
    viewMenu->addAction(viewSourceAction);

    QMenu *effectMenu = menuBar()->addMenu(tr("&Effect"));
    effectMenu->addAction(tr("Highlight all links"), this, &MainWindow::highlightAllLinks);

    rotateAction = new QAction(this);
    rotateAction->setIcon(style()->standardIcon(QStyle::SP_FileDialogDetailedView));
    rotateAction->setCheckable(true);
    rotateAction->setText(tr("Turn images upside down"));
    connect(rotateAction, &QAction::toggled, this, &MainWindow::rotateImages);
    effectMenu->addAction(rotateAction);

    QMenu *toolsMenu = menuBar()->addMenu(tr("&Tools"));
    toolsMenu->addAction(tr("Remove GIF images"), this, &MainWindow::removeGifImages);
    toolsMenu->addAction(tr("Remove all inline frames"), this, &MainWindow::removeInlineFrames);
    toolsMenu->addAction(tr("Remove all object elements"), this, &MainWindow::removeObjectElements);
    toolsMenu->addAction(tr("Remove all embedded elements"), this, &MainWindow::removeEmbeddedElements);

最后一行将QWebEngineView设置为QMainWindow中的中心小部件

    setCentralWidget(view);
}

当页面加载时,由QWebEngineView中的loadFinished()信号触发的adjustLocation()更新地址栏

void MainWindow::adjustLocation()
{
    locationEdit->setText(view->url().toString());
}

changeLocation() 函数中,我们创建了一个 QUrl 对象,然后使用它将页面加载到 QWebEngineView 中。当新的网页完成加载时,adjustLocation() 将再次执行以更新地址栏

void MainWindow::changeLocation()
{
    QUrl url = QUrl::fromUserInput(locationEdit->text());
    view->load(url);
    view->setFocus();
}

adjustTitle() 方法设置窗口标题并显示加载进度

void MainWindow::adjustTitle()
{
    if (progress <= 0 || progress >= 100)
        setWindowTitle(view->title());
    else
        setWindowTitle(QStringLiteral("%1 (%2%)").arg(view->title()).arg(progress));
}

void MainWindow::setProgress(int p)
{
    progress = p;
    adjustTitle();
}

此槽由 QWebEngineView 中的 titleChanged() 信号触发。

当网页加载完成后,QWebEngineView 中的 loadFinished() 信号会触发 finishLoading() 方法。然后该方法更新标题栏中的进度并在当前网页上评估 jQuery 库

void MainWindow::finishLoading(bool)
{
    progress = 100;
    adjustTitle();
    view->page()->runJavaScript(jQuery);

    rotateImages(rotateAction->isChecked());
}

这意味着 JavaScript 可以被视为加载到 QWebEngineView 内容的一部分,因此每当加载新页面时都需要加载。一旦加载了 jQuery 库,我们就可以开始执行浏览器中的不同 jQuery 函数。

之后显式调用 rotateImages() 函数,以确保新加载页面的图片符合切换操作的状态。

第一个基于 jQuery 的函数 highlightAllLinks() 设计用来突出显示当前网页中的所有链接。JavaScript 代码查找名为 a 的网络元素,这是超链接的标签。对于每个这样的元素,使用 CSS 设置其背景颜色为黄色

void MainWindow::highlightAllLinks()
{
    QString code = QStringLiteral("qt.jQuery('a').each( function () { qt.jQuery(this).css('background-color', 'yellow') } )");
    view->page()->runJavaScript(code);
}

rotateImages() 函数旋转当前网页上的图片。此 JavaScript 代码依赖于 CSS 变换。它查找所有 img 元素,旋转图片 180 度然后再旋转回来

void MainWindow::rotateImages(bool invert)
{
    QString code;

    if (invert)
        code = QStringLiteral("qt.jQuery('img').each( function () { qt.jQuery(this).css('transition', 'transform 2s'); qt.jQuery(this).css('transform', 'rotate(180deg)') } )");
    else
        code = QStringLiteral("qt.jQuery('img').each( function () { qt.jQuery(this).css('transition', 'transform 2s'); qt.jQuery(this).css('transform', 'rotate(0deg)') } )");
    view->page()->runJavaScript(code);
}

剩余的方法从当前网页中删除不同的元素。removeGifImages() 通过查找网页上所有元素的 src 属性来删除网页上的所有 GIF 图片。任何具有 gif 文件作为其源文件的元素都被删除

void MainWindow::removeGifImages()
{
    QString code = QStringLiteral("qt.jQuery('[src*=gif]').remove()");
    view->page()->runJavaScript(code);
}

removeInlineFrames() 方法删除所有的 iframe 或内联元素

void MainWindow::removeInlineFrames()
{
    QString code = QStringLiteral("qt.jQuery('iframe').remove()");
    view->page()->runJavaScript(code);
}

removeObjectElements() 方法删除所有的 object 元素

void MainWindow::removeObjectElements()
{
    QString code = QStringLiteral("qt.jQuery('object').remove()");
    view->page()->runJavaScript(code);
}

removeEmbeddedElements() 方法删除使用 embed 标签的任何元素,例如网页上嵌入的插件

void MainWindow::removeEmbeddedElements()
{
    QString code = QStringLiteral("qt.jQuery('embed').remove()");
    view->page()->runJavaScript(code);
}

示例项目 @ code.qt.io

© 2024 The Qt Company Ltd. 本文件所包含的文档贡献的版权归其所有者所有。本文件提供的文档受 GNU 自由文档许可证版本 1.3 的许可,该许可证由自由软件基金会发布。Qt 和相应徽标是 The Qt Company Ltd. 在芬兰和/或世界上其他国家的商标。所有其他商标均为其所有者的财产。