-1

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.

JRiggles
  • 4,847
  • 1
  • 12
  • 27
TaranJS
  • 15
  • 7
  • Does this work if you comment out this `#keyboard.on_press_key("space", self.space_pressed)`? Only the `keyboard.on_release_key` will work. – toyota Supra Aug 24 '23 at 15:17

2 Answers2

1

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()
JRiggles
  • 4,847
  • 1
  • 12
  • 27
  • Okay thanks for the clean up, but it still doesn't reach my goal of making 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. – TaranJS Aug 23 '23 at 13:41
  • I think I have a passable solution for you - see edit – JRiggles Aug 23 '23 at 13:50
0

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()
acw1668
  • 40,144
  • 5
  • 22
  • 34