【PyQt】(自定义类)QIcon派生,更易用的纯色Icon

嫌Qt自带的icon太丑,自己写了一个,主要用于纯色图标的自由改色。
当然,图标素材得网上找。



Qt原生图标与现代图标对比:

没有对比就没有伤害

Qt图标
【PyQt】(自定义类)QIcon派生,更易用的纯色Icon_第1张图片

网络素材图标
【PyQt】(自定义类)QIcon派生,更易用的纯色Icon_第2张图片
【PyQt】(自定义类)QIcon派生,更易用的纯色Icon_第3张图片
【PyQt】(自定义类)QIcon派生,更易用的纯色Icon_第4张图片



自定义类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_())

【PyQt】(自定义类)QIcon派生,更易用的纯色Icon_第5张图片



碎碎念:

  • 不得不说,与图片处理相关的复杂操作尽量别拉上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

你可能感兴趣的:(pyqt)