You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何调整带自定义形状的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 19:36:02