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

news2024/12/25 8:55:32

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



自定义阴影遮罩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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UVA437 巴比伦塔 The Tower of Babylon

UVA437 巴比伦塔 The Tower of Babylon 题面翻译 题目描述 你可能已经听说过巴比伦塔的传说。现在这个传说的许多细节已经被遗忘。所以本着本场比赛的教育性质&#xff0c;我们现在会告诉你整个传说&#xff1a; 巴比伦人有 n n n 种长方形方块&#xff0c;每种有无限个&a…

加载minio中存储的静态文件html,不显示样式与js

问题描述:点击链接获取的就是纯静态文件,但是通过浏览器可以看到明明加载了css文件与js文件 原因:仔细看你会发现加载css文件显示的contentType:text/html文件,原来是minio上传文件时将所有文件的contentType设置成了text/html 要在上传时指定文件,根据文章的类型指定的Conten…

Unity 讯飞 之 讯飞星火大模型的简单封装和使用(补充讯飞大模型识图功能)

Unity 讯飞 之 讯飞星火大模型的简单封装和使用&#xff08;补充讯飞大模型识图功能&#xff09; 目录 Unity 讯飞 之 讯飞星火大模型的简单封装和使用&#xff08;补充讯飞大模型识图功能&#xff09; 一、简单介绍 二、实现原理 三、注意事项 四、效果预览 五、案例简单…

【Element】el-switch开关 点击弹窗确认框时状态先改变----点击弹窗取消框失效

一、背景 需求&#xff1a;在列表中添加定期出账的开关按钮&#xff0c;点击开关时&#xff0c;原来的状态不改变&#xff0c;弹出弹窗&#xff1b;点击弹窗取消按钮&#xff1a;状态不改变&#xff0c;点击弹窗确定按钮&#xff1a;状态改变&#xff0c;并调取列表数据刷新页…

python 如何利用everything的能力快速搜索兴趣文件夹

演示代码 # -*- coding:UTF-8 -*- """ author: dyy contact: douyaoyuan126.com time: 2023/11/23 17:10 file: python 如何通过everything搜索兴趣文档.py desc: xxxxxx """# region 引入必要的依赖 import os模块名 DebugInfo try:from Debu…

使用 Python 和 NLTK 进行文本摘要

一、说明 文本摘要是一种自然语言处理技术&#xff0c;允许用户将大量文本总结为小块&#xff0c;而不会丢失任何重要信息。本文介绍NLP中使用Gensim和Sumy实现文本摘要的步骤。 二、为什么要总结文本&#xff1f; 互联网包含大量信息&#xff0c;而且每秒都在增加。文本摘要可…

Java实现求最大值

1 问题 接收用户输入的3个整数&#xff0c;如何将最大值作为结果输出。 2 方法 采用“截图文字代码”的方式描述。 引入输入包调用main()函数&#xff0c;提示并接收用户输入的3个整数&#xff0c;并交由变量a b c来保存。对接收的3个数据进行比较&#xff0c;先比较a和b&#…

『许战海战略文库』打造技术品牌:企业的新成长引擎

引言&#xff1a;随着全球化和技术的快速发展,企业面临的竞争压力也越来越大。在这种环境下,仅仅拥有技术优势是不够的,如何将技术转化为品牌的核心竞争力&#xff0c;从而实现企业的长期和持续发展,成为许多企业面临的核心问题。 产业技术品牌不仅代表企业技术实力&#xff0c…

Vue项目实战之一----实现分类弹框效果

效果图 实现 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>Title</title><script src"js/vue.js"></script><!-- 引入样式 --><link rel"stylesheet&qu…

p12 63.删除无头结点无头指针的循环链表中所有值为x的结点 桂林电子科技大学2015年 (c语言代码实现)注释详解

本题代码如下 void delete(linklist* L, int x) {lnode* p *L, * q *L;while (p->next ! q)// 从第一个结点开始遍历链表&#xff0c;直到尾结点的前一个结点{if (p->next->data x)//判断是否等于x{lnode* r p->next;//将r指向x的位置p->next r->next;…

热门话题解析:pytest测试用例顺序问题解决方案!

前言 上一篇文章我们讲了在pytest中测试用例的命名规则&#xff0c;那么在pytest中又是以怎样的顺序执行测试用例的呢&#xff1f; 在unittest框架中&#xff0c;默认按照ACSII码的顺序加载测试用例并执行&#xff0c;顺序为&#xff1a;09、AZ、a~z&#xff0c;测试目录、测…

Redis key的类型以及命令

系列文章目录 第一章 Java线程池技术应用 第二章 CountDownLatch和Semaphone的应用 第三章 Spring Cloud 简介 第四章 Spring Cloud Netflix 之 Eureka 第五章 Spring Cloud Netflix 之 Ribbon 第六章 Spring Cloud 之 OpenFeign 第七章 Spring Cloud 之 GateWay 第八章 Sprin…

常见树种(贵州省):016杜鹃、含笑、桃金娘、金丝桃、珍珠花、观光木

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

C语言——指针(二)

&#x1f4dd;前言 上篇文章C语言——指针&#xff08;一&#xff09;初步讲解了&#xff1a; 1&#xff0c;指针与指针变量 2&#xff0c;指针变量的基本使用&#xff08;如何定义&#xff0c;初始化&#xff0c;引用&#xff09; 这篇文章我们进一步探讨&#xff0c;使用指针…

【漏洞复现】金蝶云星空管理中心 ScpSupRegHandler接口存在任意文件上传漏洞 附POC

漏洞描述 金蝶云星空是一款云端企业资源管理(ERP)软件,为企业提供财务管理、供应链管理以及业务流程管理等一体化解决方案。金蝶云星空聚焦多组织,多利润中心的大中型企业,以 “开放、标准、社交”三大特性为数字经济时代的企业提供开放的 ERP 云平台。服务涵盖:财务、供…

原始类型 vs. 对象实践应用

● 首先是原始类型的例子 let lastName Williams; let oldLastName lastName; lastName Davis; console.log(lastName.oldLastName);● 然后是对象的例子 const jessica {firstName: Jessica,lastName: Williams,age: 27, }; const marriedJessica jessica; marriedJess…

docker部署phpIPAM

0说明 IPAM&#xff1a;IP地址管理系统 IP地址管理(IPAM)是指的一种方法IP扫描&#xff0c;IP地址跟踪和管理与网络相关的信息的互联网协议地址空间和IPAM系统。 IPAM软件和IP的工具,管理员可以确保分配IP地址仍然是当前和足够的库存先进的IP工具和IPAM服务。 IPAM简化并自动化…

2023.11.25-istio安全

目录 文章目录 目录本节实战1、安全概述2、证书签发流程1.签发证书2.身份认证 3、认证1.对等认证a.默认的宽容模式b.全局严格 mTLS 模式c.命名空间级别策略d.为每个工作负载启用双向 TLS 2.请求认证a.JWK 与 JWKS 概述b.配置 JWT 终端用户认证c.设置强制认证规则 关于我最后 本…

居家适老化设计第三十条---卫生间之坐便

以上产品图片均来源于淘宝 侵权联系删除 在居家适老化中&#xff0c;马桶是非常重要的设施之一&#xff0c;它能够提供方便、安全、舒适的上厕所体验。以下是一些居家适老化中常见的马桶设计和功能&#xff1a;1. 高度合适&#xff1a;为了方便老年人坐起和站起&#xff0c;马…

js逆向-JS加密破解

一、常见五种js加密手段 &#xff08;一&#xff09;加密位置&#xff1a; 1.Request Payload 加密 2.Request Headers 加密 3.Request URL params 参数加密 4.Response Data 数据加密 5.JS代码混淆加密 &#xff08;二&#xff09;加密算法 base64 编码 哈希算法&…