I want to add global hotkey (using the pynput module) to my Tkinter script (Random Number Generator). I want to get random number every time I press 'f7' button. It also has to work without focusing on the app. Unfortunately the app is not responding after a while. It worked once/twice but after a minute or so it got frozen.
import tkinter as tk
import random
from pynput import keyboard
rng = random.SystemRandom()
def Draw():
global text
frame=tk.Frame(root,width=100,height=100,relief='solid',bd=0)
frame.place(relx = 0.5, rely = 0.5, anchor = 'center')
text=tk.Label(frame,text='HELLO', font = "Helvetica 65 bold", justify='center')
text.pack()
def on_press(key):
try:
k = key.char
except:
k = key.name
if k in ['f7']:
return False #stop listening
n = 0
def Refresher():
global text
global n
text.configure(text=rng.randint(0,100), fg ="white", bg = "black")
root.after(100, Refresher)
if n == 1:
listener = keyboard.Listener(on_press=on_press)
listener.start()
listener.join()
n = 1
root=tk.Tk()
root["bg"] = "black"
root.title("RNG")
Draw()
Refresher()
root.mainloop()
I found the solution. We need bindglobal library and then we have global hotkeys in Tkinter. More info: https://libraries.io/pypi/bindglobal
My code:
import tkinter as tk
import random
from bindglobal import BindGlobal
rng = random.SystemRandom()
def Draw():
global text
frame=tk.Frame(root,width=100,height=100,relief='solid',bd=0)
frame.place(relx = 0.5, rely = 0.5, anchor = 'center')
text=tk.Label(frame,text='HELLO', font = "Helvetica 65 bold", justify='center')
text.configure(text=rng.randint(0,100), fg ="white", bg = "black")
text.pack()
def Refresher(e):
global text
text.configure(text=rng.randint(0,100), fg ="white", bg = "black")
root = tk.Tk()
root.title("RNG - F7")
root["bg"] = "black"
Draw()
bg = BindGlobal()
bg.start()
bg.gbind("<f7>",Refresher)
root.mainloop()
Plus I needed to modify the mentioned library because there was no support for 'F7' button.
Find and open bindglobal/init.py and add 'f7', e.g. like this:
class TkKeys(object):
tk_keys = {}
for i in ( 'space','BackSpace', 'Tab'
, 'Delete', 'End', 'Home', 'Caps_Lock'
,'Left','Right', 'Up', 'Down', 'f7'
,'Menu','Insert', 'Pause', 'Num_Lock', 'Scroll_Lock' #Those fails on OSX
):
Related
I try make own autoclicker with GUI but I don't know how make CPS(Clicks per second).
I have tried in different ways but nothing work. Please for help with solution on this problem.
from tkinter import *
import time
running = False
cps_counter = 0
def scanning():
global cps_counter
cps_chk = cpscheck.get()
delay = 1/int(cps_chk)
if running:
cps_counter += 1
label.configure(text=f'{cps_counter}')
time.sleep(delay)
def start():
global running
if running == False:
running = True
else:
running = False
window = Tk()
window.title("Title")
window.geometry("500x500")
start = Button(window, text="Start/Stop Scan", command=start)
start.grid()
cpscheck = StringVar()
textBox = Entry(bd=0, bg="#545454", highlightthickness=0, textvariable=cpscheck, font=("Helvetica", 20), fg="white", justify='center')
textBox.place( x=250, y=123, width=85.0, height=25)
label = Label(text=cps_counter)
label.place(x=100, y=100)
window.after(100, scanning) # After 1 second, call scanning
window.mainloop()
I am trying to make a game using a countdown timer for 60s.
My issue is that as the countdown timer is recursive, it keeps running until t == 0 when it runs the endgame() function.
if you pass the level, the initial countdown timer will still end after 60s which in turn will end the game. I need a way to run the next level without the initial countdown ending and ending the game.
I have tried using if True statements at the start of the function which only paused the loop until the next instance of the function started.
code:
from tkinter import *
import ctypes
from scrambld_back import *
from tkinter import font
import time
from nltk.corpus import words
user32 = ctypes.windll.user32
screensize = [user32.GetSystemMetrics(0), user32.GetSystemMetrics(1)]
root = Tk()
root.geometry(f'500x500+{screensize[1]-250}+100')
root.title('Scrambld')
root.configure(bg='white')
over = Tk()
over.geometry(f'500x500+{screensize[1]-250}+100')
root.title('Scrambld')
root.configure(bg='white')
over.iconify()
gamefont = font.Font(family='impact', size=30)
levelfont = font.Font(family='impact', size=20)
level = 0
Label(over, text='GAME OVER', font=gamefont)
Label(over, text=f'Level {level}', font=levelfont)
def endgame():
over = Toplevel(root)
over.geometry(f'500x500+{screensize[1]-250}+100')
Label(over, text='GAME OVER', font=gamefont).place(x=250, y=215, anchor='center')
Label(over, text=f'Level {level}', font=levelfont).place(x=250, y=285, anchor='center')
def play(level):
t = 15
gamewords = []
for x in words.words():
if len(x) == level+3:
gamewords.append(x)
word = gamewords[random.randint(0, len(gamewords))]
gameplay = generate(list(word))
Label(root, text=f'Level {level}', font=levelfont, bg='white').place(x=250, y=70, anchor='center')
Label(root, text=gameplay, font=gamefont, bg='white', width=100).place(x=250, y=140, anchor='center')
guess = Entry(root, font=levelfont, bg='white')
guess.place(x=250, y=360, anchor='center')
guess.bind('<Return>', lambda event, word=word: compare(event, word))
def compare(event, word):
if word.upper() == guess.get().upper():
play(level+1)
else:
pass
submit = Button(root, text='SUBMIT', font=levelfont, bg='white', width=21, command=lambda: compare(None, word))
submit.place(x=250, y=420, anchor='center')
timer = StringVar()
Label(root, textvariable=timer, font=levelfont, bg='white', width=8).place(x=250, y=250, anchor='center')
def countdown(t, lev):
print(lev, level)
print(t)
t=int(t)-1
if t < 10:
t=f'0{t}'
timer.set(f'00:{t}')
root.update()
if int(t) < 1 and lev == level:
endgame()
else:
root.after(1000, lambda: countdown(t, lev))
countdown(t, 1)
play(1)
I created a timer but for some reason the timer randomly stops updating until I click the tkinter window then it starts to update again. This happens about every minute or two. Here is my code:
from tkinter import *
from threading import Thread
tk = Tk()
tk.attributes('-alpha',1)
tk ['bg']='#302F2F'
tk.title('')
tk.wm_attributes('-topmost', 1) # put the window to front
def timer():
while True:
sleep(0.009)
...
#cut out all the stuff of creating the time but here is how i did it
label['text'] = (ftime2)
label['fg'] = colorfortext
label2['text'] = (ftime)
label2['fg'] = colorfortext
label3['text'] = (numberofworlds)
label3['fg'] = 'blue'
label = Label(tk, '', font=('Arial', 30),bg='#302F2F')
label.grid(columnspan=2)
label2 = Label(tk, '', font=('Arial', 30),bg='#302F2F')
label2.grid(columnspan=2)
label3 = Label(tk, '', font=('Arial', 30),bg='#302F2F')
label3.grid(columnspan=2)
timer_thread = Thread(target=timer)
timer_thread.start()
tk.mainloop()
I made this program in Tkinter in python where a small window pops up when the code is run and a start button would pop up and make the window full screen and show the content after. I want to make the button destroy itself after I press it so it makes a fullscreen and removes the button. I am still a beginner and would like the answer to be simple. The solution I am looking for is to maybe destroy the button completely(preferred) or move it way out of sight in the fullscreen window. Here is the code:
import Tkinter as w
from Tkinter import *
w = Tk()
w.geometry("150x50+680+350")
def w1():
w.attributes("-fullscreen", True)
l1 = Label(w, text = "Loaded!", height = 6, width = 8).pack()
global b1
b1.place(x = -10000, y = -10000)
b1 = Button(w, text = "Start", height = 3, width = 20, command = w1).place(x = 0, y = 10)
b2 = Button(w, text = "Exit", command = w.destroy).place(x = 1506, y = 0)
w.mainloop()
As you can see I want to make button one destroy itself.
Try this:
import tkinter as tk # Use `import Tkinter as tk` for Python 2
root = tk.Tk()
root.geometry("150x50+680+350")
def function():
global button_start
root.attributes("-fullscreen", True)
label = tk.Label(root, text="Loaded!", height=6, width=8)
label.pack()
button_start.place_forget() # You can also use `button_start.destroy()`
button_start = tk.Button(root, text="Start", height=3, width=20, command=function)
button_start.place(x = 0, y = 10)
button_exit = tk.Button(root, text="Exit", command=root.destroy)
button_exit.place(x=1506, y=0)
root.mainloop()
PS: Please read this.
Try:
b1.place_forget()
This will essentially "forget" about the button and hide it from view.
Edit:
If you are getting the error that b1 is None try:
b1 = Button(w, text = "Start", height = 3, width = 20, command = w1)
b1.place(x = 0, y = 10)
You need to add the b1.place() option at the bottom for this to work
I'm trying to show a sequence of numbers on the screen at regular intervals.
I'm new to python so it may be something obvious but I have tried .after and pygame.time.wait, but neither worked.
this is the code:
from tkinter import*
from random import *
import time
my_list = []
def Create_NUM(event):
x = 0
for x in range(level + 2):
button1.destroy()
num = randint(1, 100)
my_list.append(num)
Label(root, text=num,fg="red").pack()
one.pack()
time.sleep(2)
root=Tk()
num = 0
level = 1
bottomFrame = Frame(root)
bottomFrame.pack(side=BOTTOM)
button1 = Button(bottomFrame, text="Click to start game",fg="red")
button1.bind("<Button-1>", Create_NUM)
button1.pack()
root.mainloop()
I assume you want to show new number in place of old number, not below it.
import tkinter as tk
import random
def start():
# hide button
button.pack_forget()
# run `add_number` first time
add_number(level+2)
def add_number(x):
num = random.randint(1, 100)
my_list.append(num)
label['text'] = num
if x > 0:
# repeat after 2000ms (2s)
root.after(2000, add_number, x-1)
else:
# show button again after the end
button.pack()
# --- main ---
my_list = []
level = 1
root = tk.Tk()
label = tk.Label(root)
label.pack()
button = tk.Button(root, text="Click to start game", command=start)
button.pack()
root.mainloop()
Just use this simple command in your function root.update()