Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

python - How to make a tkinter window rounded?

I am trying to make a tkinter overrideredirect window round in shape. I've done this so far:

from tkinter import Tk, Canvas, BOTH, PhotoImage
from tkinter.constants import NW, RAISED
import pyautogui as pg

root = Tk()
root.overrideredirect(1)
root.attributes("-topmost", 1)
root.geometry("500x500")

# Creating a canvas for placing the squircle shape.
canvas = Canvas(root, height=500, width=500, highlightthickness=0)
canvas.pack()

def place_center(): # Placing the window in the center of the screen
    global x, y
    reso = pg.size()
    rx = reso[0]
    ry = reso[1]
    x = int((rx/2) - (500/2))
    y = int((ry/2) - (500/2))
    root.geometry(f"500x500+{x}+{y}")

def round_rectangle(x1, y1, x2, y2, radius=25, **kwargs): # Creating a rounded rectangle
        
        points = [x1+radius, y1,
                x1+radius, y1,
                x2-radius, y1,
                x2-radius, y1,
                x2, y1,
                x2, y1+radius,
                x2, y1+radius,
                x2, y2-radius,
                x2, y2-radius,
                x2, y2,
                x2-radius, y2,
                x2-radius, y2,
                x1+radius, y2,
                x1+radius, y2,
                x1, y2,
                x1, y2-radius,
                x1, y2-radius,
                x1, y1+radius,
                x1, y1+radius,
                x1, y1]

        return canvas.create_polygon(points, **kwargs, smooth=True)

place_center()

# Taking a screenshot and adding it to the canvas to create a transparent effect
root.withdraw()
s = pg.screenshot(region=(x, y, 500, 500))
tp = "C:\Users\username\AppData\Local\Temp\bg.png"
s.save(tp)
bg = PhotoImage(file=tp)
canvas.create_image(0, 0, image=bg, anchor=NW)
root.deiconify()
os.remove(tp)

# Creating the squircle
round_rectangle(0, 0, 500, 500, radius=70, fill="#1fa5fe")

root.mainloop()

I use this function to move the window:

def move(event):
    fx = root.winfo_pointerx() - 250
    fy = root.winfo_pointery() - 10
    root.geometry(f"500x500{fx}+{fy}")

I haven't added it into the code because when I move the window, it becomes square again as the screenshot is taken only of a particular region.

Before moving: Round window before moving

After moving: Squared window after moving

How can I make it round even when I move it?

I tried using root.withdraw() and root.deiconify() in a while True: loop, but it causes flickering.

Any help would be appreciated.

Thank you.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

how to change window's shape in tkinter (although this should work most certainly on Windows computers, some other OS (macOS, Linux) may have issues meaning that this exact code may not work and not give the desired output). Explanation in code comments:

from tkinter import Tk, Canvas
from PIL import Image, ImageTk
import requests


# load image from web but you can of course load it from file, this is
# just so you can run and immediately see the results
url = 'http://media-s3-us-east-1.ceros.com/g3-communications/images/2019/01/15/05eea4b9b9ce010d2dd6b0c063d2f5ca/p1-blob.png?imageOpt=1&fit=bounds&width=893'
data = requests.get(url, stream=True).raw
# just when loading your own image instead of `data` use the path, and resize
# if you need, can obvs change these numbers
image = Image.open(data).resize((600, 600), Image.ANTIALIAS)


root = Tk()
# set root bg color to some rare color because
# the `-transparentcolor` affects all colors on the window, all of them
root.config(bg='grey15')
# just simply set window to the middle, not necessary
root.geometry(f'+{root.winfo_screenwidth() // 2 - 300}+{root.winfo_screenheight() // 2 - 300}')
# the important part, set the transparentcolor to some rare color in this case `grey15`,
# can obvs be sth else depending on your theme
root.attributes('-transparentcolor', 'grey15')
# remove window from window manager
root.overrideredirect(True)

# create canvas and set the bg to the same "rare" color (width and height set
# to image width and height, can be sth different too)
canvas = Canvas(
    root, bg='grey15', width=image.width, height=image.height, highlightthickness=0
)
canvas.pack()
# convert image to PhotoImage for `tkinter` to understand
photo = ImageTk.PhotoImage(image)
# put the image on canvas because canvas supports transparent bg
canvas.create_image(0, 0, image=photo, anchor='nw')

root.mainloop()

The key parts are .attributes('-transparentcolor', ...) (which is the most likely to not work on some OS) and that the shape of the window is formed by an image of that shape (the image should have transparent background (a .png image)). It is also possible to simply draw a shape using Canvas methods (.create_). Also important to remember that the attribute affects all the colors on the window meaning that for example if you were to set the transparentcolor to say white and your background image contained white, it will most likely be transparent too (tho probably won't look as good) so I would suggest using some color that is the least likely to be on the GUI


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...