Reputation: 391
I'm currently working on a Python project using customtkinter
, and I'm facing an issue with applying a custom corner radius to an image inside a CTkFrame
. Here's a minimal example of my code:
import customtkinter
from PIL import Image
image_path = #image path
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
frame = customtkinter.CTkFrame(self, width=200, height=111, corner_radius=5)
frame.pack()
image = customtkinter.CTkImage(Image.open(image_path), size=(200, 111))
image_label = customtkinter.CTkLabel(frame, image=image, text="")
image_label.pack()
if __name__ == "__main__":
app = App()
app.mainloop()
In this code, I'm trying to display an image inside a CTkFrame
with a custom corner radius. However, the image doesn't follow the corner radius of the parent frame and appears with sharp corners.
I attempted to use a canvas to mask the image with rounded corners, but this approach results in low resolution corners and the corners don't always match the background.
How can I properly apply the custom corner radius to the image inside the CTkFrame
?
Any insights or alternative approaches would be greatly appreciated. Thank you!
Upvotes: 1
Views: 788
Reputation: 1
import customtkinter
from pywinstyles import set_opacity
from PIL import Image, ImageDraw
image_path = 'win11.jpg'#Rasim manzili | image path
def add_corners(im, rad): #Rasimni chetlarini siliqlash | Add corners to the image
circle = Image.new('L', (rad * 2, rad * 2), 0)
draw = ImageDraw.Draw(circle)
draw.ellipse((0, 0, rad * 2 - 1, rad * 2 - 1), fill=255)
alpha = Image.new('L', im.size, 255)
w, h = im.size
alpha.paste(circle.crop((0, 0, rad, rad)), (0, 0))
alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
im.putalpha(alpha)
return im
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
frame = customtkinter.CTkFrame(self, width=500, height=200, corner_radius=5)
frame.pack()
image = customtkinter.CTkImage(add_corners(Image.open(image_path), 100), size=(600, 400))
image_label = customtkinter.CTkLabel(frame, image=image, text="", fg_color='black')
set_opacity(frame, color="black") #Ramka(frame)dan Qora rangni o'chirish(shaffof qlish) | Removing the black color (making it transparent) from frame
image_label.pack()
if __name__ == "__main__":
app = App()
app.mainloop()
Upvotes: 0
Reputation: 316
I was scrolling on stackoverflow and found this post: how to round_corner a logo without white background(transparent?) on it using pil?
It reminded me of your question I commented on 4 days ago saying it is not possible to round corners in customtkinter, so I am here to correct myself.
It is indeed possible to do it using PIL.ImageDraw.Draw.ellipse()
, here is the code:
from PIL import Image, ImageDraw
def add_corners(im, rad):
circle = Image.new('L', (rad * 2, rad * 2), 0)
draw = ImageDraw.Draw(circle)
draw.ellipse((0, 0, rad * 2 - 1, rad * 2 - 1), fill=255)
alpha = Image.new('L', im.size, 255)
w, h = im.size
alpha.paste(circle.crop((0, 0, rad, rad)), (0, 0))
alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
im.putalpha(alpha)
return im
In you case, the full code is:
import customtkinter
from PIL import Image, ImageDraw
image_path = #image path
def add_corners(im, rad):
circle = Image.new('L', (rad * 2, rad * 2), 0)
draw = ImageDraw.Draw(circle)
draw.ellipse((0, 0, rad * 2 - 1, rad * 2 - 1), fill=255)
alpha = Image.new('L', im.size, 255)
w, h = im.size
alpha.paste(circle.crop((0, 0, rad, rad)), (0, 0))
alpha.paste(circle.crop((0, rad, rad, rad * 2)), (0, h - rad))
alpha.paste(circle.crop((rad, 0, rad * 2, rad)), (w - rad, 0))
alpha.paste(circle.crop((rad, rad, rad * 2, rad * 2)), (w - rad, h - rad))
im.putalpha(alpha)
return im
class App(customtkinter.CTk):
def __init__(self):
super().__init__()
frame = customtkinter.CTkFrame(self, width=200, height=111, corner_radius=5)
frame.pack()
image = customtkinter.CTkImage(add_corners(Image.open(image_path), 100), size=(200, 111))
image_label = customtkinter.CTkLabel(frame, image=image, text="")
image_label.pack()
if __name__ == "__main__":
app = App()
app.mainloop()
But this only works using .png pictures if you want a transparent background (like said in the post linked above).
If you have more questions, you should refere to the post above: there is already troubleshooting here.
Hope I helped you, have a nice day.
Edit: because I found rounding corners useful, I created a module containing a class to automate this functionnality, the module is called MoreCustomTkinterWidgets
on Pypi.
Upvotes: 1