I am using Tkinter and Python3.
In my application there are multiple buttons, that are calling their own functions.
Now I would like to add a function, that gets called by clicking on any button, without unbinding the functions specific to the button itself.
What I am trying to do is:
Multiple buttons have their own function:
**Button1** calls **function A**
**Button2** calls **function B**
**Button3** calls **function C**
Whenever ANY button is called, ONLY Function D is called, a timer of 10 minutes is set, and when any button is called now, it calls his own function.
The simplest way is to have all three buttons call the one function, with all the state and logic contained within that one function. Each time any button is pressed the state determines whether that press event calls function D or the appropriate function for the button pressed (A, B or C).
If you cannot arrange that then just make functions A, B and C do nothing but call function D, which arranges to execute the D code or A, B or C code depending on the state.
Related
I am trying to bind two functions to a button, so for example I want to toggle a buzzer and LED with a single button. Is there a way to attach two functions to the same button or can a button only do a single thing at once?
For example:
button.when_pressed = led.toggle && buzzer.toggle
Bind to a function that calls both functions:
def toggle_led_and_buzzer():
led.toggle()
buzzer.toggle()
button.when_pressed = toggle_led_and_buzzer
You can use 2 solutions. Just merge the two functions into a single function, then call up that single function with the button, or alternatively using a lambda
SOLUTION N.1
def ledtoggle_buzzertoggle():
led.toggle()
buzzer.toggle()
button.when_pressed = ledtoggle_buzzertoggle
SOLUTION N.2
You can also use lambda
button.when_pressed = lambda:[led.toggle(), buzzer.toggle()] #or without square brackets
I the following code I want to bind all frame1 items to <'Enter'> Event, but it does not work. I mean canvas.focus_set() does not take effect. How can I solve my problem?
for w in frame1.winfo_children():
w.bind('<Enter>',canvas1.focus_set())
The comment made by Lafexlos actually sends you in the right direction. When you do
w.bind('<Enter>', canvas1.focus_set())
you call canvas1.focus_set() and use the return value of this function call (which is None) to bind to the event. This isn't what you want, because now every time the event is triggered, None is executed instead of canvas1.focus_set().
What you should do is pass a function reference to the bind function. The reference for calling canvas1.focus_set() is canvas1.focus_set. However, using
w.bind('<Enter>', canvas1.focus_set)
still doesn't work.
This is because the bind function passes an event object to the function it has been given, so it will call canvas1.focus_set(event) instead of canvas1.focus_set(). Because focus_set does not accept any arguments, this fails.
You can fix this in two ways. You could make an extra function, which does accept an event object and then calls canvas1.focus_set() without arguments, and then bind the event to this new function. The other option is to use an anonymous "lambda" function to basically do the same like
w.bind('<Enter>', lambda e: canvas1.focus_set())
This way the lambda function accepts the event object as e, but doesn't pass it to focus_set.
P.S. The <Enter> event is not the event that is triggered when you press the Enter button on your keyboard (that is <Return>). The <Enter> event is triggered whenever you move the mouse onto a widget and is accompanied by the <Leave> event for when you leave the widget with your mouse. This might be what you want, but it often leads to confusion.
by using canvas1.bind_all which is the parent of frame1 I solved my problem. Thanks for all solutions.
If there is any mistake I see you making it is likely you are not calling the write command for the Enter key. Hopefully, if you are attempting to do this on windows, you should rather use Return.
More like:
for w in frame1.winfo_children():
w.bind('<Return>',canvas1.focus_set())
I have the following problem:
i have a GUI with two Buttons: "Run" and "Stop".
When I press Button "Run", function a will be executed.
How can I stop the execution by pressing Button "Stop", without any if statements? In function a, there are a ton of mathematical calculations so if I would just border the code inside the function a with a loop and check once per loop-pass if the Button "Stop" was pressed, it would take too much time.
I want to stop the execution of the function a right now, not when the whole calculations are finished. So for example to border the code inside the function with try/catch but raising the exception outside of the function, then I could stop the execution of the function everytime I want, not until the if-statement would be reached. I allready tried to solve the Problem with a thread but it doesn't work because I don't know, how to start a thread with commit some parameters to the Custom thread-class.
Here a small Pythoncode that should show what I mean:
class GUI():
def __init__(self):
#Initialization of Button "Run",connect Button "Run" to function a
#Initialization of Button "Stop",connect Button "Stop" to function b
def a(self):
"""calculation of a ton of mathematical stuff, can take MORE THAN
FIVE MINUTES to be finished, could be grouped in
individual functions to border the function-calls with try/catch,
but would be inefficient and inelegant"""
pass
def b(self):
"""Should stop the execution of function a immediately """
I am creating on_press callbacks for button behavior objects inside a loop and for some reason all of the parameters for the partial stay the same as the parameters for the last partial created.
shortened example of creation:
(button is a class that implements button behaviour)
for button in list:
button.on_press=partial(my_func, button, button.arg1, button.arg2)
the problem is that the arguments arg1 and arg2 stay the same as the last iteration of the loop instead of being updated. so when I press the buttons (doesn't matter which one) the callback is called as if I pressed the last button.
why does this happen / how can I fix this?
I am writing a program using tkinter, but I do not understand how it works. Normally, code is executed top-down, but with tkinter it obviously does not.
For example, I have bound a function to the left mouse button, and this function is executed every time I click the button. But how is the other code around that treated? My problem is that I in the start of my program initialize a variable that is used as an argument in the bound function, and then it is changed in the function and returned. But every time the function is called, the variable seems to be reset to its initial value.
Does anyone know why this is?
I have it written like this:
var = "black"
var = c.bind("<Button-1>", lambda event: func(event, arg=var))
The function "func" changes var and returns it, but the next time I press the button the variable is always "black".
Thanks in advance!
Tkinter does indeed run top down. What makes tkinter different is what happens when it gets to the bottom.
Typically, the last executable statement in a tkinter program is a call to the mainloop method of the root window. Roughtly speaking, tkinter programs look like this:
# top of the program logic
root = tkinter.Tk()
...
def some_function(): ...
...
some_widget.bind("<1>", some_function)
...
# bottom of the program logic
root.mainloop()
mainloop is just a relatively simple infinite loop. You can think of it as having the following structure:
while the_window_has_not_been_destroyed():
event = wait_for_next_event()
process_event(event)
The program is in a constant state of waiting. It waits for an event such as a button click or key click, and then processes that event. Conceptually, it processes the event by scanning a table to find if that event has been associated with the widget that caught the event. If it finds a match, it runs the command that is bound to that widget+event combination.
When you set up a binding or associate a command with a button, you are adding something to that table. You are telling tkinter "if event X happens on widget Y, run function Z".
You can't use a return result because it's not your code that is calling this function. The code that calls the function is mainloop, and it doesn't care what the function returns. Anything that gets returned is simply ignored.