如何分别处理海龟的点击和海龟的点击? [英] How to handle clicks on a turtle and clicks off of a turtle separately?

查看:80
本文介绍了如何分别处理海龟的点击和海龟的点击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Using the Python 3 "turtle" module, I am trying to handle two different click conditions separately:

  1. 如果一个海龟被点击,它应该调用一个函数.(在下面的示例中,它应该从黑色切换到红色,反之亦然.)
  2. 如果点击不是在(可见的)海龟上,则应调用不同的函数(在该点创建海龟).

现在我可以使用两个不同的鼠标按钮来完成这项工作,如下所示:

Right now I can make this work using two different mouse buttons, like so:

#!/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()

但是,我想将第二个鼠标按钮用于其他操作.

However, I want to use the second mouse button for other things.

如果将上面的代码更改为对所有内容都使用鼠标按钮 1,那么海龟在点击时确实会像预期的那样改变颜色,但是 onscreenclick 处理程序也是 > 调用这样一个新的海龟几乎就在改变颜色的海龟上方创建.

If the above code is changed to use mouse button 1 for everything, the turtles do change color when clicked like they're supposed to, but the onscreenclick handler is also called so that a new turtle is created almost right above the turtle that changes color.

如果点击不是在海龟上,有没有办法只调用onscreenclick处理程序?

Is there any way to only call the onscreenclick handler if the click is not on a turtle?

推荐答案

我相信以下内容可以满足您的描述.正如您所指出的,如果屏幕按钮事件处理程序和海龟按钮事件处理程序在同一个按钮上都处于活动状态,则两者都会被触发!对于位于 tkinter 之上的初学者友好编程环境来说,这似乎是错误的.但是你有它.

I believe the following will do what you describe. As you noted, if there is both a screen button event handler and a turtle button event handler active on the same button, both get triggered! This seems wrong for a beginner friendly programming environment sitting atop tkinter. But there you have it.

我下面的解决方案是让屏幕按钮事件处理程序测试点击是否可能是在海龟上,如果是,则忽略它.这让海龟按钮事件处理程序处理点击:

My solution below is to have the screen button event handler test if the click was likely over a turtle, and, if so, ignore it. This lets just the turtle button event handler deal with the click:

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()

一个副作用是在远离海龟的屏幕上点击会变得有点迟钝,因为许多海龟被添加到屏幕上并且需要进行测试.为了解决这个问题,我注意到,至少在我的系统上,海龟按钮事件处理程序在 屏幕按钮事件处理程序之前被调用.所以诀窍是让海龟按钮事件处理程序禁用屏幕按钮事件处理程序,但最终重新启用它:

One side effect is that clicking on the screen away from turtles gets slightly sluggish as lots of turtles are added to the screen and need to be tested. To get around this, I noticed, on my system at least, that turtle button event handlers are invoked before screen button event handlers. So the trick is to have the turtle button event handler disable the screen button event handler, but eventually reenable it:

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()

这不需要检查海龟,所以不会放慢速度.(也不要太挑剔,因为您在离乌龟很近的地方点击.)但是,如果时间不匹配,您可能必须使用其他版本.

This does not require examing the turtles so won't slow down. (Nor be as finicky as you click very close to the turtle.) However if the timing doesn't match up the same, you might have to use the other version.

这篇关于如何分别处理海龟的点击和海龟的点击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆