WebEngine Widgets视频播放器示例

使用QWebEngineView显示全屏视频。

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

全屏API是一个跨浏览器的JavaScript API,允许网页请求其中某个HTML元素占据用户的整个屏幕。它通常用于通过<video>元素进行全屏视频播放,但实际上可以用来在全屏模式下显示任何HTML内容。Qt WebEngine支持此API,但默认情况下是禁用的。此示例显示了切换该功能的步骤,包括

运行示例

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

概述

一旦启动,示例程序将创建一个带有QWebEngineView的正常(非全屏)窗口,显示嵌入的YouTube视频播放器。然后您可以点击全屏切换按钮(右下角)进入全屏模式。这还应显示一个居中的通知叠加层,通知您可以通过按Esc键退出全屏模式。

在实践中,进入全屏模式涉及创建一个带有单独的QWebEngineView实例的新全屏窗口,并将QWebEnginePage从正常窗口的QWebEngineView迁移到这个新的QWebEngineView。退出全屏模式将撤销迁移。

示例代码分为三个类,分别是MainWindowFullScreenWindowFullScreenNotification。类MainWindowFullScreenWindow各自负责管理一个顶层窗口,而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;
};

MainWindow类定义

在构造函数中,我们首先将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的全屏请求将被拒绝。

最后,我们将一些HTML(请参阅示例中包含的webenginewidgets/videoplayer/data/index.html)加载到我们的QWebEngineView

    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

© 2024 Qt公司有限公司。此处包含的文档贡献是各自所有者的版权。此处提供的文档是根据自由软件基金会发布的GNU自由文档许可证版本1.3的条款许可的。Qt及其相关标志是芬兰的Qt公司及其它国家/地区的trademarks。所有其他商标均为各自所有者的财产。