How to add this function in my Rubik's Cube Timer?

78 views Asked by At

So here is the code i used to make this timer:

import tkinter as tk
import time
import keyboard

class RubiksTimerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Rubik's Cube Timer")

        self.start_time = None
        self.running = False
        self.elapsed_time = 0

        self.timer_label = tk.Label(root, text="0.000", font=("Helvetica", 72))
        self.timer_label.pack(pady=30)

        keyboard.on_press_key("space", self.space_pressed)
        keyboard.on_release_key("space", self.space_released)

        self.root.geometry("400x300")  # Set the window dimensions
        self.root.mainloop()

    def space_pressed(self, event):
        if not self.running:
            self.start_time = None  # Reset start_time
            self.timer_label.config(text="0.000")  # Reset the timer display

    def space_released(self, event):
        if not self.running:
            self.running = True
            self.start_time = time.time()
            self.elapsed_time = 0  # Reset elapsed_time when starting the timer
            self.update_timer()
        else:
            self.running = False
            elapsed_time = time.time() - self.start_time
            self.elapsed_time += elapsed_time

    def update_timer(self):
        if self.running:
            current_time = time.time() - self.start_time + self.elapsed_time
            self.timer_label.config(text=f"{current_time:.3f}")
        self.root.after(10, self.update_timer)

if __name__ == "__main__":
    root = tk.Tk()
    app = RubiksTimerApp(root)

and I want to add I want a function so when you release the space bar to start the timer, it will only start if you have held the spacebar for at least 0.5 seconds before releasing it.

2

There are 2 answers

1
acw1668 On BEST ANSWER

Simply record the two time when the spacebar is pressed and released, and then calculate the difference to determine whether to start the timer:

import time
import tkinter as tk

class RubiksTimerApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.geometry("400x300")
        self.title("Rubik's Cube Timer")

        self.running = False
        self.pressed_time = None   # for storing the time when spacebar is pressed

        self.timer_label = tk.Label(self, text="0.000", font=("Helvetica", 72))
        self.timer_label.pack(pady=30)

        # use tkinter binding instead of using keyboard module
        self.bind("<KeyPress-space>", self.space_pressed)
        self.bind("<KeyRelease-space>", self.space_released)

    def space_pressed(self, event):
        if self.pressed_time is None:
            # record the start time of pressing the spacebar
            self.pressed_time = time.time()

    def space_released(self, event):
        if not self.running:
            # check whether the spacebar has been pressed for more than half a second
            if (time.time() - self.pressed_time) >= 0.5:
                self.running = True
                self.start_time = time.time()
                self.update_timer()
        else:
            self.running = False
        self.pressed_time = None

    def update_timer(self):
        if self.running:
            elapsed_time = time.time() - self.start_time
            self.timer_label.config(text=f"{elapsed_time:.3f}")
            self.after(10, self.update_timer)

if __name__ == "__main__":
    app = RubiksTimerApp()
    app.mainloop()
2
JRiggles On

Tkinter has built-in functionality for keyboard events, so there's no need to import keyboard - I've fixed up your code a bit to use tkinter key bindings, and made it so your RubiksTimerApp class inherits from tk.Tk which is what you'll usually see for a tkinter app.

In order to set the timer after the spacebar is held for 500mS, I've used after to set a Boolean held_flag. If the user lets go of the spacebar before the timeout, the hold_time timeout is reset and the flag remains false. The timer will only start on spacebar release if the held_flag is set.

import tkinter as tk
import time
# import keyboard

class RubiksTimerApp(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title("Rubik's Cube Timer")

        self.start_time = None
        self.running = False
        self.elapsed_time = 0
        self.held_flag = False  # flag set when space is held for >= 500mS

        self.timer_label = tk.Label(self, text="0.000", font=("Helvetica", 72))
        self.timer_label.pack(pady=30)

        self.bind("<space>", self.space_pressed)
        self.bind("<KeyRelease space>", self.space_released)

        self.geometry("400x300")  # Set the window dimensions

    def space_pressed(self, event):
        if not self.running:
            self.start_time = None  # Reset start_time
            self.timer_label.config(text="0.000")  # Reset the timer display
            self.hold_time = self.after(500, self.set_held_flag)

    def set_held_flag(self):
        self.held_flag = True

    def space_released(self, event):
        self.after_cancel(self.hold_time)  # stop the hold timeout
        if self.held_flag:  # start the timer if the flag is set
            self.held_flag = False # reset the flag for later use
            if not self.running:
                self.running = True
                self.start_time = time.time()
                self.elapsed_time = 0  # Reset elapsed_time when starting the timer
                self.update_timer()
            else:
                self.running = False
                elapsed_time = time.time() - self.start_time
                self.elapsed_time += elapsed_time

    def update_timer(self):
        if self.running:
            current_time = time.time() - self.start_time + self.elapsed_time
            self.timer_label.config(text=f"{current_time:.3f}")
        self.after(10, self.update_timer)

if __name__ == "__main__":
    app = RubiksTimerApp()
    app.mainloop()