关于在Qlabel遮罩方面的踩坑实录

先看目标效果:

想要实现封面图标的遮罩效果,有两个思路:

一、在鼠标移动到这个item上面时,重新绘制pixmap

例如以下代码:

#include <QApplication>
#include <QWidget>
#include <QPixmap>
#include <QLabel>
#include <QPainter>
#include <QColor>

class TransparentOverlayWidget : public QWidget
{
public:
    TransparentOverlayWidget(QWidget *parent = nullptr) : QWidget(parent)
    {

        // 创建 QLabel 来显示带有半透明矩形的图像
        label = new QLabel(this);
        label->setFixedSize(500,500);
        label->setScaledContents(true);
    }
    void paintEvent(QPaintEvent *event) override {
        QWidget::paintEvent(event);
        pixmap = QPixmap("background.jpg");

        // 创建QPainter并在QPixmap上绘制
        QPainter painter(&pixmap);

        // 设置半透明度,0.0为完全透明,1.0为完全不透明
        painter.setOpacity(0.5);

        // 设置绘制颜色,带有透明度
        painter.setBrush(QColor(255, 0, 0, 127)); // 透明度为127,最大值是255
        painter.setPen(Qt::NoPen);
        if(m_isHover) {
            // 绘制一个半透明矩形
            painter.drawRect(50, 50, 200, 150);
        }

        // 完成绘制
        painter.end();
        label->setPixmap(pixmap);
    }
    void enterEvent(QEnterEvent *event) {
        QWidget::enterEvent(event);
        m_isHover = true;
        qDebug()<<"进入widget";
        update();
    }
    void leaveEvent(QEvent *event) {
        QWidget::leaveEvent(event);
        m_isHover = false;
        qDebug()<<"离开widget";
        update();
    }
private:
    bool m_isHover  = false;
    QLabel *label{};
    QPixmap pixmap;
};

int main(int argc, char *argv[])
{
    QApplication app(argc, argv);

    TransparentOverlayWidget widget;
    widget.show();

    return app.exec();
}

值得注意的是:pixmap = QPixmap("background.jpg");这行代码的位置的考究。。。

每次绘制前重新初始化 :若是将这行代码放在构造函数里面就起不到透明的效果。原因如下:
确保在每次 paintEvent 时,QPixmap 都是初始的未被修改的图像,而不是之前被修改的版本。否则你可能会在一个已经绘制了半透明矩形的 QPixmap 上再次绘制半透明矩形,这会导致透明度的叠加不正确。

 二、新建Mask的QWidget类

Mask.h:

//
// Created by WeiWang on 24-9-18.
//

#ifndef MASK_H
#define MASK_H
#include<QWidget>
#include<QPainter>

class Mask : QWidget
{
public:
    Mask(QWidget *parent = nullptr):QWidget(parent) {
        setWindowFlags(Qt::FramelessWindowHint);
        this->setFixedSize(100,100);
    }
    void paintEvent(QPaintEvent *event) {
        QPainter painter(this);
        QColor color(0,0,0,160);
        // 设置绘制颜色,带有透明度
        painter.setBrush(color);
        painter.setPen(Qt::NoPen);
        painter.fillRect(rect(),color);
    }

    void move_(int x,int y){this->move(x,y);};
    void hide_(){ this->hide();};
    void show_(){ this->show();};
    void raise_(){ this->raise();};
};


#endif //MASK_H

main.cpp:

 #include <QApplication>
 #include <QWidget>
 #include <QPixmap>
 #include <QLabel>
 #include <QPainter>
 #include <QColor>
 #include "Mask.h"
 class TransparentOverlayWidget : public QWidget
 {
 public:
     TransparentOverlayWidget(QWidget *parent = nullptr)
     : QWidget(parent)
     {
         this->setFixedSize(500,500);
         // 加载图像
         QPixmap pixmap("F:\\code_review\\Qt-WorkSpace\\fight\\KuGouApp\\KuGouStart\\Res\\tabIcon\\music-cover.jpg");

         // 创建 QLabel 来显示带有半透明矩形的图像
         label = new QLabel(this);
         label->move(100,100);
         label->setScaledContents(true);
         label->setPixmap(pixmap);
         label->setFixedSize(100,100);
         label->setAlignment(Qt::AlignCenter);
         m_mask = new Mask(this);
         m_mask->move_(100,100);
         m_mask->hide_();
     }
     void paintEvent(QPaintEvent *event)override {
         if(this->m_isHover) {
             m_mask->show_();
            //m_mask->raise_();
         }
         else
             m_mask->hide_();
     }
     void enterEvent(QEnterEvent *event) {
         QWidget::enterEvent(event);
         qDebug()<<"进入widget";
         m_isHover = true;
         update();
     }
     void leaveEvent(QEvent *event) {
         QWidget::leaveEvent(event);
         qDebug()<<"离开widget";
         m_isHover = false;
         update();
     }
 private:
     QLabel *label{};
     bool m_isHover = false;

     Mask *m_mask{};
 };

 int main(int argc, char *argv[])
 {
     QApplication app(argc, argv);

     TransparentOverlayWidget widget;
     widget.show();

     return app.exec();
}

注意:此处有两个坑

①mask的初始化位置:

 一旦使用了如上图所示的初始化顺序,即先初始化mask再初始化lab,那么到了后面遮罩会被label挡住,原因如下:

在 Qt 中,子控件的绘制顺序遵循父控件的层次结构和堆叠顺序。默认情况下,父控件的子控件会按照其创建的顺序绘制。因此,如果 MaskTransparentOverlayWidget 的子控件,并且在层次结构中比 QLabel 更早创建或被覆盖,那么 QLabel 会在 Mask 之上绘制,导致 Mask 被遮住。

所以一定要让mask的初始化在label之后。

② 硬要在构造列表初始化

如果一定要在构造列表初始化的话,那么就需要使用

Mask 设置为在最顶层显示: 使用 raise() 函数将 Mask 移到顶层。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值