嫌Qt自带的icon太丑,自己写了一个,主要用于纯色图标的自由改色。
当然,图标素材得网上找。
Qt原生图标与现代图标对比:
没有对比就没有伤害
Qt图标
网络素材图标
自定义类XJQ_Icon:
from PyQt5.QtGui import QIcon,QPixmap,QImage
from cv2 import cv2
import numpy as np
from functools import reduce
__all__=['XJQ_Icon']
class XJQ_Icon(QIcon):
def __init__(self,data,fg=(255,0,0,255),bg=(0,0,0,0)):#data可以为图片路径(str)或是图片数据(np.ndarray)
# QIcon:https://doc.qt.io/qt-6/qicon.html
super().__init__()
if(isinstance(data,np.ndarray)):
im=data
elif(isinstance(data,str)):
im=self.Opt_LoadPictAsArray(data)
else:
raise Exception('data参数错误,类型仅能为np.ndarray(图片数据)或是str(图片路径)')
if(len(fg)==3):
fg=(*fg,255)
if(len(bg)==3):
bg=(*bg,255)
msk=cv2.split(im)[3]
# msk=reduce(lambda a,b:a|b,cv2.split(im))#废弃,更多时候只需要关注alpha的值
self.__msk=cv2.threshold(msk,127,255,cv2.THRESH_BINARY)[1]
#cv2纯色图:https://blog.csdn.net/qq_45666248/article/details/107666586
self.__bg=np.zeros((*msk.shape,4),np.uint8)
self.__fg=np.zeros((*msk.shape,4),np.uint8)
self.__bg[:] = bg
self.__fg[:] = fg
self.__UpdatePixmap()
def Set_ForeColor(self,fg):
if(len(fg)==3):
fg=(*fg,255)
self.__fg[:] = fg
self.__UpdatePixmap()
def Set_BackColor(self,bg):
if(len(bg)==3):
bg=(*bg,255)
self.__bg[:] = bg
self.__UpdatePixmap()
def __UpdatePixmap(self):
#模运算bitwise_and:https://blog.csdn.net/qq_40210586/article/details/106572504
fg=self.__fg
bg=self.__bg
fg=cv2.bitwise_and(fg,fg, mask=self.__msk)
bg=cv2.addWeighted(bg,1,fg,1,0)
pix=self.Trans_ArrayToPixmap(bg)
self.__pix=pix
#虽然没有setPixmap但有这个addPixmap函数,简单看了下这个函数的功能,符合预期,很好
#https://wenku.baidu.com/view/8d3284563269a45177232f60ddccda38376be1ba.html
self.addPixmap(pix)
@staticmethod
def Opt_LoadPictAsArray(path):
#cv2读取中文路径图片:https://www.zhihu.com/question/67157462/answer/251754530
return cv2.imdecode(np.fromfile(path,dtype=np.uint8),cv2.IMREAD_UNCHANGED)
@staticmethod
def Trans_ArrayToPixmap(arr):#arr对应四通道图片。不使用PIL.Image模块
#https://blog.csdn.net/comedate/article/details/121259033
#https://blog.csdn.net/weixin_44431795/article/details/122016214
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 QWidget,QApplication,QPushButton,QLabel
from PyQt5.QtCore import QSize
app = QApplication(sys.argv)
# icon=XJQ_Icon('返回.png')
# icon=XJQ_Icon('三角形-002.png')
icon=XJQ_Icon('比赛控制者.png')
icon.Set_ForeColor((0,255,255,192))
btn=QPushButton("ABC")
btn.setIconSize(QSize(100,100))
btn.setStyleSheet('font-size:50px;background:#FF8844')
btn.setIcon(icon)
btn.show()
sys.exit(app.exec_())
碎碎念:
- 不得不说,与图片处理相关的复杂操作尽量别拉上Qt,会将操作复杂化的(而且往往得不到想要的效果)。像是在这篇帖子如何在 QPainter 中使用mask中,哪怕这么简单而又常见的场景,解决方案都那么抽象。
- 图标素材请去网上获取,我看着爱给网提供的素材都还不错,虽然资源收费,但貌似没有很好的反爬防盗机制,图片很轻易就能保存下来(嘛如果真有防盗那直接去别的素材网就好了
参考:
- 网络图标素材-爱给网:https://www.aigei.com/view/98465.html
- QIcon类:https://doc.qt.io/qt-6/qicon.html
- QIcon.addPixmap方法:https://wenku.baidu.com/view/8d3284563269a45177232f60ddccda38376be1ba.html
- cv2无法读取中文路径的解决方法:https://www.zhihu.com/question/67157462/answer/251754530
- 创建cv2纯色图:https://blog.csdn.net/qq_45666248/article/details/107666586
- cv2掩模操作bitwise_and:https://blog.csdn.net/qq_40210586/article/details/106572504
- cv2图片叠加addWeighted:https://blog.csdn.net/qq_29391809/article/details/117394512
未经本人同意不得私自转载。本文发布于CSDN:https://blog.csdn.net/weixin_44733774/article/details/135282787