【问题标题】:Add delays between two successively executed functions在两个连续执行的函数之间添加延迟
【发布时间】:2016-03-18 18:40:44
【问题描述】:

我想,如果用户连续调用两个函数,两个函数之间会有某种类型的“延迟”,以便在执行第一个函数时不会中断按键。也许像队列这样的东西会做。为了形象化我在说什么,下面是我要调用的函数,根据按键,在海龟图形窗口中绘制其对应的字母:

def draw_H():
    # Draw the left leg of H.
    # The turtle starts at the bottom left of the letter, pointing right.
    left(90)
    forward(letter_height)
    # Draw the bar of the H.
    # The turtle starts at the top of the left leg, pointing up.
    forward(-letter_height/2)
    right(90)
    forward(letter_width)
    # Draw the right leg of the H.
    # The turtle starts at the right side of the bar, pointing right.
    left(90)
    forward(letter_height/2)
    forward(-letter_height)
    right(90)
    # The H is drawn.
    # The turtle is in the top right, pointing right.
    draw_space()


def draw_E():
    # Draw an E.
    left(90)
    forward(letter_height)
    right(90)
    forward(letter_width)
    forward(-letter_width)
    right(90)
    forward(letter_height/2)
    left(90)
    forward(letter_width)
    forward(-letter_width)
    right(90)
    forward(letter_height/2)
    left(90)
    forward(letter_width)
    draw_space()

def draw_L():
    # Draw an L
    left(90)
    forward(letter_height)
    forward(-letter_height)
    right(90)
    forward(letter_width)
    draw_space()

def draw_O():
    # Draw an O
    forward(letter_width)
    left(90)
    forward(letter_height)
    left(90)
    forward(letter_width)
    left(90)
    forward(letter_height)
    left(90)
    forward(letter_width)
    draw_space()

def draw_W():
    # This function will draw a W
    left(105)
    forward(letter_height)
    backward(letter_height)
    right(40)
    forward(letter_height/2)
    right(131)
    forward(letter_height/2)
    left(141)
    forward(letter_height)
    right(165)
    penup()
    forward(letter_height)
    left(90)
    draw_space()        

def draw_R(letter_width, letter_height):
    # This function will draw an R

    slant_height = (math.sqrt(letter_width**2 + (letter_height/2)**2))
    slant_angle = (90+(90-(math.degrees(math.acos(letter_width/slant_height)))))
    space_angle = (180 - slant_angle)

    left(90)
    forward(letter_height)
    right(90)
    forward(letter_width)
    right(90)
    forward(letter_height/2)
    right(90)
    forward(letter_width)
    left(slant_angle)
    forward(slant_height)
    left(space_angle)
    draw_space()

def draw_D(letter_width, letter_height):
    # This function will draw a REAL D

    angle_height = math.sqrt(letter_width**2 + (letter_height/2)**2)
    D_angle = (90+(math.degrees(math.acos(letter_width/angle_height))))
    Second_D_angle = ((90 - (D_angle-90)) + (90-(math.degrees(math.acos(letter_width/angle_height)))))
    D_space_angle = (math.degrees(math.atan(letter_width/(letter_height/2))))

    left(90)
    forward(letter_height)
    right(D_angle)
    forward(angle_height)
    right(Second_D_angle)
    forward(angle_height)
    left(90+D_space_angle)
    penup()
    forward(letter_width)
    draw_space()

下面是如何调用函数来绘制相应的字母:

onkey(draw_H, "h")
onkey(draw_E, "e")
onkey(draw_L, "l")
onkey(draw_O, "o")
onkey(draw_W, "w")
onkey(lambda: draw_R(letter_width, letter_height), "r")
onkey(lambda: draw_D(letter_width, letter_height), "d")

现在发生的情况是,当调用函数并且用户重复按住/按下对应函数的相同键时,会发生这种情况:

^这是当我按住 H 键时发生的情况。另外:

^这就是我快速连续键入 R 和 H 时发生的情况。我希望在调用这些函数和激活它们之间有一点延迟,这样每个函数都能够完成它的过程,乌龟不会到处发疯。非常感谢有关此问题的任何帮助! :)

【问题讨论】:

  • 您在寻找time.sleep吗?
  • @senshin 好吧,time.sleep 只是在有限的时间内“暂停”执行。想要的是,如果用户快速连续调用两个函数,则第一个函数调用完成,而第二个函数等待它完成,有点像队列。
  • 嗯,有很多或代码和很多或与问题无关...下次您应该尝试构建minimal reproducible example。你至少应该给出一个准确的例子,因为 Python 只执行一条指令,而前一条指令返回......
  • @R.Kap 肯定这就是非并行程序的定义。
  • @SergeBallesta 请检查现在编辑的帖子。

标签: python function python-3.x turtle-graphics


【解决方案1】:

欢迎来到事件编程的世界!

让我们暂时忘记海龟吧。当某些字符在键盘上被击中时,您希望您的程序绘制绘图。但是当你在画一些东西时,你不希望另一个角色的命中开始一个新的绘图。因此,如果一个处于活动状态,您希望它不进入新的绘图过程。你只需要一点同步。

由于所有都发生在同一个线程中(无论如何,如果不同的线程尝试访问屏幕,大多数 GUI 的行为都会很糟糕),您实际上应该使用队列来保存绘图请求,如果您已经在绘图,则只需将请求排队:

q = Queue.Queue()
drawing = False
drawingLock = threading.Lock()

def draw(x):
    global drawing
    q.put(x)
    process = False:
    drawingLock.acquire()
    if not drawing:
        process = True
        drawing = True
    drawingLock.release()
    if process:
        while not q.empty():
            do_draw(q.get())  # call the actual drawings here
        drawingLock.acquire()
        drawing = False
        drawingLock.release()

这个 draw 函数应该从 onclick 事件中调用,并将绘图分派给您的实际绘图函数。

【讨论】:

  • 我试过了,我导入了正确的模块,但我仍然收到错误Traceback (most recent call last): File "/Users/Rohan/Google Drive/K12 High School Documents/Computer_Science/section_5/assignment_5a.py", line 452, in <module> drawingLock = thread.allocate_lock() NameError: name 'thread' is not defined
  • 好的,我导入了threading,然后输入了drawingLock = **threading**.allocate_lock(),但现在我收到了错误Traceback (most recent call last): File "/Users/Rohan/Google Drive/K12 High School Documents/Computer_Science/section_5/assignment_5a.py", line 452, in <module> drawingLock = threading.allocate_lock() AttributeError: module 'threading' has no attribute 'allocate_lock'
  • 我没有注意到你使用的是Python3。在 Python 2 中,您可以使用 import threaddrawingLock = thread.allocate_lock()import threadingdrawingLock = threading.Lock()。但在 Python3 中,threading.Lock() 是推荐的方式(旧的低级 thread 并在 Python 3 中更名为 _thread,这意味着它现在是一个实现细节)
  • 嗯,这有助于程序开始,但现在,每当我输入与特定函数对应的字母时,我都会得到do_draw(q.get()) # call the actual drawings here NameError: name 'do_draw' is not defined'
  • @R.Kap:你必须写do_draw。它只是draw_Hdraw_E、...的包装器。
猜你喜欢
  • 2021-10-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多