Qt视频播放窗口叠加透明窗口

前言

本人在做一个视频监控项目时,遇到了透明窗口无法透明的问题,特记录下解决过程。

更新:经测试,本文提到的方法用于多分屏复杂的视频播放窗口时有问题。


目录

前言

一、需求

二、关键代码

2.1、透明窗口设置

2.1.1、构造函数中调用以下代码

2.1.2、重载paintEvent事件

2.2、视频播放窗口设置

2.2.1、调用透明窗口

2.2.2、透明窗口位置及大小自适应视频窗口

2.2.3、坐标转换

 三、所有源码

3.1、透明窗口

3.2、视频播放窗口


一、需求

在视频播放界面上,叠加一个透明窗口,实现拉框局部放大功能。

本来以为这个很简单,直接给窗口加一个透明设置项就行,但最终发现,在未播放视频时,窗口确实是透明的,但是当开始播放视频后,窗口就不透明了,特此记录下本人最终的解决办法。

先看下效果图:

二、关键代码

2.1、透明窗口设置

2.1.1、构造函数中调用以下代码

setAttribute(Qt::WA_TranslucentBackground, true);
setWindowFlags(Qt::SplashScreen|Qt::FramelessWindowHint);

第一行,使透明背景生效,透明背景在paintEvent中设置;

第二行,Qt::SplashScreen,启动画面,原本使用的Qt::ToolTip标签,但是这个会导致窗口一直置顶,所以换成了Qt::SplashScreen。Qt::FramelessWindowHint让窗口无边框,窗口如果是其它控件的子控件,这句也可以不要;

2.1.2、重载paintEvent事件

void DigitalZoom::paintEvent(QPaintEvent *event){
    QPainter painter(this);
    painter.fillRect(this->rect(), QColor(0, 0, 0, 1));
}

2.2、视频播放窗口设置

2.2.1、调用透明窗口

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

    m_digitalZoomWidget = new DigitalZoom(this);
    m_digitalZoomWidget->show();
}

2.2.2、透明窗口位置及大小自适应视频窗口

使用Qt::SplashScreen后,透明窗口的位置和大小就和其父窗口没有关系了,需要对位置进行转换,我这里因为透明窗口的父类是视频播放窗口,所以在视频播放窗口类中重载了moveEvent和resizeEvent事件。

void mainWidget::resizeEvent(QResizeEvent *event)
{
    m_digitalZoomWidget->resize(width(),height());
}

void mainWidget::moveEvent(QMoveEvent *event)
{
    m_digitalZoomWidget->move(geometry().x(),geometry().y());
}

2.2.3、坐标转换

本人因为需要实现数字放大功能,所以需要转换拉框坐标,这里就不列出了。


 三、所有源码

3.1、透明窗口

digitalzoom.h

#ifndef DIGITALZOOM_H
#define DIGITALZOOM_H

#include <QWidget>

class DigitalZoom : public QWidget
{
    Q_OBJECT
public:
    explicit DigitalZoom(QWidget *parent = nullptr);

protected:
    void paintEvent(QPaintEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;

signals:

public slots:

private:
    QPoint m_startPoint; /* 鼠标按下位置 */
    QPoint m_endPoint;  /* 鼠标移动后的位置 */
    bool m_bIsLeftMousePressMove = false; /* 鼠标左键按下移动标志 */
};

#endif // DIGITALZOOM_H

digitalzoom.cpp

#include "digitalzoom.h"
#include <QPainter>
#include <QPaintEvent>
#include <QLabel>

DigitalZoom::DigitalZoom(QWidget *parent) : QWidget(parent)
{
    setAttribute(Qt::WA_TranslucentBackground, true);
    setWindowFlags(Qt::SplashScreen|Qt::FramelessWindowHint);

    QLabel* upLab = new QLabel("我是透明窗口上的不透明控件",this);
    upLab->setStyleSheet("color:red");
}

void DigitalZoom::paintEvent(QPaintEvent *event){
    QPainter painter(this);
    if(m_bIsLeftMousePressMove){
        painter.setRenderHint(QPainter::Antialiasing, true);
        painter.setPen(QPen(QColor(0, 160, 230), 5));
        painter.drawRect(event->rect());
    }else{
        painter.fillRect(this->rect(), QColor(0, 0, 0, 1));
    }
}

void DigitalZoom::mousePressEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton)
    {
        m_startPoint = event->pos();
    }

    QWidget::mousePressEvent(event);
}

void DigitalZoom::mouseMoveEvent(QMouseEvent *event)
{
    if(event->buttons() & Qt::LeftButton){
        m_endPoint = event->pos();
        m_bIsLeftMousePressMove = true;
        update(QRect(m_startPoint,m_endPoint));
    }
}

void DigitalZoom::mouseReleaseEvent(QMouseEvent *event)
{
    if(m_bIsLeftMousePressMove){
        m_bIsLeftMousePressMove = false;
    }

    update();
}

3.2、视频播放窗口

 mainWidget.h

#ifndef MAINWIDGET_H
#define MAINWIDGET_H

#include <QWidget>
#include "digitalzoom.h"

namespace Ui {
class mainWidget;
}

class mainWidget : public QWidget
{
    Q_OBJECT

public:
    explicit mainWidget(QWidget *parent = nullptr);
    ~mainWidget();

protected:
    void resizeEvent(QResizeEvent *event) override;
    void moveEvent(QMoveEvent *event) override;

private:
    Ui::mainWidget *ui;
    DigitalZoom* m_digitalZoomWidget;
};

#endif // MAINWIDGET_H

mainWidget.cpp

#include "mainwidget.h"
#include "ui_mainwidget.h"

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

    /* play video start */
    //此处测试在当前窗口上通过winId()获取窗口句柄来播放视频
    /* play video stop */

    m_digitalZoomWidget = new DigitalZoom(this);
    m_digitalZoomWidget->show();
}

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

void mainWidget::resizeEvent(QResizeEvent *event)
{
    m_digitalZoomWidget->resize(width(),height());
}

void mainWidget::moveEvent(QMoveEvent *event)
{
    m_digitalZoomWidget->move(geometry().x(),geometry().y());
}

 mainWidget.ui

默认生成,未作任何修改。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

秦时小

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值