libvlc视频播放器: 在播放界面上叠加自定义窗口

1,651 阅读2分钟

「这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战

一、功能需求介绍

libvlc支持两种方式开发,第一种是回调方式开发,第二种是传入窗口ID直接渲染。

回调方式开发可以拿到每一帧图像自己渲染,传入窗口ID的方式是libvlc内部直接控制窗体渲染。 如果采用传入窗口ID方式开发,想要使用常规的方式在播放器的窗口上直接加控件或者覆盖新窗口都行不通(继承关系都不行),因为将窗口ID传入进去之后,窗口的控制权就交给libvlc了。

在播放器窗口上叠加窗口可以显示很多自定义的一些提示内容,或者将播放器的控制按钮放在上面等等效果。

就像下面一样:

将播放器的控制菜单浮动在播放窗口上,全屏播放时操作比较方便,不影响看视频。 image.png

在调整音量、播放状态改变时,可以在窗口上弹出提示。 image.png

要达到这种效果,覆盖新窗口上去,只能使用子窗口形式,设置新窗口为透明属性,在主窗口的状态事件(移动、大小改变、重绘)里,设置覆盖窗口的大小,位置,让覆盖的窗口始终跟随在播放窗口上。

二、实现方式: 完整代码

最终的运行效果

(1). 未播放视频之前的效果 image.png

(2). 播放视频中的效果

image.png

image.png

image.png

2.1 form.cpp :附加上去的窗口

#include "form.h"
#include "ui_form.h"

Form::Form(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Form)
{
    ui->setupUi(this);

   //窗口无边框
   setWindowFlags(Qt::FramelessWindowHint|Qt::Window);
   //setAutoFillBackground(true);

   // 窗口透明
   this->setAttribute(Qt::WA_TranslucentBackground);
}

Form::~Form()
{
    delete ui;
}

void Form::paintEvent(QPaintEvent *pEvent)
{

    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式
}


2.2 form.h :附加上去的窗口

#ifndef FORM_H
#define FORM_H

#include <QWidget>
#include <QStyleOption>
#include <QPainter>
namespace Ui {
class Form;
}

class Form : public QWidget
{
    Q_OBJECT

public:
    explicit Form(QWidget *parent = nullptr);
    ~Form();
private:
    void paintEvent(QPaintEvent *pEvent);
private:
    Ui::Form *ui;
};

#endif // FORM_H

2.3 form.ui

附加的窗口上,设计了3个按钮和一个标签--显示一些提示文字。 image.png

image.png

2.4 widget.cpp 主窗口

主窗口代码里只贴出和本文问题相关的代码。

#include "widget.h"
#include "ui_widget.h"

Widget* Widget::pThis = nullptr;

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    pThis=this;

    ui->setupUi(this);

    //叠加的窗口
    form=new Form(this);
    form->setStyleSheet(QString("background-color: rgba(255, 0, 0, 0%);"));
    form->show();
	
	.....................
}


Widget::~Widget()
{
    delete ui;
}


//重载窗口移动事件
void Widget::moveEvent(QMoveEvent *event)
{
    QPoint pos_form=ui->widget->mapToGlobal(ui->widget->pos());
    form->move(pos_form);
    form->setGeometry(pos_form.x(),pos_form.y(),ui->widget->width(),ui->widget->height());
}


void Widget::paintEvent(QPaintEvent *pEvent)
{
    QStyleOption opt;
    opt.initFrom(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);//绘制样式

    QPoint pos_form=ui->widget->mapToGlobal(ui->widget->pos());
    form->move(pos_form);
    form->setGeometry(pos_form.x(),pos_form.y(),ui->widget->width(),ui->widget->height());
}

2.5 widget.h 主窗口

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <vlc/vlc.h>
#include <QDebug>
#include <QFileDialog>
#include <QMoveEvent>
#include "form.h"
#include <QTime>
#include <QThread>
#include <QTimer>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
     ...................
private slots:
     ...................
protected:
    ...................
    void moveEvent(QMoveEvent *event);
    void paintEvent(QPaintEvent *pEvent);
private:
    ...................

};
#endif // WIDGET_H