WebEngine 小工具视频播放器示例

使用QWebEngineView 显示全屏视频。

视频播放器演示了如何使用QWebEngineView 支持 HTML5 视频的全屏播放。

全屏 API是一个跨浏览器的 Javascript API,可让网页请求让其中一个 HTML 元素占据用户的整个屏幕。它通常通过<video> 元素用于全屏播放视频,但原则上也可用于以全屏模式显示任何 HTML 内容。Qt WebEngine 支持该 API,但默认情况下是禁用的。本示例展示了开启该 API 所需的步骤,包括

运行示例

运行示例 Qt Creator,打开Welcome 模式,并从Examples 中选择示例。有关详细信息,请参阅Qt Creator: 教程:构建并运行

概述

启动后,示例程序将创建一个普通(非全屏)窗口,其中QWebEngineView 显示一个嵌入式 YouTube 视频播放器。然后,您可以点击全屏切换按钮(右下角)进入全屏模式。这还会显示一个居中的通知覆盖图,告诉你可以按 Esc 键退出全屏模式。

从实现上讲,进入全屏模式需要创建一个新的全屏窗口,并使用单独的QWebEngineView 实例,然后将正常窗口的QWebEnginePage QWebEngineView 迁移到这个新的QWebEngineView 上。退出全屏模式则会逆转这种迁移。

示例代码分为三个类:MainWindowFullScreenWindowFullScreenNotificationMainWindowFullScreenWindow 分别负责管理一个顶级窗口,而FullScreenNotification 则负责通知框的样式和动画。MainWindow 在启动时创建,并在整个程序运行期间存在,而每次进入全屏模式时都会创建一个新的FullScreenWindow

MainWindow 类声明

MainWindow 是以QWebEngineView 为中心部件的QMainWindow

#include "fullscreenwindow.h"

#include <QMainWindow>
#include <QWebEngineView>
#include <QWebEngineFullScreenRequest>

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void fullScreenRequested(QWebEngineFullScreenRequest request);

private:
    QWebEngineView *m_view;
    QScopedPointer<FullScreenWindow> m_fullScreenWindow;
};

主窗口类定义

在构造函数中,我们首先将QWebEngineView 设置为中心部件:

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , m_view(new QWebEngineView(this))
{
    setCentralWidget(m_view);

然后,我们配置Qt WebEngine 以宣传对全屏 API 的支持:

    m_view->settings()->setAttribute(QWebEngineSettings::FullScreenSupportEnabled, true);

如果没有这一行,全屏切换按钮将被禁用(显示为灰色),因为页面上运行的 Javascript 可以检测到我们的浏览器不支持全屏模式。

接下来,我们将fullScreenRequested 信号连接到我们的槽:

    connect(m_view->page(),
            &QWebEnginePage::fullScreenRequested,
            this,
            &MainWindow::fullScreenRequested);

每当页面上的 Javascript 想要进入或退出全屏模式时,就会发出该信号。如果不处理该信号(但仍将FullScreenSupportEnabled 属性保留为true ),切换按钮将被启用,但由于 Javascript 的全屏请求将被拒绝,因此点击该按钮将没有任何效果。

最后,我们在QWebEngineView 中加载一些 HTML(见示例中的webenginewidgets/videoplayer/data/index.html ):

    m_view->load(QUrl(QStringLiteral("qrc:/index.html")));

MainWindow 的第二部分是处理全屏请求:

void MainWindow::fullScreenRequested(QWebEngineFullScreenRequest request)
{
    if (request.toggleOn()) {
        if (m_fullScreenWindow)
            return;
        request.accept();
        m_fullScreenWindow.reset(new FullScreenWindow(m_view));
    } else {
        if (!m_fullScreenWindow)
            return;
        request.accept();
        m_fullScreenWindow.reset();
    }
}

我们在进入全屏模式时创建一个新的FullScreenWindow ,并在退出时删除它。

FullScreenWindow 类声明

FullScreenWindow 是一个包含QWebEngineViewFullScreenNotificationQWidget

#include <QWidget>

QT_BEGIN_NAMESPACE
class QWebEngineView;
QT_END_NAMESPACE

class FullScreenNotification;

class FullScreenWindow : public QWidget
{
    Q_OBJECT
public:
    explicit FullScreenWindow(QWebEngineView *oldView, QWidget *parent = nullptr);
    ~FullScreenWindow();

protected:
    void resizeEvent(QResizeEvent *event) override;

private:
    QWebEngineView *m_view;
    FullScreenNotification *m_notification;
    QWebEngineView *m_oldView;
    QRect m_oldGeometry;
};

FullScreenWindow 类定义

构造函数负责隐藏普通窗口(同时保存其几何图形),并显示新的FullScreenWindow

FullScreenWindow::FullScreenWindow(QWebEngineView *oldView, QWidget *parent)
    : QWidget(parent)
    , m_view(new QWebEngineView(this))
    , m_notification(new FullScreenNotification(this))
    , m_oldView(oldView)
    , m_oldGeometry(oldView->window()->geometry())
{
    m_view->stackUnder(m_notification);

    auto exitAction = new QAction(this);
    exitAction->setShortcut(Qt::Key_Escape);
    connect(exitAction, &QAction::triggered, [this]() {
        m_view->triggerPageAction(QWebEnginePage::ExitFullScreen);
    });
    addAction(exitAction);

    m_view->setPage(m_oldView->page());
    setGeometry(m_oldGeometry);
    showFullScreen();
    m_oldView->window()->hide();
}

调用QWebEngineView::setPage 会将网页从MainWindow 的视图移至FullScreenWindow 的视图。

在析构函数中,我们使用相同的方法将网页移回,然后恢复主窗口的几何形状和可见性:

FullScreenWindow::~FullScreenWindow()
{
    m_oldView->setPage(m_view->page());
    m_oldView->window()->setGeometry(m_oldGeometry);
    m_oldView->window()->show();
    hide();
}

我们重载QWidget::resizeEvent 进行手动布局,保持QWebEngineView 最大化,并将FullScreenNotification 置于窗口中央:

void FullScreenWindow::resizeEvent(QResizeEvent *event)
{
    QRect viewGeometry(QPoint(0, 0), size());
    m_view->setGeometry(viewGeometry);

    QRect notificationGeometry(QPoint(0, 0), m_notification->sizeHint());
    notificationGeometry.moveCenter(viewGeometry.center());
    m_notification->setGeometry(notificationGeometry);

    QWidget::resizeEvent(event);
}

FullScreenNotification 类声明

FullScreenNotification 只是一个带有一些样式和动画的QLabel

#include <QLabel>

class FullScreenNotification : public QLabel
{
    Q_OBJECT
public:
    FullScreenNotification(QWidget *parent = nullptr);

protected:
    void showEvent(QShowEvent *event) override;

signals:
    void shown();

private:
    bool m_previouslyVisible;
};

FullScreenWindow 类定义

在构造函数中,我们配置了QLabel ,并使用动画框架设置了延迟淡出动画:

FullScreenNotification::FullScreenNotification(QWidget *parent)
    : QLabel(parent)
    , m_previouslyVisible(false)
{
    setText(tr("You are now in full screen mode. Press ESC to quit!"));
    setStyleSheet(
        "font-size: 24px;"
        "color: white;"
        "background-color: black;"
        "border-color: white;"
        "border-width: 2px;"
        "border-style: solid;"
        "padding: 100px");
    setAttribute(Qt::WA_TransparentForMouseEvents);

    auto effect = new QGraphicsOpacityEffect;
    effect->setOpacity(1);
    setGraphicsEffect(effect);

    auto animations = new QSequentialAnimationGroup(this);
    animations->addPause(3000);
    auto opacityAnimation = new QPropertyAnimation(effect, "opacity", animations);
    opacityAnimation->setDuration(2000);
    opacityAnimation->setStartValue(1.0);
    opacityAnimation->setEndValue(0.0);
    opacityAnimation->setEasingCurve(QEasingCurve::OutQuad);
    animations->addAnimation(opacityAnimation);

    connect(this, &FullScreenNotification::shown,
            [animations](){ animations->start(); });

    connect(animations, &QAbstractAnimation::finished,
            [this](){ this->hide(); });
}

自定义信号shown 用于触发动画,由showEvent 方法发出:

void FullScreenNotification::showEvent(QShowEvent *event)
{
    QLabel::showEvent(event);
    if (!m_previouslyVisible && isVisible())
        emit shown();
    m_previouslyVisible = isVisible();
}

示例项目 @ code.qt.io

© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.