Tkinter의 Canvas 위젯에는 두 가지 좌표계가 존재합니다. 첫 번째는 윈도우(Window) 좌표계이고, 두 번째는 캔버스(Canvas) 좌표계입니다.
윈도우 좌표계는 항상 창의 왼쪽 상단 모서리를 원점 (0, 0)으로 기준으로 하며, 반면 캔버스 좌표계는 캔버스 위에 실제로 배치된 아이템들의 위치를 나타냅니다. 스크롤이 발생하면 이 두 좌표계 사이에 차이가 생기기 때문에 정확한 위치 계산을 위해서는 좌표 변환이 필요합니다.
윈도우 좌표를 캔버스 좌표로 변환하는 방법
마우스 이벤트와 같은 입력 이벤트는 기본적으로 윈도우 좌표계에서 발생합니다. 따라서 이벤트로 전달받은 좌표를 캔버스 좌표계로 변환하려면 Canvas 위젯이 제공하는 다음 두 메서드를 사용할 수 있습니다.
canvas.canvasx(event.x) # 화면 x좌표를 캔버스 x좌표로 변환 canvas.canvasy(event.y) # 화면 y좌표를 캔버스 y좌표로 변환
이처럼 canvasx()와 canvasy() 메서드를 활용하면 마우스 포인터의 위치를 캔버스 내부의 실제 좌표 값으로 손쉽게 얻을 수 있습니다.
예제 코드
아래 예제는 캔버스 위젯 안에서 마우스 포인터의 위치를 실시간으로 가져오는 간단한 애플리케이션입니다. 마우스 왼쪽 버튼을 클릭하면 시작 좌표를, 버튼을 누른 상태로 움직이면 종료(현재) 좌표를 콘솔에 출력합니다.
# 필요한 라이브러리 임포트
from tkinter import *
# Tkinter 프레임(윈도우) 인스턴스 생성
win = Tk()
# 윈도우 크기 설정
win.geometry("700x350")
# 캔버스 위젯 생성
canvas = Canvas(win)
canvas.pack()
# 마우스 버튼 클릭 시 호출되는 함수
def on_button_pressed(event):
start_x = canvas.canvasx(event.x)
start_y = canvas.canvasy(event.y)
print("start_x, start_y =", start_x, start_y)
# 마우스 드래그(모션) 시 호출되는 함수
def on_button_motion(event):
end_x = canvas.canvasx(event.x)
end_y = canvas.canvasy(event.y)
print("end_x, end_y =", end_x, end_y)
# 캔버스에 마우스 이벤트 바인딩
canvas.bind("<Button-1>", on_button_pressed)
canvas.bind("<Button1-Motion>", on_button_motion)
# 윈도우에 라벨 위젯 추가
Label(win, text="마우스 포인터를 움직여 캔버스 아무 곳이나 클릭해 보세요").pack()
win.mainloop()실행 결과
위 코드를 실행하면 캔버스가 포함된 창이 화면에 나타납니다. 이후 마우스 포인터를 움직여 캔버스 위 임의의 지점을 클릭하면, 해당 위치의 캔버스 상대 좌표가 콘솔에 출력됩니다.
start_x, start_y = 340.0 159.0
출력된 값은 윈도우 기준 좌표가 아니라 캔버스 좌표계 기준의 값입니다. 만약 캔버스가 스크롤된 상태라면, canvasx()와 canvasy() 덕분에 스크롤 오프셋까지 자동으로 반영된 정확한 좌표를 얻을 수 있습니다. 이 방식은 그림판 앱, 도형 선택 영역 표시 등 마우스 인터랙션이 필요한 캔버스 애플리케이션을 개발할 때 매우 유용하게 활용됩니다.