You need to enable JavaScript to run this app. Qt5如何在支持透明效果的QVideoWidget上使用paintEvent绘制内容
优惠活动
大模型
产品
解决方案
定价
更多

Qt5如何在支持透明效果的QVideoWidget上使用paintEvent绘制内容

Qt5 QVideoWidget播放RTSP流叠加标注无遮挡解决方案

问题根本原因

QVideoWidget的视频渲染默认走独立硬件加速管线,和普通QWidget的软件渲染管线分离,直接叠加控件、或者绘制时未先渲染视频帧的情况下,就会出现标注遮挡视频、透明属性失效穿透到桌面的问题。你之前添加的Qt::WA_X11OpenGLOverlay属性会绕过窗口管理器合成逻辑,直接渲染到屏幕最底层,不适合当前场景,直接删除该行代码即可。

推荐解决方案

方案一:改用QGraphicsVideoItem+QGraphicsView架构(兼容性最好)

该架构原生支持多层元素分层渲染,是Qt官方推荐的视频叠加标注实现方案,适配全平台,不会出现遮挡问题:

  • 初始化场景、视图,关闭视图默认背景,开启全视口更新
  • 底层添加QGraphicsVideoItem作为视频输出载体,绑定到你的QMediaPlayer实例
  • 标注可以通过自定义QGraphicsItem添加到场景上层,也可以重写QGraphicsView的paintEvent直接绘制
    核心示例代码:
// 初始化图形场景和视图
QGraphicsScene *scene = new QGraphicsScene(this);
QGraphicsView *videoView = new QGraphicsView(scene, this);
videoView->setStyleSheet("background: transparent;");
videoView->setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
videoView->show();

// 添加视频渲染项
QGraphicsVideoItem *videoItem = new QGraphicsVideoItem();
scene->addItem(videoItem);
// 你的QMediaPlayer实例绑定视频输出
mediaPlayer->setVideoOutput(videoItem);

// 上层绘制标注示例:重写QGraphicsView的paintEvent
void CustomGraphicsView::paintEvent(QPaintEvent *event)
{
    QGraphicsView::paintEvent(event);
    QPainter painter(viewport());
    painter.setPen(QPen(Qt::red, 3));
    painter.drawText(50,50,"自定义标注");
    painter.drawRect(100,100,300,200);
}

方案二:子类化QVideoWidget重写paintEvent

如果要保留QVideoWidget的使用方式,直接继承QVideoWidget重写绘制逻辑即可,注意必须先调用父类的paintEvent渲染视频帧,再绘制标注:

  1. 自定义子类继承QVideoWidget,重写paintEvent方法
  2. 关闭QVideoWidget的自动背景填充,必要时关闭WA_PaintOnScreen属性强制走统一绘制管线
    核心示例代码:
// 自定义视频控件类
class CustomVideoWidget : public QVideoWidget
{
    Q_OBJECT
public:
    CustomVideoWidget(QWidget *parent = nullptr) : QVideoWidget(parent) {
        setAutoFillBackground(false);
        setAttribute(Qt::WA_PaintOnScreen, false);
    }
protected:
    void paintEvent(QPaintEvent *event) override
    {
        // 先调用父类方法渲染底层视频帧
        QVideoWidget::paintEvent(event);
        // 再在上层绘制自定义标注
        QPainter painter(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(QPen(Qt::green, 2));
        painter.drawEllipse(200,200,100,100);
    }
};

写完之后将UI文件中的默认QVideoWidget提升为CustomVideoWidget类即可。

方案三:QLabel叠加适配(兼容性一般)

如果一定要用叠加QLabel的实现方式,需要给QLabel开启透明背景属性,重写QLabel的paintEvent避免填充背景:

QLabel *overlayLabel = new QLabel(ui->videoWidget);
overlayLabel->resize(ui->videoWidget->size());
// 开启透明背景
overlayLabel->setAttribute(Qt::WA_TranslucentBackground);
overlayLabel->setStyleSheet("background-color: transparent;");
overlayLabel->show();

// 重写QLabel的paintEvent绘制标注
void CustomLabel::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    QPainter painter(this);
    painter.setPen(Qt::blue);
    painter.drawText(100,100,"叠加层标注");
}

该方案在部分开启强硬件加速的平台可能依然存在透明失效问题,优先选择前两个方案。

内容的提问来源于stack exchange,提问作者Przemysław Wojcik

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.22 03:54:08