I want to draw on a canvas and write the logic to capture that canvas.
So, I tried to make a drawing board with tkinter and capture it with PIL.
However, only a part of the canvas was captured, probably because the coordinate values were incorrectly obtained.
import tkinter as tk
from PIL import ImageGrab
# 선택:0, 점:1, 선:2, 사각형3, 원:4, 텍스트 5
draw_mode = 0
# 색
draw_color = "black"
# x1, y1: 시작점
x1 = None
y1 = None
# 마우스 왼쪽 버튼을 눌렀을 때
def mouseLDown(event):
global x1, y1
mouse_text.set("X:"+str(event.x)+" Y:"+str(event.y)+" L Down")
# 점 그리기 모드라면
if draw_mode == 1:
canvas.create_oval(event.x-2, event.y-2, event.x+2, event.y+2, fill=draw_color, outline=draw_color)
# 텍스트 그리기 모드라면
elif draw_mode == 5:
canvas.create_text(event.x, event.y, text=input_text.get(), fill=draw_color)
# 선 그리기 모드라면
elif draw_mode >= 2 and draw_mode <= 4:
x1 = event.x
y1 = event.y
# 마우스를 움직일 때
def mouseMove(event):
global x1, y1
mouse_text.set("X:"+str(event.x)+" Y:"+str(event.y)+" Move")
canvas.create_oval(event.x-2, event.y-2, event.x+2, event.y+2, fill=draw_color, outline=draw_color)
# 마우스 왼쪽 버튼을 뗐을 때
def mouseLUp(event):
global x1, y1
mouse_text.set("X:"+str(event.x)+" Y:"+str(event.y)+" L Up")
# 선 그리기 모드라면
if draw_mode == 2:
canvas.create_line(x1, y1, event.x, event.y, width=2, fill=draw_color)
# 네모 그리기 모드라면
elif draw_mode == 3:
canvas.create_rectangle(x1, y1, event.x, event.y, width=2, outline=draw_color, fill=draw_color)
# 원 그리기 모드라면
elif draw_mode == 4:
canvas.create_oval(x1, y1, event.x, event.y, width=2, outline=draw_color)
# 선택 버튼 함수
def selectButton():
global draw_mode
draw_mode = 0
# 점 그리기 버튼 함수
def pointButton():
global draw_mode
draw_mode = 1
# 선 그리기 버튼 함수
def lineButton():
global draw_mode
draw_mode = 2
# 사각형 버튼 함수
def rectangleButton():
global draw_mode
draw_mode = 3
# 원 그리기 버튼 함수
def circleButton():
global draw_mode
draw_mode = 4
# 텍스트 그리기 버튼 함수
def textButton():
global draw_mode
draw_mode = 5
# 하얀색 버튼 함수
def whiteButton():
global draw_color
draw_color = "white"
# 검은색 버튼 함수
def blackButton():
global draw_color
draw_color = "black"
# 빨간색 버튼 함수
def redButton():
global draw_color
draw_color = "red"
# 노란색 버튼 함수
def yellowButton():
global draw_color
draw_color = "yellow"
# 파란색 버튼 함수
def blueButton():
global draw_color
draw_color = "blue"
# 녹색 버튼 함수
def greenButton():
global draw_color
draw_color = "green"
def get_absolute_coordinates(widget):
x = widget.winfo_rootx()
y = widget.winfo_rooty()
return x, y
def get_relative_coordinates(widget):
x = widget.winfo_x()
y = widget.winfo_y()
return x, y
def saveButton():
# 캔버스의 절대 좌표 구하기
c_a_x, c_a_y = get_absolute_coordinates(canvas)
c_r_x, c_r_y = get_relative_coordinates(canvas) # canvas의 상대 좌표
cf_r_x, cf_r_y = get_relative_coordinates(canvas_frame) # frame의 상대 좌표
cf_a_x, cf_a_y = get_absolute_coordinates(canvas_frame) # frame의 절대 좌표
w_a_x, w_a_y = get_absolute_coordinates(canvas.winfo_toplevel()) # 최상위 윈도우의 절대 좌표
print('캔버스의 절대 좌표1 ({}, {})'.format(c_a_x, c_a_y))
print('캔버스의 상대 좌표1 ({}, {})'.format(c_r_x, c_r_y))
print('캔버스 프레임의 절대 좌표1 ({}, {})'.format(cf_a_x, cf_a_y))
print('캔버스 프레임의 상대 좌표1 ({}, {})'.format(cf_r_x, cf_r_y))
print('최상위 윈도우의 절대 좌표1 ({}, {})'.format(w_a_x, w_a_y))
# canvas width, heigth
cw = canvas.winfo_width()
ch = canvas.winfo_height()
width = c_a_x + cw
height = c_a_y + ch
print('캔버스의 길이 {}'.format(cw))
print('캔버스의 높이 {}'.format(ch))
print('---------------------------------------')
# canvas area capture
image = ImageGrab.grab((c_a_x, c_a_y, width, height))
# save image
image.save("D:/jupyter/image/test{}.png".format(3))
# 윈도우를 생성한다
window = tk.Tk()
window.title("점선면 그림판")
window.configure(bg='blue')
# 스타일 프레임을 생성한다
style_frame = tk.Frame(window)
style_frame.grid(row=0, column=0, sticky=tk.W)
# 선택 그리기 버튼
select_button = tk.Button(style_frame, text="선택", width=3, command=selectButton)
select_button.grid(row=0, column=0, sticky=tk.W)
# 점그리기 버튼
point_button = tk.Button(style_frame, text=".", width=3, command=pointButton)
point_button.grid(row=0, column=1, sticky=tk.W)
# 선그리기 버튼
line_button = tk.Button(style_frame, text="/", width=3, command=lineButton)
line_button.grid(row=0, column=2, sticky=tk.W)
# 네모그리기 버튼
rectangle_button = tk.Button(style_frame, text="□", width=3, command=rectangleButton)
rectangle_button.grid(row=0, column=3, sticky=tk.W)
# 원그리기 버튼
circle_button = tk.Button(style_frame, text="○", width=3, command=circleButton)
circle_button.grid(row=0, column=4, sticky=tk.W)
# 텍스트 버튼
text_button = tk.Button(style_frame, text="T", width=3, command=textButton)
text_button.grid(row=0, column=5, sticky=tk.W)
# 저장 버튼 - TEST
save_button = tk.Button(style_frame, text="저장", width=3, command=saveButton)
save_button.grid(row=0, column=6, sticky=tk.W)
# 색상 프레임을 생성한다
color_frame = tk.Frame(window)
color_frame.grid(row=0, column=1, sticky=tk.E)
# 하얀색 버튼
white_button = tk.Button(color_frame, bg="white", width=3, command=whiteButton)
white_button.grid(row=0, column=0, sticky=tk.E)
# 검은색 버튼
black_button = tk.Button(color_frame, bg="black", width=3, command=blackButton)
black_button.grid(row=0, column=1, sticky=tk.E)
# 빨간색 버튼
red_button = tk.Button(color_frame, bg="red", width=3, command=redButton)
red_button.grid(row=0, column=2, sticky=tk.E)
# 파란색 버튼
blue_button = tk.Button(color_frame, bg="blue", width=3, command=blueButton)
blue_button.grid(row=0, column=3, sticky=tk.E)
# 노란색 버튼
yellow_button = tk.Button(color_frame, bg="yellow", width=3, command=yellowButton)
yellow_button.grid(row=0, column=4, sticky=tk.E)
# 초록색 버튼
green_button = tk.Button(color_frame, bg="green", width=3, command=greenButton)
green_button.grid(row=0, column=5, sticky=tk.E)
# 인포 프레임을 생성한다
info_frame = tk.Frame(window)
info_frame.grid(row=1, column=0, columnspan=2)
# 마우스 엔트리
mouse_text = tk.StringVar()
mouse_entry = tk.Entry(info_frame, textvariable=mouse_text, width=25)
mouse_entry.grid(row=0, column=0)
# 텍스트 라벨
input_label = tk.Label(info_frame, text=" Text Input:")
input_label.grid(row=0, column=1)
# 텍스트 엔트리
input_text = tk.StringVar()
input_entry = tk.Entry(info_frame, textvariable=input_text, width=15)
input_entry.grid(row=0, column=2)
# 캔버스 프레임을 생성한다
canvas_frame = tk.Frame(window, bd=2, bg="green")
canvas_frame.grid(row=2, column=0, columnspan=2, sticky=tk.W)
# 캔버스 생성한다
canvas = tk.Canvas(canvas_frame, width=400, height=300, bg="white")
canvas.pack()
# 마우스 이벤트 연결
canvas.bind("<Button-1>", mouseLDown) # 마우스 왼쪽 버튼 누렀을 때 이벤트
canvas.bind("<B1-Motion>", mouseMove) # 마우스 클릭하고 움직일 때 이벤트
canvas.bind("<ButtonRelease-1>", mouseLUp) # 마우스 왼쪽 버튼 클릭 해제할 때 이벤트
window.mainloop()
above is my code. The following is a picture of the result I expect with this code.
And here is a picture of the actual result.