0

I am trying to build a CPS-Test app with Python Tkinter. I have been trying to make a button that when clicked, increases your clicks (data["count"]). It takes your clicks in 10 seconds and calculates the speed. Then it destroys the window and prints the speed.

I will soon remove the print thing but for now I want to keep it while the problem is still there. However, what is happening is my window is not rendering until 10 seconds is up, so as soon as you click the button, it just ends and the speed is 0.1 cps.

I don't understand why this is happening, as no errors are popping up. I tried modifying the code so the Button is rendered first, which made the page show, but then an error pops up saying that the Button command is not defined until after the Button is made.

I tried using the .pack method after making the button and keeping them separate, but it didn't work and ended up doing the same thing. Why is this happening?

from tkinter import *
from time import sleep

tab = Tk()
tab.geometry('500x500')
tab.resizable(0, 0)
tab.title("")

data = {"count": 0, "time": 0}

def click():
  data["count"] += 1
  if data["time"] == 10:
    cps = data["count"]/data["time"]
    Label(tab, text = str(cps) + " clicks per second!", font = "helvetica 30 bold underline italic", padx = 50, pady = 50).pack()
    print(cps)
    tab.destroy()
    quit()

btn = Button(tab, text = 'Click Me!', font = "helvetica 24 bold", command = click, background = "blue", activebackground = "yellow").pack()

def countTime():
  sleep(1)
  data["time"] += 1

for i in range(0, 10):
  countTime()
martineau
  • 119,623
  • 25
  • 170
  • 301
  • 1
    While your code is running `sleep(1)`, it is *not doing anything else* - such as updating the display, or responding to user input. In the specific case of Tkinter, you need to use the `.after()` method to schedule your action for some point in the future, rather than waiting for it. – jasonharper Aug 02 '22 at 00:29
  • The code in your question never renders or prints *anything*. It takes about 10 seconds to execute because of the calls to `sleep()` — not your `click()` function —, but no window is rendered and nothing is printed. That (obviously) means there is no button to click. Please provide a [mre]. Note that generally-speaking, tkinter applications require a call to `mainloop()` in order to work. – martineau Aug 02 '22 at 01:25

1 Answers1

0

I'm surprised the button actually shows at all. You typically need to call mainloop to get your widgets to show as seen in the example here. So your code first constructs a button with

btn = Button(tab, text = 'Click Me!', ...).pack()

but at this point the widget isn't shown as you haven't called mainloop and if you did call mainloop the code would stop there before your loop and calls to countTime waiting until the TK app exited. This how how the threading model works. But, since you didn't call mainloop your code then goes into a loop that lasts 10 seconds (10 calls to countTime which each sleep for 1 second) before being complete without ever calling mainloop and hence never showing the button.

What you need to do is use the after method, or similar, as demonstrated here. you could also read that section linked above on the threading model and use a Python thread to do the counting.

Oliver Dain
  • 9,617
  • 3
  • 35
  • 48