【PyQt】(自定义类)阴影遮罩-升级版

这是之前发的代码(自定义类)阴影遮罩的升级版。
升级就升级在,优化了对非矩形控件的遮盖效果,例如圆角按钮,以及默认方法不满足时可以传入其他的遮盖方法。



自定义阴影遮罩Mask:

class Mask(QWidget):
    __exclude=None
    __color=None
    clicked=pyqtSignal(object)#单击遮罩时触发,以实现其他操作
    def __init__(self,parent=None,*exclude,color=QColor(0,0,0,128)):
        super().__init__(parent)
        exclude=list(exclude)
        for pst in range(len(exclude)):
            if(type(exclude[pst])!=tuple):
                exclude[pst]=(exclude[pst],self.Trans_WidMask_Default)
            else:
                if(len(exclude[pst])<2):
                    exclude[pst]=(exclude[pst][0],self.Trans_WidMask_Default)
                elif(type(exclude[pst][1])==bool):
                    if(exclude[pst][1]==False):
                        exclude[pst]=(exclude[pst][0],self.Trans_WidMask_Default)
                    else:
                        exclude[pst]=(exclude[pst][0],self.Trans_WidMask_Style)
        self.__exclude=exclude
        self.__color=color
        self.show()
        self.__wid=QWidget()
    def mousePressEvent(self,event):
        self.clicked.emit(self)
    def paintEvent(self,event):
        self.resize(self.parent().size())
        bit=QBitmap(self.size())
        bit.fill(Qt.black)
        painter_bit=QPainter(bit)
        for item,offset in self.__Get_Offset().items():
            wid,trans=item
            pix=trans(wid)
            # pix=self.Trans_WidMask_Default(wid)
            # pix=self.Trans_WidMask_Style(wid)
            painter_bit.drawPixmap(QRect(offset,wid.size()),pix)
        painter_bit.end()

        painter_self=QPainter(self)
        painter_self.fillRect(0,0,self.size().width(),self.size().height(),self.__color)
        painter_self.end()
        self.setMask(bit)
    def __Get_Offset(self):
        record={}
        parent_self=self.parent()
        for item in self.__exclude:
            if(not item[0].isVisible()):
                continue
            wid=item[0]
            parent_wid=wid.parent()
            offset=QPoint(0,0)
            while (True):
                offset+=wid.pos()
                if(not parent_wid):
                    break
                if(parent_wid==parent_self):
                    break
                wid=wid.parent()
                parent_wid=wid.parent()
            if(parent_wid):
                record[item]=offset
        return record

    @classmethod
    def Trans_WidMask_Default(self,wid):
        pix=QPixmap(wid.size())
        pix.fill(Qt.white)
        return pix
    @classmethod
    def Trans_WidMask_Style(self,wid):
        arr=self.Trans_PixToArray(wid.grab())
        #洪填,将外围填充
        arr=cv2.cvtColor(arr,cv2.COLOR_RGBA2GRAY)
        h, w = arr.shape[:2]
        mask = np.zeros([h+2, w+2],np.uint8)
        arr_copy=arr.copy()
        arr=cv2.rectangle(arr,(0,0),(w-1,h-1),(int(arr[0][0]),))
        cv2.floodFill(arr, mask, (0,0), (0,), (2,), (2,), cv2.FLOODFILL_FIXED_RANGE)#参数是试出来的...懒得研究洪填
        arr=arr==arr_copy
        arr=arr*255
        arr=arr.astype(np.uint8)
        return self.Trans_ArrayToPix(arr)
    @staticmethod
    def Trans_PixToArray(pix):#pix是RGBA四通道QPixmap。不使用PIL.Image模块
        h,w=pix.height(),pix.width()
        buffer = QImage(pix).constBits()
        buffer.setsize(h*w*4)
        arr = np.frombuffer(buffer, dtype=np.uint8).reshape((h,w,4))
        return arr.copy()
    @staticmethod
    def Trans_ArrayToPix(arr):#arr对应四通道图片。不使用PIL.Image模块
        arr=cv2.cvtColor(arr,cv2.COLOR_RGBA2BGRA)
        img=QImage(arr.data, arr.shape[1], arr.shape[0], arr.shape[1]*4, QImage.Format_RGBA8888)
        return QPixmap(img)


测试代码+运行结果:


if __name__=='__main__':
    import sys
    from PyQt5.QtWidgets import QApplication

    app = QApplication(sys.argv)

    lb_1=QPushButton("ABCDE")
    lb_1.setStyleSheet("font-size:150px ; border:2px groove gray;border-radius:50px;padding:2px 4px;border-style: outset;}"
                                           "QPushButton{background-color: rgb(0, 224, 224);}"
                                           "QPushButton:hover{background-color:rgb(0, 255, 255); color: black;}"
                                           "QPushButton:pressed{background-color:rgb(0, 192, 192);border-style: inset;")

    lb_2=QPushButton("PQRST")
    lb_2.setStyleSheet("font-size:150px ; background-color:#FF0000")

    lb_3=QPushButton("XYZ",lb_2)
    lb_3.setStyleSheet("font-size:50px ; background-color:#FFFF00")

    win=QWidget()
    vbox=QVBoxLayout(win)
    vbox.addWidget(lb_1)
    vbox.addStretch(1)
    vbox.addWidget(lb_2)
    win.show()
    win.resize(755,400)


	#【创建阴影遮罩】
    # msk=Mask(win,lb_1,lb_2,color=QColor(0,0,0,192))
    # msk=Mask(win,lb_1,lb_3,color=QColor(0,0,0,192))
    msk=Mask(win,(lb_1,True),lb_3,color=QColor(0,0,0,192))
    # msk.setParent(None)
    msk.clicked.connect(lambda msk:msk.hide())#单击隐藏遮罩

    sys.exit(app.exec())

运行结果

说明:

  1. 与前篇文章(自定义类)阴影遮罩的用法大致一致,是“即用即贴”型,不用时就调用msk.setParent(None)撤走即可。
  2. 简单说明Mask的构造函数Mask(parent=None,*exclude,color=QColor(0,0,0,128))
    exclude元素可以有4种样式:wid、(wid,False)、(wid,True)、(wid,Func),其中wid等价于(wid,False)。
    exclude元素的第二参数如果为False那么将对应调用Mask.Trans_WidMask_Default[普通型],为True将调用Mask.Trans_WidMask_Style[样式表型],当这两种方法都不能满足遮盖需求时,即可自己编写第三种方法并将第二参数设置为该函数。
    上面的说明看不懂没关系,试着运行下测试代码就知道了。
  3. 遮罩单击时会触发clicked信号,用于实现“点击空白位置以取消”的操作。(感觉还不够用的话就自己改Mask代码吧


参考:

  • (自定义类)阴影遮罩:https://blog.csdn.net/weixin_44733774/article/details/134587980
  • QPixmap与numpy.array互转:https://blog.csdn.net/weixin_44733774/article/details/134578487
  • OpenCV中floodfill的使用(洪水填充):https://blog.csdn.net/remakeprogramer/article/details/113724635

未经本人同意不得私自转载。本文发布于CSDN:https://blog.csdn.net/weixin_44733774/article/details/134609775

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/190981.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【中间件】消息队列中间件intro

中间件middleware 内容管理 introwhy use MQMQ实现漫谈主流消息队列QMQ IntroQMQ架构QMQ 存储模型 本文还是从理论层面分析消息队列中间件 cfeng现在处于理论分析阶段&#xff0c;以中间件例子&#xff0c;之前的blog对于中间件是从使用角度分享了相关的用法&#xff0c;现在就…

带你用uniapp从零开发一个仿小米商场_9. 轮播图组件封装及使用

导航栏有了,接下来就是轮播图了,轮播图如下, 因为uniapp 官方自己有轮播图,所以这里就不自己写了,直接使用uniapp的轮播图二次开发就好 uniapp的轮播图组件叫swiper ,感兴趣的朋友可以点击链接,直接去看官方文档,也可以看我这里实操 用hbuilderX编译uniapp的代码有一个好处…

FO-like Transformation

参考文献&#xff1a; [RS91] Rackoff C, Simon D R. Non-interactive zero-knowledge proof of knowledge and chosen ciphertext attack[C]//Annual international cryptology conference. Berlin, Heidelberg: Springer Berlin Heidelberg, 1991: 433-444.[BR93] Bellare M…

枚举的第一行

2023年11月26日 问题: 好奇enum的所声明的枚举类的第一行是什么 从java技术卷1中第五章5.6中,了解是枚举类的实例 验证 错误信息: 解释: 此时只有有参构造 在这个枚举类里不能使用空,大概意思是说不能使用空参创建实例 校验 在原有的基础上创建一个无参构造 结果:不再报错,第…

常见树种(贵州省):019滇白珠、杜茎山、苍山越桔、黄背越桔、贵州毛柃、半齿柃、钝叶柃、细枝柃、细齿叶柃木、土蜜树、山矾、胡颓子、檵木

摘要&#xff1a;本专栏树种介绍图片来源于PPBC中国植物图像库&#xff08;下附网址&#xff09;&#xff0c;本文整理仅做交流学习使用&#xff0c;同时便于查找&#xff0c;如有侵权请联系删除。 图片网址&#xff1a;PPBC中国植物图像库——最大的植物分类图片库 一、滇白珠…

电路 buck-boost相关知识

BUCK-BOOST 文章目录 BUCK-BOOST前言一、DC-DC工作模式电容电感特性伏秒积平衡原理 二、BUCK电路三、BOOST电路四、BUCK-BOOST电路总结 前言 最近需要用到buck-boost相关的电路知识&#xff0c;于是便写下这篇文章复习一下。 一、DC-DC 在学习buck-boost电路之前我们先来看一…

steam/csgo搬砖项目真能月入过万吗?到底真的假的

steam/csgo搬砖第三课之如何出售 steam搬砖核心原理是什么&#xff1f;为什么会有差价产生&#xff1f;buff不是更低价吗&#xff1f;很多小白会有这些疑问&#xff01; steam搬砖指的是通过买卖csgo游戏装备赚钱的。 玩过游戏的应该就很清楚&#xff0c;像绝地求生&#xff…

新的centos7.9安装jenkins(二)

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 接上一节文章。 这个版本默认git也安装好了&#xff0c;所以全局配置这个不需要了。 maven安装3.9.3版本…

第一百八十一回 如何绘制阴影效果

文章目录 1. 概念介绍2. 使用方法2.1 SegmentedButton2.2 ButtonSegment 3. 代码与效果3.1 示例代码3.2 运行效果 4. 内容总结 1. 概念介绍 我们在本章回中介绍的SegmentedButton组件是一种分段式按钮&#xff0c;它把多个按钮连接成一组显示&#xff0c;组内再对不同的按钮进…

231126 刷题日报

1. 高楼扔鸡蛋 O(N*logN) 2. 698. 划分为k个相等的子集 没做出来&#xff0c;和划分两个子集不同 3. 300. 最长递增子序列 LIS petencie sorting 没看懂&#xff0c;明天看吧 4. 518. 零钱兑换 II 完全背包问题&#xff1a;每个物品数量是无限的 注意&#xff1a;dp的定义…

STM32F103C8T6_PWM引脚

可以看到&#xff1a;一共可以产生4 x 416路PWM信号&#xff1a;每个TIMER4路PWM&#xff0c; PA0,PA1,PA2,PA3,PA8,PA10,PA11; PA共7个 PB0,PB1,PB6,PB7,PB8,PB9,PB14; PB共7个

PTA NeuDS-数据库题目集

一.判断题 1.在数据库中产生数据不一致的根本原因是冗余。T 解析&#xff1a;数据冗余是数据库中产生数据不一致的根本原因&#xff0c;因为当同一数据存储在多个位置时&#xff0c;如果其中一个位置的数据被修改&#xff0c;其他位置的数据就不一致了。因此&#xff0c;在数据…

Jmeter接口测试快速入门 以飞致云平台为例

接口测试快速入门 以飞致云平台为例-CSDN博客 飞致云电商平台可以做接口测试练习。快速了解如何测试接口&#xff0c;如何做关联 系统基地址&#xff1a;https://gz.fit2cloud.com/ 接口测试快速入门 以飞致云平台为例-CSDN博客 博文中介绍了如何在swagger页面上进行接口测试。…

文本转语音:微软语音合成标记语言 (SSML) 文本结构和事件

​ SSML 的语音服务实现基于万维网联合会的语音合成标记语言版本 1.0。 ​ 语音服务支持的元素可能与 W3C 标准不同。 每个 SSML 文档是使用 SSML 元素&#xff08;或标记&#xff09;创建的。 这些元素用于调整语音、风格、音节、韵律、音量等。 下面是 SSML 文档的基本结构…

基本数据结构二叉树(1)

目录 1.树概念及结构 1.1树的概念 1.2 树的相关概念 1.3 树的表示 1.4 树在实际中的运用&#xff08;表示文件系统的目录树结构&#xff09; 2.二叉树概念及结构 2.1概念 2.2现实中的二叉树&#xff1a; 2.3 特殊的二叉树&#xff1a; 2.5 二叉树的存储结构 2. 链式存…

事件委派+自定义属性+编程式导航实现路由跳转及传参

当我们页面中有许多a标签需要实现点击跳转到同一个页面并携带不同的参数时&#xff0c;我们就可以使用事件委派自定义属性编程式导航 的方式&#xff0c;用最小的内存实现路由跳转的最大效率。 为什么我们不用router-link 进行跳转&#xff1f; 要知道&#xff0c;我们页面中…

Django之ORM

ORM全称对象关系映射 作用&#xff1a;通过python面向对象的代码简单快捷的操作数据库&#xff0c;但是封装程度太高&#xff0c;有时候sql语句的效率偏低&#xff0c;需要自己写sql语句 类----->表 对象--->记录 对象属性--->记录某个字段对应的值 写在models.p…

4.前端--HTML标签-表格列表表单【2023.11.25】

1.表格 1.1表格的作用 表格的作用&#xff1a;表格主要用于显示、展示数据 1.2表格的基本格式 <table><tr><td>单元格内的文字</td><td>单元格内的文字</td>...</tr>... </table><table> </table> 是用于定义表…

WebSocket协议在java中的应用

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

关于 raw 图像的理解

1、问题背景 在图像调试过程&#xff0c;当发现一个问题时&#xff0c;很多时候都要通过 dump raw图像来分析&#xff0c;如果raw图像上有&#xff0c;那就排除了是 ISP的处理导致。 下一步就是排查 sensor 或者镜头&#xff0c;这样可以有效的帮我们定位问题所在。 但遇到过…