需要安装pycario库
pip install pycairo
下面是实现
import cairo
import wx
from io import BytesIO
from PIL import Image
import math
class AnnularPercent(wx.Panel):
def __init__(self, parent,value:float ,id=wx.ID_ANY, pos=wx.DefaultPosition, size=(100,100), style=wx.TAB_TRAVERSAL, name=wx.PanelNameStr):
super().__init__(parent, id=id, pos=pos, size=size, style=style, name=name)
#百分比的值
self.value=int(value)
#环的宽度
self.barSize=16
#背景颜色
self.backgroundColour=(1,1,1)
#环的颜色
self.barColour=(0,0,1)
#标题
self.title=''
#创建环形百分比的位图
bitmap = self.OnDraw(self.value,self.barSize)
self.sBitmap = wx.StaticBitmap(self,bitmap=bitmap)
#百分比的文本
self.percentText = wx.StaticText(self.sBitmap,label=str(self.value)+'%',style=wx.ALIGN_CENTER)
self.percentText.SetBackgroundColour(wx.WHITE)
self.percentText.SetFont(wx.Font(12,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL))
self.Update()
position=(int(size[0]/2-self.percentText.GetSize()[0]/2),int(size[1]/2-self.percentText.GetSize()[1]/2))
self.percentText.Move(position[0],position[1])
def OnDraw(self,value:float,width:int):
mem_stream = BytesIO()
ims = cairo.ImageSurface(cairo.FORMAT_ARGB32, self.GetSize()[0], self.GetSize()[1])
cr = cairo.Context(ims)
# 设置背景颜色
cr.set_source_rgb(self.backgroundColour[0], self.backgroundColour[1], self.backgroundColour[2])
cr.paint() # 应用颜色设置到整个Surface上
#设置画笔宽度
cr.set_line_width(width)
#将画笔移动到的位置
cr.translate(self.GetSize()[0]/2, self.GetSize()[1]/2)
#设置画笔颜色
cr.set_source_rgb(0.9411, 0.9411, 0.9294)
#画一个圆
cr.arc(0, 0, self.GetSize()[0]/2-cr.get_line_width()/2, 0, 2*math.pi)
cr.stroke_preserve()
#清除上下文路径
cr.new_path()
#设置画笔颜色
cr.set_source_rgb(self.barColour[0],self.barColour[1],self.barColour[2])
#旋转-90度
cr.rotate(-0.5*math.pi)
#以画笔为中心设置一个圆的路径
cr.arc(0, 0, self.GetSize()[0]/2-cr.get_line_width()/2, 0, value*math.pi)
#根据路径绘画
cr.stroke_preserve()
#将图案以内存流的方式存储
ims.write_to_png(mem_stream)
# 可以选择将内存流的位置重置为开始处
mem_stream.seek(0)
#从流中读取图片
image = Image.open(mem_stream)
#设置wx_Image的长宽
wx_image = wx.Image(image.width, image.height)
#设置图片
wx_image.SetData(image.convert('RGB').tobytes())
#转换
bitmap = wx_image.ConvertToBitmap()
return bitmap
def SetValue(self,value:float):
"""
设置百分比的值
Args:
value (float): 百分比的值
"""
self.value=int(value)
bitmap = self.OnDraw(value/100*2,self.barSize)
self.sBitmap.SetBitmap(bitmap)
self.percentText.SetLabel(self.title+str(value)+'%')
self.Update()
position=(int(self.GetSize()[0]/2-self.percentText.GetSize()[0]/2),int(self.GetSize()[1]/2-self.percentText.GetSize()[1]/2))
self.percentText.Move(position[0],position[1])
def SetFontSize(self,size:int):
"""
设置百分比的字体大小
Args:
size (int): 字体大小
"""
self.percentText.SetFont(wx.Font(size,wx.FONTFAMILY_DEFAULT,wx.FONTSTYLE_NORMAL,wx.FONTWEIGHT_NORMAL))
self.Update()
position=(int(self.GetSize()[0]/2-self.percentText.GetSize()[0]/2),int(self.GetSize()[1]/2-self.percentText.GetSize()[1]/2))
self.percentText.Move(position[0],position[1])
def SetBarSize(self,size:int):
"""
设置环的宽度
Args:
size (int): 宽度
"""
self.barSize=size
bitmap = self.OnDraw(self.value/100*2,self.barSize)
self.sBitmap.SetBitmap(bitmap)
def SetImageBackgroundColour(self,R:int,G:int,U:int):
"""
设置背景颜色
Args:
R (int): _description_
G (int): _description_
U (int): _description_
"""
self.backgroundColour=(R/255,G/255,U/255)
self.percentText.SetBackgroundColour(wx.Colour(R,G,U))
bitmap = self.OnDraw(self.value/100*2,self.barSize)
self.sBitmap.SetBitmap(bitmap)
def SetTitle(self,title:str):
"""
设置标题
Args:
title (str): 标题
"""
self.title=title+'\n'
self.percentText.SetLabel(self.title+str(self.value)+'%')
self.Update()
position=(int(self.GetSize()[0]/2-self.percentText.GetSize()[0]/2),int(self.GetSize()[1]/2-self.percentText.GetSize()[1]/2))
self.percentText.Move(position[0],position[1])
def SetFontColour(self,colour:wx.Colour):
self.percentText.SetForegroundColour(colour)
def SetBarColour(self,R:int,G:int,U:int):
"""
设置环的颜色
Args:
R (int): _description_
G (int): _description_
U (int): _description_
"""
self.barColour=(R/255,G/255,U/255)
bitmap = self.OnDraw(self.value/100*2,self.barSize)
self.sBitmap.SetBitmap(bitmap)