Python Pillow圆角矩形绘制异常:Discord机器人等级卡经验条被截断
问题根源
你遇到的圆角截断问题来自两个原因:
- 当已填充的进度条总宽度(
length - 起始x坐标40)小于2倍圆角半径(你设置的15,两倍就是30px)时,Pillow的rounded_rectangle方法无法正常绘制完整圆角,会自动削平边角 - 你同时给背景条和进度条都加了外描边,两层描边重叠也会导致边缘显示异常
解决方法
你可以按下面的方案修改代码:
- 动态调整进度条的圆角半径,确保半径永远不超过进度条宽度的一半
- 拆分填充和描边的绘制逻辑,先绘制背景填充、再绘制进度填充,最后统一给整个经验条加外描边,避免重叠
修改后的代码参考:
def draw(self, user: str, rank: str, level: str, xp: str, needed_xp: str, profile_bytes: BytesIO) -> BytesIO: profile_bytes = Image.open(profile_bytes) im = Image.new('RGBA', (800, 200), (44, 44, 44, 255)) im_draw = ImageDraw.Draw(im) im_draw.text((154, 5), user, font=self.font, fill=(255, 255, 255, 255)) rank_text = f'Rank: #{rank}' im_draw.text((154, 37), rank_text, font=self.medium_font, fill=(255, 255, 255, 255)) xp_text = f'Level: {level}' im_draw.text((154, 62), xp_text, font=self.small_font, fill=(255, 255, 255, 255)) xp_text = f'Experience: {xp}/{needed_xp}' im_draw.text((154, 87), xp_text, font=self.small_font, fill=(255, 255, 255, 255)) # 先画经验条背景填充,不带描边 im_draw.rounded_rectangle((40, 180, 440, 150), fill=(64, 64, 64, 255), radius=15) length = 40 + int(xp)/int(needed_xp)*400 # 计算进度条宽度,动态调整圆角半径 progress_width = length - 40 radius = 15 if progress_width >= 30 else progress_width / 2 # 画进度填充,不带描边 im_draw.rounded_rectangle((40, 180, length, 150), fill=(221, 221, 221, 255), radius=radius) # 最后统一画整个经验条的外描边 im_draw.rounded_rectangle((40, 180, 440, 150), outline=(92, 23, 47, 255), width=3, radius=15) im.paste(profile_bytes, (10, 10)) im.show()
额外优化建议
如果想要进度条右端永远保持圆角,哪怕进度为0的时候也显示小圆角,可以直接设置最小半径为2-3px,不会出现完全直角的情况。
内容的提问来源于stack exchange,提问作者Philskillz
相关产品推荐
相关产品推荐

