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

Python 海龟鼠标事件仅在超时后响应,而不是在您单击时响应,python,while-loop,onclick,turtle-graphics,Python,While Loop,Onclick,Turtle Graphics,当在随机方块中单击时,它仅在绘制下一个方块时才显示“您单击了!”,而不是在您最初单击时 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 dra

当在随机方块中单击时,它仅在绘制下一个方块时才显示“您单击了!”,而不是在您最初单击时

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秒钟循环结束后才说“你点击了!”而不是在你最初点击时说

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()
我不能在打印“youclicked!”的print语句之后放置break命令,因为它在循环之外

在此之间:

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

计算机必须按顺序运行,因此一次只能处理一行,因此,除非我弄错了,否则您的程序会被计时器“捕获”,然后运行整个程序并返回开始。
你可以用一个嵌套的if语句开发一个while循环,从设备中获取datetime,如果turtles有datetime,那么计算机必须按顺序运行,这样一次只能处理一行,因此,除非我弄错了,否则你的程序在计时器上被“捕获”,然后运行整个程序并返回开始。
如果Turtle具有基于事件的交互式GUI(图形用户界面)的datetime应用程序,这意味着它们在某些事件发生时执行操作,则可以使用嵌套的if语句开发一个while循环,该语句从设备获取datetime。对于这样的应用程序,如果您创建一个等待循环一段时间(就像您的代码一样),那么整个应用程序将在这段时间内被阻塞。这就是为什么
打印
仅在3s延迟后执行

所有GUI库都包含一个激活某些计时器事件的方案。对于turtle API,有一个
on_timer(func,delay)
方法,它在一些
延迟之后调用函数
func
(以毫秒表示)。我们的想法是每3000毫秒重复调用
drawbox
函数。因此,您的代码将基于两个主要回调函数:
get\u mouse\u click
调用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()
导入海龟
随机输入
t1=海龟。海龟()
t2=海龟。海龟()
s=海龟屏幕()
def海龟_设置()
t1.隐匿处()
t2.隐匿处()
s、 示踪剂(1,0)
s、 onclick(获取鼠标点击)#定义“点击”事件回调
def draw():
对于范围(2)中的i:
t1.fd(400)
t1.lt(90)
t1.fd(400)
t1.lt(90)
def drawbox():
全局框#将框坐标存储为全局变量
X=random.randint(0350)#以便可用于测试
Y=random.randint(0350)#在鼠标单击回调中
框=(X,Y,X+50,Y+50)
t2.clear()#在绘制新框之前,清除以前的框
t2.penup()
t2.后藤(X,Y)
t2.pendown()
对于范围(2)中的i:
t2.fd(50)
t2.lt(90)
t2.fd(50)
t2.lt(90)
s、 ontimer(drawbox,3000)#定义计时器事件回调
def获取鼠标点击(x,y):

如果具有交互式GUI(图形用户界面)的方框[0]应用程序是基于事件的,这意味着它们在某些事件发生时执行其操作。对于这样的应用程序,如果您创建一个等待循环一段时间(就像您的代码一样),那么整个应用程序将在这段时间内被阻塞。这就是为什么
打印
仅在3s延迟后执行

所有GUI库都包含一个激活某些计时器事件的方案。对于turtle API,有一个
on_timer(func,delay)
方法,它在一些
延迟之后调用函数
func
(以毫秒表示)。我们的想法是每3000毫秒重复调用
drawbox
函数。因此,您的代码将基于两个主要回调函数:
get\u mouse\u click
调用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()
导入海龟
随机输入
t1=海龟。海龟()
t2=海龟。海龟()
s=海龟屏幕()
def海龟_设置()
t1.隐匿处()
t2.隐匿处()
s、 示踪剂(1,0)
s、 onclick(获取鼠标点击)#定义“点击”事件回调
def draw():
对于范围(2)中的i:
t1.fd(400)
t1.lt(90)
t1.fd(400)
t1.lt(90)
def drawbox():
全局框#将框坐标存储为全局变量
X=random.randint(0350)#以便可用于测试
Y=random.randint(0350)#在鼠标单击回调中
框=(X,Y,X+50,Y+50)
t2.clear()#在绘制新框之前,清除以前的框
t2.penup()
t2.后藤(X,Y)
t2.pendown()
对于范围(2)中的i:
t2.fd(50)
t2.lt(90)
t2.fd(50)
t2.lt(90)
s、 ontimer(drawbox,3000)#定义计时器事件回调
def获取鼠标点击(x,y):

如果框[0]我相信你可以简化这个问题。主要是让海龟成为内盒,而不是内盒。这简化了绘图、擦除和事件处理。避免调用
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秒钟内点击内框,或者输掉游戏,那么我们可以引入@scirocorics建议的
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()
从海龟导入海龟,屏幕
从随机导入randint
边框尺寸=400
盒子尺寸=50
光标大小=20
单击_TIMEOUT=3000#毫秒
def move_box():
x=randint(框大小/2-边框大小/2,边框大小/2-框大小/2)
y=randint(盒子尺寸/