WebEngine 內容操縱範例

演示如何加載和操縱 Web 內容。

內容操縱 展示如何使用 JQuery 采用 Qt WebEngine Widgets 去創建具有特殊效果和內容操縱的 Web 瀏覽器。

在應用程序中,調用 QWebEnginePage::runJavaScript () 去執行 jQuery JavaScript 代碼。實現 QMainWindow 采用 QWebEngineView 作為構建瀏覽器本身的中心 Widget。

運行範例

要運行範例從 Qt Creator ,打開 歡迎 模式,然後選擇範例從 範例 。更多信息,拜訪 構建和運行範例 .

MainWindow 類定義

The MainWindow 類繼承 QMainWindow 。它實現許多履行應用程序和 Web 內容動作的槽:

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;
};
					

還聲明 QString 包含 jQuery, QWebEngineView 顯示 Web 內容,和 QLineEdit 充當地址欄。

MainWindow 類實現

我們從實現構造函數開始。構造函數的第一部分是設置值為 progress 到 0。此值在稍後的代碼中用於可視化網頁加載:

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

下一步,加載 jQuery 庫通過使用 QFile 並讀取文件內容。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 QToolBar 及一組導航動作來自 QWebEngineView::pageAction ():

    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 Widget 並賦值它們一組動作:

    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 作為中心 Widget 在 QMainWindow :

    setCentralWidget(view);
}
					

當加載頁麵時, adjustLocation() 被觸發通過 loadFinished() 信號在 QWebEngineView 以更新地址欄:

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();
}
					

The 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();
}
					

此槽被觸發通過 titleChanged() 信號在 QWebEngineView .

當網頁已加載時, finishLoading() 方法被觸發通過 loadFinished() 信號在 QWebEngineView 。然後,方法更新標題欄中的進度並調用 runJavaScript() 以根據當前網頁評估 jQuery 庫:

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

這意味著可以把 JavaScript 視為內容的一部分加載到 QWebEngineView ,因此每當加載新頁麵時,都需要加載。一旦加載 jQuery 庫,就可以開始在瀏覽器中執行不同 jQuery 函數。

The rotateImages() function is then called explicitly to make sure that the images of the newly loaded page respect the state of the toggle action.

首個基於 jQuery 的函數 highlightAllLinks() ,旨在用來突齣顯示當前網頁中的所有鏈接。JavaScript 代碼查找 Web 元素名為 a (超鏈接標簽)。對於每個這種元素,通過使用 CSS 把背景色設為黃色:

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

The 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() 移除頁麵中的所有 GIF 圖像通過查找 src 屬性 (為網頁中的所有元素)。任何元素采用 gif 文件作為源被移除:

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

The removeInlineFrames() 方法移除所有 iframe 或內聯元素:

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

The removeObjectElements() 方法移除所有 object 元素:

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

The removeEmbeddedElements() 方法移除任何元素使用 embed 標簽 (如嵌入在頁麵中的插件):

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

範例工程 @ code.qt.io