海龟鼠标事件仅在超时后响应,而不是在您单击时响应
Turtle mouse event only responds after timeout, not as you click
在随机方块内单击时,它仅在绘制下一个方块时显示 "You clicked!",而不是在您最初单击时显示。
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 秒循环结束时才说 "You clicked!",而不是在您最初点击时说。
我无法在打印 "You clicked!" 的 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()
这里:
def starter():
turtle_set_up()
draw()
while 1:
box1()
starter()
计算机必须按顺序 运行 所以它一次只能处理一行,所以,除非我弄错了,否则你的程序在计时器上得到 'caught' 然后 运行s 通过程序并返回到开始。
如果海龟有 datetime
,你可以开发一个带有嵌套 if 语句的 while 循环,从设备获取日期时间
具有交互式 GUI(图形用户界面)的应用程序是 event-based,这意味着它们会在某些事件发生时执行它们的操作。对于此类应用程序,如果您为给定的时间创建了一个等待循环(就像您的代码一样),那么整个应用程序将被阻塞这段时间。这就是为什么 print
只在 3s 延迟后执行。
所有 GUI 库都包含激活某些计时器事件的方案。对于乌龟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()
我相信你可以简化这个问题。主要是通过制作海龟 be 内盒而不是 drawing 内盒。这简化了绘图、擦除和事件处理。在你有一个工作程序之前避免调用 tracer()
方法,因为它只会使调试复杂化。我们也可以 stamp 而不是 draw 边框。
如果我们只是希望能够点击内框并使其随机移动到新位置:
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()
如果我们想让程序更game-like,要求用户在每次走棋3秒内点击内框,否则就输了,那么我们可以引入ontimer()
@sciroccorics 建议的事件:
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()
在随机方块内单击时,它仅在绘制下一个方块时显示 "You clicked!",而不是在您最初单击时显示。
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 秒循环结束时才说 "You clicked!",而不是在您最初点击时说。
我无法在打印 "You clicked!" 的 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()
这里:
def starter():
turtle_set_up()
draw()
while 1:
box1()
starter()
计算机必须按顺序 运行 所以它一次只能处理一行,所以,除非我弄错了,否则你的程序在计时器上得到 'caught' 然后 运行s 通过程序并返回到开始。 如果海龟有 datetime
,你可以开发一个带有嵌套 if 语句的 while 循环,从设备获取日期时间具有交互式 GUI(图形用户界面)的应用程序是 event-based,这意味着它们会在某些事件发生时执行它们的操作。对于此类应用程序,如果您为给定的时间创建了一个等待循环(就像您的代码一样),那么整个应用程序将被阻塞这段时间。这就是为什么 print
只在 3s 延迟后执行。
所有 GUI 库都包含激活某些计时器事件的方案。对于乌龟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()
我相信你可以简化这个问题。主要是通过制作海龟 be 内盒而不是 drawing 内盒。这简化了绘图、擦除和事件处理。在你有一个工作程序之前避免调用 tracer()
方法,因为它只会使调试复杂化。我们也可以 stamp 而不是 draw 边框。
如果我们只是希望能够点击内框并使其随机移动到新位置:
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()
如果我们想让程序更game-like,要求用户在每次走棋3秒内点击内框,否则就输了,那么我们可以引入ontimer()
@sciroccorics 建议的事件:
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()