Mike Smith
Mike Smith

Reputation: 456

Turtle: timer keeps blinking

I have some code for a timer:

from turtle import Screen, Turtle, bgcolor

# --- functions ---

def delSec(string):
    if len(string) == 1:
        return "0" + string
    else:
        return string

def tick():
    global milisecs, ticking


    turtle.clear()

    if milisecs < 0:
        turtle.write("TIMER DONE", align='center', font=FONT)
        ticking = False
        return
    else:
        turtle.write(delSec(str(milisecs//(60*60*10)))+":"+delSec(str((milisecs%(60*60*10))//(60*10)))+":"+delSec(str((milisecs%(60*10))//10))+":"+str(milisecs%10), align='center', font=FONT)
##        turtle.write(delSec(str(milisecs//(60*60)))+":"+delSec(str((milisecs%(60*60))//(60)))+":"+delSec(str((milisecs%(60))//1)), align='center', font=FONT)
        if not paused:
              milisecs -= 1

    screen.ontimer(tick, 100)

def reset():
    global milisecs, ticking, key_reset, key_pause, key_both
    #global paused

    print("reset")

    screen.onkey(None, key_reset)  # Disable event handler inside handler
    screen.onkey(None, key_pause)  # Disable event handler inside handler
    screen.onkey(None, key_both)

    milisecs = sum(time*10)

    if not ticking:
        ticking = True
        tick()

    #paused = False

    screen.onkey(reset, key_reset)  # Reenable event handler
    screen.onkey(pause, key_pause)  # Reenable event handler
    screen.onkey(both, key_both)

def both():
    reset()
    pause()

def pause():
    global paused

    print("pause/unpause")

    paused = not paused

# --- main ---

bgcolor('darkblue')
FONT = ("Arial", 60, "normal")

strings = input("Please enter the time: ").strip().split(' ')

time = [60 ** (len(strings) - index - 1) * int(unit) for index, unit in enumerate(strings)]

milisecs = -1
ticking = False
paused = False
key_reset = "r"
key_pause = "p"
key_both = "b"

screen = Screen()

turtle = Turtle()
turtle.hideturtle()
turtle.color('white')

reset()

screen.listen()
screen.mainloop()

Since it is changing every 10th of a second, it keeps blinking. It is kind of annoying because if I am trying to do something while using this timer, then it gets really annoying. Is there any way to make this smooth instead of constant blinking currently? Thanks! (I have currently set it to where it shows time up to a 10th of a second, and I would like to keep it that way)


EDIT: If you want to change the code, feel free to do so, I would just like it if you would keep the current functions the same, so don't make it so something else doesn't work anymore. Thanks!

Upvotes: 2

Views: 387

Answers (1)

cdlane
cdlane

Reputation: 41925

I've changed your (actually our) code minimally to get rid of flicker by introducing the tracer() and update() screen methods. This tells turtle that we know best when to (manually) update the screen and stop doing so automatically:

from turtle import Screen, Turtle

# --- constants ---

FONT = ("Arial", 60, "normal")

KEY_RESET = "r"
KEY_PAUSE = "p"
KEY_BOTH = "b"

# --- functions ---

def delSec(string):
    if len(string) == 1:
        return "0" + string

    return string

def tick():
    global milisecs, ticking

    turtle.clear()

    if milisecs < 0:
        turtle.write("TIMER DONE", align='center', font=FONT)
        screen.update()
        ticking = False
        return

    turtle.write( \
        delSec(str(milisecs // (60*60*10))) + ":" + \
        delSec(str((milisecs % (60*60*10)) // (60*10))) + ":" + \
        delSec(str((milisecs % (60*10)) // 10)) + "." + \
        str(milisecs % 10), align='center', font=FONT)

    screen.update()

    if not paused:
        milisecs -= 1

    screen.ontimer(tick, 100)

def reset():
    global milisecs, ticking

    print("reset")

    screen.onkey(None, KEY_RESET)  # Disable event handler inside handler
    screen.onkey(None, KEY_PAUSE)  # Disable event handler inside handler
    screen.onkey(None, KEY_BOTH)

    milisecs = sum(time*10)

    if not ticking:
        ticking = True
        tick()

    screen.onkey(reset, KEY_RESET)  # Reenable event handler
    screen.onkey(pause, KEY_PAUSE)  # Reenable event handler
    screen.onkey(both, KEY_BOTH)

def both():
    reset()
    pause()

def pause():
    global paused

    print("pause/unpause")

    paused = not paused

# --- main ---

strings = input("Please enter the time: ").strip().split(' ')

time = [60 ** (len(strings) - index - 1) * int(unit) for index, unit in enumerate(strings)]

milisecs = -1
ticking = False
paused = False

screen = Screen()
screen.bgcolor('darkblue')
screen.tracer(False)

turtle = Turtle()
turtle.hideturtle()
turtle.color('white')

reset()

screen.listen()
screen.mainloop()

I also made some small code tweaks as well as change the tenths of seconds presentation from being "45:7" to more standardized "45.7". Revert as you see fit.

Upvotes: 1

Related Questions