Qt 半透明背景(遮罩)

简述

前些天从嵌入式Linux Qt4 切换到嵌入式Linux Qt5 开发平台,发现遮罩不能用了,原本半透明的背景变成了黑色,全网找遍资料,没有特别好的解决方案,无奈自己手撸撸一个,且测亲测好用。

测试环境

  • Qt5.6.2
  • Linux 4.1
  • Arm

方案一

透明背景只是显示在父窗口上,不能遮住整个屏幕,不理想

QFrame *f = new QFrame(this);
f->setGeometry(100,100,100,1280);
f->setStyleSheet("QFrame{background-color: rgba(0,0,0, 177);}");
f->show();

方案二

这种在amr 上不生效,在pc 上没问题,不过这个是整个QFrame 对象,包括子窗口统一透明处理

#ifndef __arm__

QFrame *f = new QFrame ();
f->setGeometry(200,100,100,1280);
QPalette p = f->palette();
p.setBrush(QPalette::Background, QColor(0,0,0));
f->setPalette(p);
f->setWindowOpacity(0.7f);
f->show();

#endif

方案三

这种和第一种差不多,但是透明背景是用的Dialog
并且 this 的第一个祖先必须是全屏的,否则遮罩(Dialog)显示区域就是遮罩父对象的区域

// arm pc 都有效
QDialog d(this->topLevelWidget()); //获得这个窗口最顶层的父对象
//d.setGeometry(300,100,100,1280);
d.setWindowFlags(Qt::FramelessWindowHint); //在arm 上,如果不去掉标题栏,背景会变成黑色
d.setStyleSheet("QDialog{background-color: rgba(0,0,0,50%);}");
d.exec();

方案四

arm linux 有效,pc 未测试,不过应该大同小异,思路如下

  • 截取全屏,用黑色半透明笔刷给图片上色
  • 根据遮罩的几何位置,显示对应图片的位置
// ShadowFrame.h
#ifndef SHADOWFRAME_H
#define SHADOWFRAME_H

#include 

class ShadowFrame : public QWidget
{
    Q_OBJECT

    explicit ShadowFrame(QWidget *parent = nullptr);
    ~ShadowFrame();
public:
    static ShadowFrame *instance();
    //设置遮罩位置和遮罩大小,并刷新遮罩
    void updateShadow();
    void updateShadow(int x, int y, int w, int h);
    void updateShadow(const QRect &rect);

    // QWidget interface
protected:
    virtual void paintEvent(QPaintEvent *event);
    QPixmap mPixmap;
};

#endif // SHADOWFRAME_H

// ShadowFrame.cpp
#include "ShadowFrame.h"

#include 
#include "MyDebug.h"
#include 
#include 
#include 

ShadowFrame::ShadowFrame(QWidget *parent) :
    QWidget(parent)
{
    this->setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
    this->mPixmap = QPixmap(qApp->desktop()->size());
    this->mPixmap.fill(Qt::red);
}

ShadowFrame::~ShadowFrame()
{
}

ShadowFrame *ShadowFrame::instance()
{
    static ShadowFrame w;
    return &w;
}

void ShadowFrame::updateShadow()
{
    QSize size = qApp->desktop()->size();
    updateShadow(0, 0, size.width(), size.height());
}

void ShadowFrame::updateShadow(int x, int y, int w, int h)
{
    updateShadow(QRect(x, y, w, h));
}

void ShadowFrame::updateShadow(const QRect &rect)
{
    this->setGeometry(rect);
    QScreen *screen = QApplication::primaryScreen();
    QPixmap pixmap = screen->grabWindow(0); //截屏全屏
    QPainter p(&mPixmap);
    {
#if 01  // 由于我的应用程序在显示时旋转了270度,所以获取到的图片是横向的,需要调整坐标并旋转。没有这个需求的将编译选项就改为 0 可正常使用
        p.save();
        p.translate(pixmap.height(), 0);
        p.rotate(90);
        p.drawPixmap(0,0, pixmap);
        p.restore();
#else
        p.drawPixmap(0,0, pixmap);
#endif
    }
    p.fillRect(mPixmap.rect(), QColor(0, 0, 0, 150)); //黑色半透明笔刷

    update();
}

void ShadowFrame::paintEvent(QPaintEvent *)
{
    QPainter p(this);
    p.drawPixmap(QPoint(0, 0), mPixmap, geometry());
    p.setBrush(Qt::blue);
}

#include "MainWindow.h"

#include 
#include 
#include "ShadowFrame.h"

int main(int argc, char *argv[])
{
	QApplication a(argc, argv);
	
    ShadowFrame::instance()->updateShadow();
    ShadowFrame::instance()->show();
    
    QWidget *w = new QWidget(/*ShadowFrame::instance()*/);
    w->setAttribute(Qt::WA_DeleteOnClose);
    //w->setStyleSheet("background-color: rgb(114, 159, 207);");
    w->setGeometry(200, 300, 400, 400);
    
    QPushButton *btn = new QPushButton(w);
    btn->setGeometry(100, 100, 100, 100);
    btn->setText("点我在");
    connect(btn, &QPushButton::clicked, []{
        qDebug("点击成功");
    });    
    w->show();
    w->raise(); //将窗口置顶
	
	return a.exec();
}

示例图

Qt 半透明背景(遮罩)_第1张图片

你可能感兴趣的:(Qt)