Turtle 鼠标事件仅在超时后响应,而不是在您单击时响应



当在随机方块内单击时,它仅在绘制下一个方块时显示"您单击了!",而不是在您最初单击时显示。

import turtle
import random
import time
t1 = turtle.Turtle()
t2 = turtle.Turtle()
s = turtle.Screen()
def turtle_set_up():
    t1.hideturtle()
    t2.hideturtle()
    t2.penup()
    s.tracer(1, 0)
def draw():
    for i in range(2):
        t1.fd(400)
        t1.lt(90)
        t1.fd(400)
        t1.lt(90)
def drawbox():
    t2.pendown()
    for i in range(2):
        t2.fd(50)
        t2.lt(90)
        t2.fd(50)
        t2.lt(90)
    t2.penup()
def box1():
    X = random.randint(0, 350)
    Y = random.randint(0, 350)
    Xleft = X
    Xright = X + 50
    Ytop = Y + 50
    Ybottom = Y
    t2.goto(X, Y)
    drawbox()

在这里,它会检查您的鼠标单击是否在绘制的框中。如果是,它会擦除旧框,以便每 3 秒绘制一个新框。

我不明白为什么它会等到3秒后说"你点击了!"而不是在你最初点击时说出来。

我无法在打印"您单击!"的打印语句之后放置中断命令,因为它在循环之外。

在这里之间:

    t_end = time.time() + 60 * 0.05
    while time.time() < t_end:
        def get_mouse_click_coor(x, y):
            X_click = x
            Y_click = y
            if Xright > X_click > Xleft and Ytop > Y_click > Ybottom:
                print('You clicked!')
        s.onclick(get_mouse_click_coor)
    t2.clear()

在这里:

def starter():
    turtle_set_up()
    draw()
    while 1:
        box1()
starter()

具有交互式GUI(图形用户界面(的应用程序是基于事件的,这意味着它们在某些事件发生时执行其操作。对于此类应用程序,如果在给定的时间内创建等待循环(就像代码一样(,则整个应用程序将在此时间内被阻止。这就是为什么print仅在 3s 延迟后执行的原因。

所有 GUI 库都包含激活某些计时器事件的方案。对于 turtle API,有一个 on_timer(func, delay) 方法,可以在一段时间delay(以毫秒表示(后调用函数func。这个想法是每 3000 毫秒重复调用一次 drawbox 函数。因此,您的代码将基于两个主要的回调函数:get_mouse_click在单击事件上调用,drawbox在计时器事件上调用。这是我建议的修改后的代码:

import turtle
import random
t1 = turtle.Turtle()
t2 = turtle.Turtle()
s = turtle.Screen()
def turtle_set_up():
    t1.hideturtle()
    t2.hideturtle()
    s.tracer(1, 0)
    s.onclick(get_mouse_click)   # define the 'click' event callback
def draw():
    for i in range(2):
        t1.fd(400)
        t1.lt(90)
        t1.fd(400)
        t1.lt(90)
def drawbox():
    global box                   # store box coordinates as global variable
    X = random.randint(0, 350)   # so that they are available for testing
    Y = random.randint(0, 350)   # in the mouse click callback
    box = (X, Y, X+50, Y+50)
    t2.clear()                   # clear previous box before drawing new one
    t2.penup()
    t2.goto(X, Y)
    t2.pendown()
    for i in range(2):
        t2.fd(50)
        t2.lt(90)
        t2.fd(50)
        t2.lt(90)
    s.ontimer(drawbox, 3000)     # define timer event callback
def get_mouse_click(x, y):
    if box[0] <= x <= box[2] and box[1] <= y <= box[3]:
        print('You clicked!')
def starter():
    turtle_set_up()
    draw()
    drawbox()
starter()

计算机必须按顺序运行,因此一次只能处理一行,因此,除非我弄错了,否则您的程序会在计时器上被"捕获",然后运行整个程序并返回到起点。您可以使用嵌套的 if 语句开发一个 while 循环,该语句从设备获取日期时间,如果海龟有日期时间

我相信

你可以简化这个问题。 主要是让成为内盒,而不是内盒。 这简化了绘制、擦除和事件处理。 在获得工作程序之前,请避免调用 tracer() 方法,因为它只会使调试复杂化。 我们也可以盖章而不是边框。

如果我们只是希望能够单击内框并将其随机移动到新位置:

from turtle import Turtle, Screen
from random import randint
BORDER_SIZE = 400
BOX_SIZE = 50
CURSOR_SIZE = 20
def move_box():
    x = randint(BOX_SIZE/2 - BORDER_SIZE/2, BORDER_SIZE/2 - BOX_SIZE/2)
    y = randint(BOX_SIZE/2 - BORDER_SIZE/2, BORDER_SIZE/2 - BOX_SIZE/2)
    turtle.goto(x, y)
def on_mouse_click(x, y):
    print("You clicked!")
    move_box()
screen = Screen()
turtle = Turtle('square', visible=False)
turtle.shapesize(BORDER_SIZE / CURSOR_SIZE)
turtle.color('black', 'white')
turtle.stamp()
turtle.shapesize(BOX_SIZE / CURSOR_SIZE)
turtle.onclick(on_mouse_click)
turtle.penup()
turtle.showturtle()
move_box()
screen.mainloop()

如果我们想让程序更像游戏,要求用户在每次移动后 3 秒内点击内框,或者输掉游戏,那么我们可以按照@sciroccorics的建议引入ontimer()事件:

from turtle import Turtle, Screen
from random import randint
BORDER_SIZE = 400
BOX_SIZE = 50
CURSOR_SIZE = 20
CLICK_TIMEOUT = 3000  # milliseconds
def move_box():
    x = randint(BOX_SIZE/2 - BORDER_SIZE/2, BORDER_SIZE/2 - BOX_SIZE/2)
    y = randint(BOX_SIZE/2 - BORDER_SIZE/2, BORDER_SIZE/2 - BOX_SIZE/2)
    turtle.goto(x, y)
    screen.ontimer(non_mouse_click, CLICK_TIMEOUT)
def on_mouse_click(x, y):
    global semaphore
    print("You clicked!")
    semaphore += 1
    move_box()
def non_mouse_click():
    global semaphore
    semaphore -= 1
    if semaphore < 1:
        turtle.onclick(None)
        turtle.color('black')
        print("Game Over!")
screen = Screen()
semaphore = 1
turtle = Turtle('square', visible=False)
turtle.shapesize(BORDER_SIZE / CURSOR_SIZE)
turtle.color('black', 'white')
turtle.stamp()
turtle.shapesize(BOX_SIZE / CURSOR_SIZE)
turtle.onclick(on_mouse_click)
turtle.penup()
turtle.showturtle()
move_box()
screen.mainloop()

最新更新