如何分别处理乌龟点击和乌龟点击?

时间:2020-06-12 01:53:24

标签: python-3.x onclick turtle-graphics

使用Python 3“ turtle”模块,我试图分别处理两种不同的点击条件:

  1. 如果单击了乌龟,则应调用一个函数。 (在下面的示例中,它应该从黑色切换为红色,反之亦然。)
  2. 如果未点击(可见)乌龟,则应调用其他功能(在该位置创建乌龟)。

现在,我可以使用两个不同的鼠标按钮来完成这项工作,就像这样:

#!/usr/local/bin/python3

import turtle

sc = turtle.Screen()

def new_turtle(x, y):
  t = turtle.RawTurtle(sc, shape='circle', visible=False)
  t.penup()
  t.speed(0)
  t.goto(x, y)
  t.color('black')
  t.showturtle()
  t.onclick(selector(t), 2)

def deselector(t):
  def deselect(x, y):
    t.color('black')
    t.onclick(selector(t), 2)
  return deselect

def selector(t):
  def select(x, y):
    t.color('red')
    t.onclick(deselector(t), 2)
  return select

sc.onscreenclick(new_turtle, 1)

turtle.mainloop()

但是,我想用鼠标第二键做其他事情。

如果将以上代码更改为使用鼠标按钮1进行所有操作,则在按预期的方式单击时,海龟的确会更改颜色,但是onscreenclick处理程序也 称为几乎在变色的乌龟正上方创建了一只新乌龟。

如果对乌龟的点击不是 ,有什么方法只能调用onscreenclick处理程序吗?

1 个答案:

答案 0 :(得分:1)

我相信以下内容将满足您的描述。如您所述,如果在同一个按钮上同时有一个屏幕按钮事件处理程序和一个乌龟按钮事件处理程序,则两者都会被触发!对于坐在tkinter之上的初学者友好的编程环境来说,这似乎是错误的。但是你有。

我下面的解决方案是让屏幕按钮事件处理程序测试单击是否可能是在乌龟上进行的,如果是,则将其忽略。这样一来,乌龟按钮事件处理程序就可以处理点击:

from turtle import Screen, Turtle
from functools import partial

CURSOR_SIZE = 20

def new_turtle(x, y):
    screen.onscreenclick(None)  # disable event handler inside handler

    # don't respond if the click was on a turtle
    if not any(t.distance(x, y) <= CURSOR_SIZE/2 for t in screen.turtles()):
        t = Turtle(shape='circle', visible=False)
        t.color('black')
        t.penup()
        t.goto(x, y)
        t.showturtle()
        t.onclick(partial(select, t))

    screen.onscreenclick(new_turtle)  # reenable event handler

def select(t, x, y):
    t.color('black' if t.pencolor() == 'red' else 'red')

screen = Screen()

screen.onscreenclick(new_turtle)

screen.mainloop()

一个副作用是,在屏幕上远离海龟的位置单击会变得缓慢,因为许多海龟已添加到屏幕中,需要进行测试。为了解决这个问题,我至少在系统上注意到,在屏幕按钮事件处理程序之前 调用了海龟按钮事件处理程序。因此,诀窍是让乌龟按钮事件处理程序禁用屏幕按钮事件处理程序,但最终重新启用它:

from turtle import Screen, Turtle
from functools import partial, update_wrapper

def new_turtle(x, y):
    screen.onscreenclick(None)  # disable this event handler inside handler

    t = Turtle(shape='circle', visible=False)
    t.color('black')
    t.penup()
    t.goto(x, y)
    t.showturtle()
    t.onclick(partial(select, t))

    screen.onscreenclick(new_turtle)  # reenable event handler

def select(t, x, y):
    screen.onscreenclick(None)  # disable screen event handler inside handler
    t.onclick(None)  # disable this event handler inside handler

    t.color('black' if t.pencolor() == 'red' else 'red')

    t.onclick(partial(select, t))  # reenable this event handler
    screen.ontimer(wrapper)  # reenable screen event handler, eventually

screen = Screen()

wrapper = partial(screen.onscreenclick, new_turtle)  # prep wrapper for later use
update_wrapper(wrapper, screen.onscreenclick)

screen.onscreenclick(new_turtle)

screen.mainloop()

这不需要检查海龟,因此不会放慢速度。 (也不要在靠近海龟的地方那样挑剔。)但是,如果时间安排不一样,则可能必须使用其他版本。

相关问题