如何调整带自定义形状的tkinter overrideredirect窗口避免移动时变回方形
问题原因
你的问题核心出在移动窗口的move函数硬编码了窗口尺寸为固定的500x500,每次拖拽移动时都会强制把窗口重置为初始大小,自然会覆盖之前调整好的自定义形状。同时还有两个配套问题:调整尺寸后没有更新右下角拖拽触发区的位置、缺少变量存储当前窗口的实际宽高。
修改方案
核心改动点
- 新增两个全局变量存储当前窗口的宽高,初始值为500
- 修改
move函数,动态使用当前宽高设置窗口位置,不再写死500x500 - 修改
resize函数,调整尺寸后同步更新宽高变量、右下角拖拽触发区的位置 - 删除代码末尾多余的
root.unbind("<B1-Motion>"),避免初始状态无法拖拽移动窗口
完整可运行修改后代码
from tkinter import Label, Tk, Canvas, BOTH, PhotoImage, Toplevel from tkinter.constants import BOTTOM, E, NW, RAISED import pyautogui as pg root = Tk() root.overrideredirect(1) root.attributes("-transparentcolor", 'white') root.attributes("-topmost", 1) root.geometry("500x500") # 新增变量存储当前窗口宽高 current_width = 500 current_height = 500 # Creating a canvas for placing the squircle shape. canvas = Canvas(root, height=500, width=500, highlightthickness=0, bg='white') canvas.pack(fill=BOTH, expand=1) 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 move(event): global rect, current_width, current_height fx = root.winfo_pointerx() - (current_width/2) fy = root.winfo_pointery() - 10 # 动态使用当前宽高,不再写死500x500 root.geometry(f"{current_width}x{current_height}+{int(fx)}+{int(fy)}") 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) def cl(event): root.quit() def resize(event): def end(event): global rect root.bind("<B1-Motion>", move) global rect, current_width, current_height, side root.unbind("<B1-Motion>") x = root.winfo_pointerx() - root.winfo_rootx() y = root.winfo_pointery() - root.winfo_rooty() if x > 0: fx = root.winfo_rootx() fy = root.winfo_rooty() + y ht = root.winfo_height() - y if ht > 0: root.geometry(f"{x}x{ht}+{fx}+{fy}") canvas.delete(rect) rect = round_rectangle(0, 0, x, ht, radius=50, fill="#1fa5fe") # 更新当前宽高变量 current_width = x current_height = ht # 更新右下角拖拽触发区位置 side.place(x=x-10, y=ht-10) root.bind("<ButtonRelease-1>", end) place_center() # Creating the squircle rect = round_rectangle(0, 0, 500, 500, radius=50, fill="#1fa5fe") root.bind("<B1-Motion>", move) root.bind("<Button-3>", cl) rx = root.winfo_rootx() ry = root.winfo_rooty() side = Label(canvas, text=' \n', background="blue") side.place(x=500-10, y=500-10) side.bind("<B1-Motion>", resize) root.mainloop()
修改后调整窗口大小再移动,自定义圆角形状不会再丢失,右下角拖拽触发区也会跟随窗口大小正常更新。
内容的提问来源于stack exchange,提问作者IJ_123
相关产品推荐
相关产品推荐

