【问题标题】:How to make two onscreenclicks execute after each other如何让两个屏幕点击相互执行
【发布时间】:2021-05-27 19:39:03
【问题描述】:

onscreenclick 函数有问题。我的代码中有两个onscreenclick 命令,当我按下屏幕时,它们都会同时执行,我想以某种方式使它在我第一次按下屏幕时执行第一个命令,第二次按下屏幕时执行第二个命令.

import turtle
import time
import random
from random import randint
from time import sleep
wn = turtle.Screen()
wn.title("Reaction test")
wn.setup(width=600,  height=600 )
wn.tracer(0)
wn.bgcolor("blue")
turtle.write("Click to start", move=False, align="center", font=("Arial", 40, "normal"))
from turtle import *
start = time.time()
def clicked(x, y):
    resetscreen()
    turtle.hideturtle()
    wn.setup(width=600, height=600)
    wn.tracer(0)
    wn.bgcolor("red")
    wn.title("Reaction test")
    turtle.write("   Click when the\nscreen turns green", move=False, align="center", font=("Arial", 40, "normal"))
    sleep(randint(5, 15))
    resetscreen()
    turtle.hideturtle()
    wn.setup(width=600, height=600)
    wn.tracer(0)
    wn.bgcolor("green")
    wn.title("Reaction test")
    turtle.write("CLICK!", move=False, align="center", font=("Arial", 40, "normal"))
    start
wn.listen()
wn.onscreenclick(clicked)
def click(x, y):
    ms = time.time() - start
    resetscreen()
    turtle.hideturtle()
    wn.setup(width=600, height=600)
    wn.tracer(0)
    wn.bgcolor("Green")
    wn.title("Reaction test")
    milliseconds = int(ms) * 1000
    turtle.write(("Your reaction time was",milliseconds,"milliseconds"), move=False, align="center", font=("Arial", 40, "normal"))
    wn.listen()
wn.onscreenclick(click)
wn.mainloop()

【问题讨论】:

    标签: python turtle-graphics


    【解决方案1】:

    在执行 wn.onscreenclick(click) 之前删除您的 clicked 侦听器

    类似的东西

    wn.onscreenclick(None) #remove previous listeners once it's executed.
    wn.onscreenclick(click)
    

    【讨论】:

    • 感谢您的响应,但不幸的是它不起作用,它仍然可以在 sama 时间结束
    【解决方案2】:

    使用全局点击计数器。然后从那里决定你的乌龟在你的点击例程中做什么。

    #! /usr/bin/python3
    
    from random import randint
    import time
    import turtle as tr
    
    turtle, screen  = tr .Turtle(),  tr .Screen()
    screen .setup( width=640,  height=480 )
    screen .title( 'Reaction test' )
    screen .bgcolor( 'blue' )
    screen .tracer( 5, 0 )
    turtle .hideturtle()
    turtle .penup()
    screen .update()
    
    C= 'center'
    smallfont = ( 'Arial', 33, 'normal' )
    largefont = ( 'Arial', 44, 'normal' )
    turtle .write( 'Click to start', align=C, font=largefont )
    clicks, start = 0, 0  ##  empty forward declarations
    
    def clicked(x, y):  ##  just use one click callback
        global clicks, start
        if clicks == 0:
            turtle .clear()
            screen .bgcolor( 'red' )
            turtle .write( '   Click when the\nscreen turns green', align=C, font=largefont )
            screen .update()
            time .sleep( randint(3, 5) )
            turtle .clear()
            screen .bgcolor( 'green' )
            turtle .write( 'CLICK!', align=C, font=largefont )
            screen .update()
            start = time .time()
            clicks += 1
        elif clicks == 1:
            now = time .time()
            turtle .clear()
            ms = round( (now -start) *1000,  3 )
            turtle .write( f'Your reaction time was\n  {ms} milliseconds', align=C, font=smallfont )
            screen .update()
            time .sleep( 2.5 )
            turtle .goto( 0, 100 )
            turtle .write( 'Thanks', align=C, font=largefont )
            time .sleep( 1.5 )
            screen .bye()
    
    screen .listen()
    screen .onscreenclick( clicked )
    screen .mainloop()
    

    【讨论】:

      【解决方案3】:

      您可以使用一个处理程序,跟踪到目前为止发生的点击次数,并相应地选择您在处理程序中的行为。这可能会因大量巨大的条件而变得混乱。

      另一种方法是仅从第一次点击开始侦听第二次点击。不要忘记删除每个侦听器,因为它们是一次性的。

      import random
      import time
      import turtle
      
      def write(msg):
          turtle.write(
              msg, 
              move=False, 
              align="center", 
              font=("Arial", 40, "normal")
          )
      
      class Timer:
          start = 0
      
      def on_first_click(x, y):
          turtle.Screen().onscreenclick(None)
          turtle.resetscreen()
          turtle.Screen().bgcolor("red")
          write("   Click when the\nscreen turns green")
          time.sleep(random.randint(5, 15))
          turtle.resetscreen()
          turtle.Screen().bgcolor("green")
          Timer.start = time.time()
          write("CLICK!")
          turtle.Screen().onscreenclick(on_second_click)
      
      def on_second_click(x, y):
          turtle.Screen().onscreenclick(None)
          elapsed_ms = round((time.time() - Timer.start) * 1000, 3)
          turtle.resetscreen()
          write(f"Your reaction time was\n{elapsed_ms} milliseconds")
          turtle.exitonclick()
      
      turtle.hideturtle()
      wn = turtle.Screen()
      wn.title("Reaction test")
      wn.setup(width=600, height=600)
      wn.tracer(0)
      wn.bgcolor("blue")
      write("Click to start")
      wn.onscreenclick(on_first_click)
      wn.mainloop()
      

      我删除了from turtle import *,它污染了全局命名空间并使代码难以理解。当您为所有内容添加 turtle 前缀时,很容易分辨出什么是海龟库函数以及您的代码的一部分。

      使用全局是不好的做法,因为共享状态往往会导致难以解开的错误,因此我使用 class Timer: timer = 0 来命名需要在点击处理程序之间共享的状态。

      上面的版本不是线程安全的,而是一次性使用的。如果你想循环运行它,这里有一个不错的下一步重构:

      import random
      import time
      import turtle
      
      def write(msg):
          turtle.write(
              msg, 
              move=False, 
              align="center", 
              font=("Arial", 40, "normal")
          )
      
      class Reaction:
          def __init__(self, turtle):
              self.turtle = turtle
              self.start_time = 0
      
          def on_first_click(self, x, y):
              self.turtle.Screen().onscreenclick(None)
              self.turtle.resetscreen()
              self.turtle.Screen().bgcolor("red")
              write("   Click when the\nscreen turns green")
              time.sleep(random.randint(5, 15))
              self.turtle.resetscreen()
              self.turtle.Screen().bgcolor("green")
              self.start = time.time()
              write("CLICK!")
              self.turtle.Screen().onscreenclick(self.on_second_click)
      
          def on_second_click(self, x, y):
              self.turtle.Screen().onscreenclick(None)
              elapsed_ms = round((time.time() - self.start) * 1000, 3)
              self.turtle.resetscreen()
              write(f"Your reaction time was\n{elapsed_ms} milliseconds")
              self.turtle.exitonclick()
      
          def run(self):
              self.start = 0
              self.turtle.hideturtle()
              wn = self.turtle.Screen()
              wn.title("Reaction test")
              wn.setup(width=600, height=600)
              wn.tracer(0)
              wn.bgcolor("blue")
              write("Click to start")
              wn.onscreenclick(self.on_first_click)
              wn.mainloop()
      
      if __name__ == "__main__":
          Reaction(turtle).run()
      

      【讨论】:

      • 感谢真的帮助了它
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-12-24
      • 2016-02-16
      • 1970-01-01
      • 2021-10-06
      • 2011-03-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多