Now I am going to design a little GUI game like find a pair. And I want to add the sound effect when I click every buttons on it. But I don't know how to add these sound. As the previous answer
How can I play a sound when a tkinter button is pushed?
said, I need to defined the button as this way:
Button(root, text="Play music", command=play_music).pack()
The button has another feature.
Button(game_window,image=blank_image,command=cell_0).grid(row=1,column=1)
So how 'command=play_music' should be placed?
I think you want to alter your functions with a common functionality. For this decorators are really good. A decorator allows you to add functionality to existing functions. An exampel can be found below:
import tkinter as tk
import winsound as snd
def sound_decorator(function):
def wrapped_function(*args,**kwargs):
print('I am here')
snd.PlaySound('Sound.wav', snd.SND_FILENAME)
return function(*args,**kwargs)
return wrapped_function
#sound_decorator
def cmd():
print('command')
root = tk.Tk()
button = tk.Button(root, text = 'Play', command = cmd)
button.pack()
root.mainloop()
make a change like this:
Button(game_window,image=blank_image,command=lambda:[cell_0(),play()]).grid(row=1,column=1)
Then it works.
Related
I'm giving myself a crash-course in Python and TKinter, but there is one small detail I can't grasp.
Closing a Toplevel window in a function instead of a button.
My button alone works perfect:
button = Button(UpdateWindow, text="Destroy Window", command=UpdateWindow.destroy)
Using a button with a reference to a close function bombs:
def Close():
tkMessageBox.showwarning('', 'Close function called', icon="warning")
command=UpdateWindow.destroy
btn_updatecon = Button(ContactForm, text="Update", width=20, command=lambda:[UpdateData(), Close()])
What am I missing in the function? It is being called, but no close.
The SQLite3 project im working with is here
Any guidance greatly appreciated.
command=UpdateWindow.destroy defines a variable. If you want to keep the command variable use command(), while if you want the recommended way use UpdateWindow.destroy()
Let's say if we write something like this:
import threading
Button(root, command=threading.Thread(target=func1).start)
Now if we click the button once then it will be fine but we try to click the button again then a error comes "Thread can only be executed once".
So, how to avoid this
Edited Answer::
As you clarified it in comments, you can redefine the Button every time it is clicked allowing it to accept multiple clicks and thus creating multiple threads as required.
You could do that inside the target func1() or callback function for threading.Thread object.
A working example example would be like this:
import tkinter as tk
import threading
def func1():
theButton.configure(command=threading.Thread(target=func1).start)
print('Do everything else here')
root = tk.Tk()
theButton = tk.Button(root, text='Start', command=threading.Thread(target=func1).start)
theButton.pack()
root.mainloop()
Edit: Thanks to CoolCloud for suggesting a better way to configure the Button inside callback func1().
It is because you create one instance of threading.Thread() and pass its start method to command option of the button. You should create new instance whenever the button is clicked by using lambda:
import tkinter as tk
import threading
root = tk.Tk()
def func1():
print('Hello')
tk.Button(root, text='Go', command=lambda: threading.Thread(target=func1).start()).pack()
root.mainloop()
I did some research in Tkinter and found the root.bind('<Control-Key-whatever key', function).
I wanted to add this to an application I was making.
I made a button and I want it to perform a function when I click a certain key combination.
Here is my code:
from tkinter import *
root = Tk()
root.geometry("600x600")
def printFunction():
print("Hello World")
root.bind('<Control-Key-v>', printFunction)
button = Button(root, text="click here", command=printFunction)
button.pack()
root.mainloop()
So when I click the button the function should perform, and when I click Ctrl+v the function should perform. The button works fine, but the key combination does not work. How do I fix this?
It should be something like
root.bind('<Control-v>', printFunction)
But keep in mind, this will again throw another error, because you have to pass event as a parameter to the function.
def printFunction(event=None):
print("Hello World")
Why event=None? This is because your button is also using the same function as a command but without any arguments passed to it on declaration. So to nullify it, this is a workaround.
Alternatively, your could also pass something like *args instead of event:
def printFunction(*args):
print("Hello World")
Hope you understood better.
Cheers
You can use
from tkinter import *
root = Tk()
root.geometry("600x600")
def printFunction(event):
print("Hello World")
button = Button(root, text="click here", command=lambda:printFunction(None))
root.bind('<Control-v>', printFunction)
button.pack()
root.mainloop()
Argument event is needed for the concerned function
Event name should be converted to <Control-v>
Don't forget to add lambda just before the function name call from
the button in order to call without issue by any means.
I am trying to build a program that listens for certain key combinations and then shows information to the user in a Tkinter window. To do this, I'm using a keylogger like so (simplified for this example):
from pyHook import HookManager
from pythoncom import PumpMessages
import Tkinter as tk
def on_keyboard_event(event):
label.config(text=event.Key)
root.update()
return True
hm = HookManager()
hm.KeyDown = on_keyboard_event
hm.HookKeyboard()
root = tk.Tk()
label = tk.Label(root, text='Hello world')
label.pack()
PumpMessages()
As expected, the window pops up and shows the user what key they pressed. However, I would like to integrate functionality to show other messages by interacting with the Tkinter window, such as by pressing a button. However, it seems I need Tkinter's mainloop to do this, which I can't figure out how to run alongside PumpMessages(), since it also halts the code similar to mainloop().
I tried running root.mainloop() in a root.after(), and I tried recreating root.mainloop like so:
def mainloop():
root.update()
root.after(50, mainloop)
and then running it right before PumpMessages, but neither of these solutions worked. It also doesn't seem like you can run PumpMessages or root.mainloop in a thread, though I could just not be doing it right. If this is not possible with Tkinter, is there an alternate Python GUI I could use that would make it possible?
You don't need to create a function to use mainloop() so just simply place the mainloop() at the bottom of your code. If you want a delay on it, use root.after(milliseconds, function)
Also, remember to put mainloop() before PumpMessages()
e.g.
def mainloopfunction():
mainloop()
root.after(5000, mainloopfunction)
Hope I could help!
Hi guys im trying to make a subprogram that waits for a button to be pressed in order to continue, in othe words: a loop that has a condidtinal, beeing the conditianal having a button pressed, and I have no idea of what can i use to do that.
Here is an easy example of what others have said, this function waits until you hit the button, when it will run the function written:
import tkinter as tk
root = tk.Tk()
root.title('waiting for button click...')
def carry_on:
# do what ever
button = tk.Button(text = 'click to continue', command = carry_on)
button.pack()
root.mainloop()
if you have a more specific question please add more information :)