如何获取滚动后CustomTkinter Canvas的正确位置以解决绘图偏移
问题:CustomTkinter滚动Canvas后绘图位置偏移
使用CustomTkinter开发绘图程序时,带滚动条的Canvas在滚动后,鼠标拖动绘制椭圆的位置始终与光标错位。尝试过canvasx()和canvasy()方法,但未解决问题。
原代码
from customtkinter import * from tkinter import Scrollbar set_appearance_mode('System') set_default_color_theme('dark-blue') window = CTk() # Window window.geometry("800x520") fill_color = '#000000' def draw_with_brush(event): fx, fy = event.x - 1 , event.y - 1 lx, ly = fx + 1, fy + 1 canvas.create_oval((fx, fy, lx, ly), outline=fill_color, width=10, fill=fill_color) canvas = CTkCanvas(window, bg='white', bd=2, relief=SUNKEN, height=430, width=700, scrollregion=(0,0,100000,100000)) canvas.place(x=60, y=50) canvas.bind("<B1-Motion>", draw_with_brush) x_scroll = Scrollbar(window, orient=HORIZONTAL, command=canvas.xview) x_scroll.place(x=60, y=495, width=700) y_scroll = Scrollbar(window, orient=VERTICAL, command=canvas.yview) y_scroll.place(x=780, y=50, height=430) canvas.config(xscrollcommand=x_scroll.set, yscrollcommand=y_scroll.set) window.mainloop() # Loop
解决方案
问题核心是**event.x和event.y获取的是鼠标相对于Canvas组件本身的坐标,而非Canvas内部滚动后的实际绘图坐标**。正确做法是用canvas.canvasx(event.x)和canvas.canvasy(event.y)将组件坐标转换为Canvas内部的滚动坐标。
你之前尝试这两个方法但无效,大概率是未正确替换event.x和event.y的位置。修改后的draw_with_brush函数如下:
def draw_with_brush(event): # 转换为Canvas内部滚动后的坐标 x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) fx, fy = x - 1, y - 1 lx, ly = fx + 2, fy + 2 # 保持椭圆大小一致 canvas.create_oval((fx, fy, lx, ly), outline=fill_color, width=10, fill=fill_color)
修改后的完整代码
from customtkinter import * from tkinter import Scrollbar set_appearance_mode('System') set_default_color_theme('dark-blue') window = CTk() # Window window.geometry("800x520") fill_color = '#000000' def draw_with_brush(event): # 转换鼠标坐标为Canvas滚动后的实际坐标 x = canvas.canvasx(event.x) y = canvas.canvasy(event.y) fx, fy = x - 1, y - 1 lx, ly = fx + 2, fy + 2 canvas.create_oval((fx, fy, lx, ly), outline=fill_color, width=10, fill=fill_color) canvas = CTkCanvas(window, bg='white', bd=2, relief=SUNKEN, height=430, width=700, scrollregion=(0,0,100000,100000)) canvas.place(x=60, y=50) canvas.bind("<B1-Motion>", draw_with_brush) x_scroll = Scrollbar(window, orient=HORIZONTAL, command=canvas.xview) x_scroll.place(x=60, y=495, width=700) y_scroll = Scrollbar(window, orient=VERTICAL, command=canvas.yview) y_scroll.place(x=780, y=50, height=430) canvas.config(xscrollcommand=x_scroll.set, yscrollcommand=y_scroll.set) window.mainloop() # Loop
说明
canvasx()和canvasy()会自动计算Canvas的滚动偏移量,将鼠标在组件上的位置转换为Canvas内部的绝对坐标,滚动后绘图位置可精准对应鼠标位置。- 调整椭圆右下角坐标计算为
fx + 2,确保椭圆大小不会因坐标转换改变。
内容的提问来源于stack exchange,提问作者Little Developer
相关产品推荐
相关产品推荐

