How to open a tkinter window when a key is pressed - python

I have this code:
from tkinter import *
import keyboard
#console
if keyboard.is_pressed('c'):
console=Tk()
console.geometry("500x425")
console.title("Devoloper Console")
console.resizable(True,True)
console.configure(bg='gray95')
Basically, I'm trying to use the keyboard module to detect when I press C on my keyboard, and then open a Tkinter window when I press C.
The code above doesn't work (obviously) and I don't know why. However, I do know that the problem is that it isn't detecting the keypress and not a problem with the window.

You need a continuing loop to check when c is pressed.
from tkinter import *
import keyboard
x = True
while x:
if keyboard.is_pressed('c'):
x = False
console=Tk()
console.geometry("500x425")
console.title("Devoloper Console")
console.resizable(True,True)
console.configure(bg='gray95')
console.mainloop()

import tkinter as tk
import keyboard
while (not keyboard.is_pressed("c")):
pass
root = tk.Tk()
root.bind("<c>", lambda e: tk.Toplevel())
root.mainloop()
Does this do what you wanted?

Module keyboard has a function called wait. It waits for a key to be pressed. You have to use that. Also use mainloop for the tkinter window to make it run corectly.
import tkinter as tk
import keyboard
keyboard.wait("c") #< It'll wait for c to be pressed
console = tk.Tk()
console.geometry("500x425")
console.title("Devoloper Console")
console.resizable(True,True)
console.configure(bg='gray95')
...

Related

Tkinter window not responding when push buttton

I have a program that I wrote in tkinter, but if the while true loop starts running, the window stops working(not responding) what should I do?
code:
import pyautogui
import sys
import keyboard
def basla():
while True:
if keyboard.is_pressed("shift"):
pyautogui.press("enter")
pyautogui.typewrite("/pull ")
elif keyboard.is_pressed("E"):
pyautogui.press("enter")
pyautogui.typewrite("/me WHO GAS")
pyautogui.press("enter")
def bitir():
sys.exit()
pencere = Tk()
pencere.title("Keybinder")
pencere.geometry("300x300+10+10");
baslat_buton = Button(pencere)
baslat_buton.config(text="Başlat", bg="black",width=8,height=2, fg="white", command=basla)
baslat_buton.place(x=100,y=100)
bitir_buton = Button(pencere)
bitir_buton.config(text="Bitir", bg="black", fg="white",width=8,height=2, command=bitir)
bitir_buton.place(x=100,y=150)
mainloop()```
"In tkinter don't use while True which runs forever (or runs longer time) because it blocks mainloop() in tkinter and it can't update items in window, and it looks like it freezes."
Check out this topic and see if it makes it clear to you. tkinter root.mainloop with While True loop

issue with tkinter messagebox

I'm using several tkinter messageboxes in my code. But ive noticed a problem with the showinfo messageboxes I've used in my code. Basically, I want a function to be called when the ok on the messagebox is pressed. Also, the user can choose not to proceed by just closing the messagebox. But, it looks like when I press the x icon to close the messagebox, the function is still called. Here is a minimum reproducible code to explain what i mean.
from tkinter import *
from tkinter import messagebox
root = Tk()
def func() :
Label(root,text="This is the text").pack()
msg = messagebox.showinfo("Loaded","Your saved state has been loaded")
if msg == "ok" :
func()
root.mainloop()
My question is, What should i do so that the function is not called when the x icon is pressed?
There are different types of messagebox, the one your using here is not what you actually should be using for your case. What you want is something called askyesno, or something that is prefixed by 'ask' because your code depend upon the users action. So you want to 'ask' the user, like:
from tkinter import *
from tkinter import messagebox
root = Tk()
def func() :
Label(root,text="This is the text").pack(oadx=10,pady=10)
msg = messagebox.askyesno("Loaded","Your saved state has been loaded")
if msg: #same as if msg == True:
func()
root.mainloop()
Here, askyesno like other 'ask' prefixed functions will return True or 1 if you click on the 'Yes' button, else it will return False or 0.
Also just something I realized now, showinfo, like other 'show' prefixed messagebox function, returns 'ok' either you press the button or close the window.
Some more 'ask' prefixed messageboxes ~ askokcancel, askquestion, askretrycancel, askyesnocancel. Take a look here

Key listener script with GUI won't work (Tkinter)

I need to "listen" if the user types the ENTER key while a GUI application runs in background (using Tkinter), if the user type the ENTER key a messagebox should show up, but as soon as I run the script the GUI do not appear, and if I press ENTER a huge list of errors appears in the console, and the GUI shows up (the messagebox won't). I think I'm missing something in the "listening" function:
from pynput.keyboard import Key, Listener
import logging
from tkinter import *
from tkinter import messagebox
window = Tk()
window.title("i'm listening...")
window.geometry("400x400")
def on_press(key):
logging.info(str(key))
if str(key) == "Key.enter":
msg = messagebox.showinfo( "simple message", "you clicked the enter button!")
'''
do
other
stuffs
'''
with Listener(on_press=on_press) as listener:
listener.join()
window.mainloop()
Console:
RuntimeError: main thread is not in main loop
Thanks for your help/tips!

Python Tkinter - destroy window after time or on click

I have following code:
import tkinter as tk
from tkinter import messagebox
try:
w = tk.Tk()
w.after(3000, lambda: w.destroy()) # Destroy the widget after 3 seconds
w.withdraw()
messagebox.showinfo('MONEY', 'MORE MONEY')
if messagebox.OK:
w.destroy()
w.mainloop()
confirmation = 'Messagebox showed'
print(confirmation)
except Exception:
confirmation = 'Messagebox showed'
print(confirmation)
Is there better way to do this, without using threading and catching exception?
You use if messagebox.OK:, but messagebox.OK is defined as OK = "ok". Therefore, your if statement is always true. If you want to check whether the user clicked the button you need to get the return value of the showinfo function.
So you can do:
a = messagebox.showinfo('MONEY', 'MORE MONEY')
if a:
w.destroy()
Or even shorter:
if messagebox.showinfo('MONEY', 'MORE MONEY'):
w.destroy()
This way w.destroy is not run when the user didn't click anything (so when w.destroy has already been run by the after call).
In total:
import tkinter as tk
from tkinter import messagebox
w = tk.Tk()
w.withdraw()
w.after(3000, w.destroy) # Destroy the widget after 3 seconds
if messagebox.showinfo('MONEY', 'MORE MONEY'):
w.destroy()
confirmation = 'Messagebox showed'
print(confirmation)

python button combination to open a tkinter message box

im new topython 2.7 and want to know if it is possible to open a tkinter messagebox with a button combination on keyboard (Ctrl+alt+'something')
that pops up like an windows error message
import win32api
import time
import math
import Tkinter
import tkMessageBox
top = Tkinter.Tk()
def Message():
tkMessageBox.showinfo("Window", "Text")
for i in range(9000):
x = int(600+math.sin(math.pi*i/100)*500)
y = int(500+math.cos(i)*100)
win32api.SetCursorPos((x,y))
time.sleep(.01)
Yes, you can bind to control and alt characters. Bindings are fairly well documented. Here's one good source of information:
http://effbot.org/tkinterbook/tkinter-events-and-bindings.htm
As an example, to bind to ctrl-alt-x you would do this:
top.bind("<Control-Alt-x>", Message)
You can bind to a sequence of events by specifying the whole sequence. For example, if you wanted to implement a cheat code you could do something like this:
label.bind("<c><h><e><a><t>", Message)
For letters, "a" is the same as "<a>", so you can also do this:
label.bind("cheat", Message)
Here is a complete working example:
import Tkinter as tk
import tkMessageBox
def Message(event=None):
tkMessageBox.showinfo("Window", "Text")
def Cheat(event=None):
tkMessageBox.showinfo("Window", "Cheat Enabled!")
root = tk.Tk()
label = tk.Label(root, text="Press control-alt-m to see the messagebox\ntype 'cheat' to enable cheat.")
label.pack(fill="both", expand=True, padx=10, pady=100)
label.bind("<Control-Alt-x>", Message)
label.bind("<c><h><e><a><t>", Cheat)
label.focus_set()
root.mainloop()
If you want something like: Press button A, then press button B then open a Message box it is possible.
Do something like:
from Tkinter import *
import tkMessageBox
def change():
global switch
switch=True
def new_window():
if switch:
tkMessageBox.showinfo("Random name", "Correct combination")
else:
print "Not the correct order"
root = Tk()
switch = False
root.bind("<A>", change)
root.bind("<B>",new_window)
root.mainloop()
If you want more buttons then use an integer and increase it while using switches for the correct button order.
Note that you can bind key combinations as well with root.bind("<Shift-E>") for example
Edit: Now a and b keyboard button insted of tkinter buttons

Categories