QT窗口:透明与半透明、不规则异形窗口、控件透明与半透明、不规则异形按钮

目录

1、不规则异形窗口和控件的代码原理

2、主窗口全透明

3、主窗口半透明(以白里透红为例)

4、不规则异形窗口

5、不规则异形按钮

6、使用样式表实现透明与半透明


1、不规则异形窗口和控件的代码原理

步骤①:载入一个QPixmap图片,如果图片中某些位置带有全透明alpha通道,那么QPixmap::mask()就会根据全透明的位置生成掩码(注:生成的掩码类型为QBitmap),然后把掩码设置给QWidget控件,这时QWidget就会变成不规则的异形。

步骤②:这时的QWidget只是异形,背景还是原生的灰色,这时我们只需把前面用到的QPixmap作为背景图设置给QWidget即可。需要注意的是,显然我们应当保证背景图的大小和掩码的大小一致。

注意:一般我们使用的QPixmap图片与我们的窗体或控件,大小是不一致的,这时我们既可以让窗口或控件去适应图片的大小:QWidget.resize(pixmap.size()),也可以让图片去适应窗口或控件的大小:pixmap = pixmap.scaled(widget.size()),具体使用哪种,看你的需求。

设置背景图,推荐使用资源文件与样式表:border-image:url(:pic/a.png),在本文的应用场景中,同样是设置背景图,border-image 比 background-image 更合适,因为border-image会自动把图片拉伸充满控件,而background-image会把图片保持为原大小。

给不同控件设置背景图,QPushButton、QLabel等各有不同的方法,例如QPushbutton::setIcon()、QLabel::setPixmap(), QLabel::setPicture(),用起来不具备通用性,只有样式表是通用的。

如果背景图的显示效果,无法满足你的需求,请自行百度搜索:《QT实现背景图片多种填充方式:居中、平铺、缩放、拉伸

2、主窗口全透明

直接在UI的主窗口中,拖出几个控件,下图我放置了一个QPushButton按钮、QCheckBox复选框、设置了蓝色背景的QWidget。

然后用代码设置主窗体的透明:

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);//无边框
    this->setAttribute(Qt::WA_TranslucentBackground, true);//窗体背景全透明
//    setWindowOpacity(0.5);//这行代码会使主窗体及其所有的子控件整体半透明,见下图右
}

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

运行效果如下,左图所示。

       

可以看到,整个窗体背景实现了完全透明,只有控件是不透明的。如果我们设置了整体半透明(也即这行代码:setWindowOpacity(0.5)),那么控件窗口与控件都会呈现半透明,效果如上图右图所示。

总结:由上述示例代码可见,实现主窗体全透明,必须要同时做以下2项,缺一不可:①设置窗口无边框,②设置背景全透明

3、主窗口半透明(以白里透红为例)

本文由【暴躁的野生猿】发表于CSDN,非法转载请帮忙举报谢谢。

只需覆盖QWidget的paintEvent函数即可:

void MainWindow::paintEvent(QPaintEvent*event)
{
    QPainter p(this);
    //边框黑色不透明 (因为设置了窗体无边框,这行代码可能没有效果)
    p.setPen(QColor(0, 255, 0, 255));
    p.setBrush(QColor(255, 0, 0, 150));//填充红色半透明
    p.drawRect(this->rect());//绘制半透明矩形,覆盖整个窗体
    QWidget::paintEvent(event);
}

效果如下所示,代码原理就是,在主窗体背景全透的基础上,在主窗体上绘制了一个与之等大的半透明矩形。

总结:由上述示例代码可见,实现主窗体半透明,必须要同时做以下2项,缺一不可:①设置窗口无边框,②设置背景全透明,③覆盖QWidget的paintEvent函数并写半透明代码。

4、不规则异形窗口

准备一张带透明通道的PNG图片,(不会PS制作PNG的朋友可以用光影魔术手制作),下面我的示例中,我准备了2张PNG图片分别如下所示,其中第一张:局部全透明、整体半透明,第二张:局部全透明、其余位置不透明。
然后在设计师界面随意拖出两个控件。

      

#include "form.h"
#include "ui_form.h"
#include <QPixmap>
#include <QBitmap>
#include <QDebug>
#include <QPainter>

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

    this->setWindowFlags(Qt::FramelessWindowHint);//设置窗体无边框
    this->setAttribute(Qt::WA_TranslucentBackground);//设置窗体全透明
    pix.load(":/pic/qt2.png");//从资源文件载入图片
    pix = pix.scaled(size());//把载入的PNG图片缩放到与窗体一样大

}

void Form::paintEvent(QPaintEvent *e)
{
    Q_UNUSED(e)
    QPainter painter(this);//画笔以this窗体作为画布
    painter.drawPixmap(0, 0, pix);//从(0,0)开始在画布上绘制PNG图片
}

有上述代码可见,要实现不规则窗体,原理无非就是,先把窗口弄成全透明,然后在全透明的这个画布上绘制PNG图片。

      

可以看到,窗体整体呈现为不规则形状,而且透过上图的QT空心位置,可以点击到后面的文件,说明窗口真的是空心的。

5、不规则异形按钮

如下所示,随意拖出两个控件:一个QPushButton,一个QLabel。在本例中,给这2个控件设置异形,我将演示两种不同的方案:①让控件自适应图片的大小,②让图片自适应控件的大小.。这两种方案分别呈现的效果见下文图片。

   

素材为:,这种带透明通道的简易图形素材,用wps/word配合光影魔术手,很容易制作。

QPixmap arrowPix(":/pic/arrow.png");//从资源文件载入图片

    ui->pushButton->resize(arrowPix.size());//把按钮调整为和图片一样大
    ui->pushButton->setMask(arrowPix.mask());//根据alpha通道生成掩码,掩码让控件形成不规则形状(该行不会添加背景图)    
    ui->pushButton->setStyleSheet("background-image或border-image: url(:/pic/arrow.png)");//给按钮设置背景图

    arrowPix = arrowPix.scaled(ui->label->size());//把图片调整为和控件一样大
    ui->label->setMask(arrowPix.mask());
    ui->label->setStyleSheet("border-image: url(:/pic/arrow.png);");

效果:

6、使用样式表实现透明与半透明

所谓顶级窗口,就是其parent是nullptr的QWidget或其子类。

如果控件不是顶级窗口,直接使用样式表,就能实现各种透明和半透明。

如果控件是顶级窗口,要想用样式表实现透明或半透明效果,则必须做以下4项工作,缺一不可:① 无边框, ②背景全透, ③设置qss ,④覆盖painterEvent

XXX::XXX(QWidget *parent) : //构造
    QWidget(parent)
{
    setWindowFlags(windowFlags() | Qt::FramelessWindowHint);//无边框
    this->setAttribute(Qt::WA_TranslucentBackground, true);//窗体背景全透明
    this->setStyleSheet("border:none; background-color: rgba(255,0,0,200);");//设置样式表
}


/*继承了QWidget的控件,要使用qss,必须覆盖该函数*/
void XXX::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event)
    QStyleOption opt;
    opt.init(this);
    QPainter p(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &p, this);
}

样式表语法支持alpha通道:

任意一个QWidget,都可以直接设置:

background-color: rgba(10,20,30,40);

rgba的4个参数分别为Red Green Blue Alpha(0 =全透, 255=不透)

对于自己写的继承QWidget的子类,要使用样式表,必须要覆盖painterEvent,这是官方手册要求的,直接抄就行了:

  • 10
    点赞
  • 73
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值