Мы можем решить эту проблему так, как вы пытались, но мы должны добавить обработчики щелчков на экране в определенном порядке и воспользоваться преимуществом мало используемого параметра add
:
from turtle import Screen, Turtle, mainloop
FONT_SIZE = 20
FONT = ('Arial', FONT_SIZE, 'normal')
def draw_square(x, y):
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
for _ in range(4):
turtle.forward(50)
turtle.left(90)
def button_clicked(x, y):
if 100 < x < 100 + text_width and -FONT_SIZE/2 - 100 < y < FONT_SIZE/2 - 100:
quit()
def make_close_button(x, y):
turtle.penup()
turtle.setposition(x, y - FONT_SIZE / 2)
turtle.write("close", move=True, font=FONT)
width = turtle.xcor() - x # pixel width of text we just wrote
turtle.pendown()
for _ in range(2):
turtle.left(90)
turtle.forward(FONT_SIZE)
turtle.left(90)
turtle.forward(width)
turtle.penup()
turtle.home()
return width
turtle = Turtle()
text_width = make_close_button(100, -100)
screen = Screen()
screen.onscreenclick(button_clicked)
screen.onscreenclick(draw_square, add=True)
mainloop()
Но этот подход затрудняет отключение события onscreenclick()
внутри кода обработчика событий. То есть, пока один квадрат все еще рисуется, вы можете щелкнуть в любом месте экрана и начать второй, мешая завершению первого. Чтобы решить эту проблему, мы могли бы попробовать совершенно другой подход с единственной функцией-обработчиком событий, которую мы можем отключить и включить при необходимости:
from turtle import Screen, Turtle, mainloop
FONT_SIZE = 20
FONT = ('Arial', FONT_SIZE, 'normal')
def draw_square():
for _ in range(4):
turtle.forward(50)
turtle.left(90)
def button_clicked(x, y):
screen.onscreenclick(None) # disable event handler inside event handler
if button.distance(x, y) < FONT_SIZE:
quit()
turtle.penup()
turtle.goto(x, y)
turtle.pendown()
draw_square()
screen.onscreenclick(button_clicked)
def make_close_button(x, y):
button = Turtle(visible=False)
button.speed('fastest')
button.penup()
button.setposition(x, y - FONT_SIZE / 2)
button.write("close", move=True, font=FONT)
width = button.xcor() - x # pixel width of text we just wrote
button.pendown()
for _ in range(2):
button.left(90)
button.forward(FONT_SIZE)
button.left(90)
button.forward(width)
button.penup()
button.setposition(x + width / 2, y)
return button
button = make_close_button(100, -100)
turtle = Turtle()
screen = Screen()
screen.onscreenclick(button_clicked)
mainloop()
Здесь мы немного разбили функциональность, чтобы иметь функции с конкретными обязанностями. И вместо того, чтобы выяснить, щелкнули ли мы рядом с кнопкой, мы оставили черепаху позади и просто проверили расстояние щелчка от этой черепахи.
Оба подхода имеют свои преимущества и недостатки.