Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Tkinter binding a function with arguments to a widget

Tags:

python

tkinter

I have a tkinter frame and a button attached to it:

from tkinter import *

def rand_func(a,b,c,effects):
    print (a+b+c)

root=Tk()
frame=Frame(root)
frame.bind("<Return>",lambda a=10, b=20, c=30: rand_func(a,b,c))
frame.pack()

button=Button(frame, text="click me", command=lambda a=1,b=2,c=3,eff=None:rand_func(a,b,c))
button.pack()

root.mainloop()

I want the same function to be done when user presses enter and when he presses the button. Sadly, the code above gives an error at the frame binding. Does anyone know a solution to this problem?

like image 618
Serban Razvan Avatar asked Sep 04 '11 14:09

Serban Razvan


People also ask

How do you bind an event with a widget?

We can bind an event to widgets using the bind('key', callback function) method. Key represents the event through which we target a particular event, whereas callable function activates the event. To create a callback function, we switch to a specific widget as the argument and then add the particular event.

How do you pass an argument to an event handler in tkinter?

The first >argument is the Event object passed to all event handlers, and the second and third >arguments will be set to their default values—the extra arguments we need to pass it. This technique can be extended to supply any number of additional arguments to >handlers.

What does bind () do in tkinter?

In Tkinter, bind is defined as a Tkinter function for binding events which may occur by initiating the code written in the program and to handle such events occurring in the program are handled by the binding function where Python provides a binding function known as bind() where it can bind any Python methods and ...

How do I bind the Enter key to a function in tkinter?

To bind the <Enter> key with an event in Tkinter window, we can use bind('<Return>', callback) by specifying the key and the callback function as the arguments. Once we bind the key to an event, we can get full control over the events.


2 Answers

When you create a binding with bind, Tkinter automatically adds an argument that has information about the event. You'll need to account for that either in your rand_func definition or in how you call it.

This argument is not included when you use the command attribute. You must take care to account for this extra argument either in how you call the function in each case, or in how the function interprets its parameters.

Here's one solution that uses lambda in the binding to accept the extra event only when using bind command, but not pass it on to the final command.

import tkinter as tk

class SampleApp(tk.Tk):
    def __init__(self, *args, **kwargs):
        tk.Tk.__init__(self, *args, **kwargs)
        self.frame = tk.Frame(self)
        self.frame.pack()
        self.button = tk.Button(self.frame, text="click me",
                             command=lambda a=1, b=2, c=3: 
                                self.rand_func(a, b, c))
        self.button.pack()
        self.frame.bind("<Return>", 
                        lambda event, a=10, b=20, c=30: 
                            self.rand_func(a, b, c))
        # make sure the frame has focus so the binding will work
        self.frame.focus_set()

    def rand_func(self, a, b, c):
        print "self:", self, "a:", a, "b:", b, "c:", c
        print (a+b+c)

app = SampleApp()
app.mainloop()

That being said, it's rare that binding to a frame is the right thing to do. Typically a frame won't have keyboard focus, and unless it has focus the binding will never fire. If you are setting a global binding you should either bind to the "all" binding tag (using the bind_all method) or to the toplevel widget.

like image 158
Bryan Oakley Avatar answered Oct 17 '22 12:10

Bryan Oakley


How about:

import tkinter as tk


def rand_func(eff=None, a=1, b=2, c=3):
    print(a + b + c)

root = tk.Tk()
root.bind("<Return>", lambda eff: rand_func(eff, a=10, b=20, c=30))

frame = tk.Frame(root)
frame.pack()

button = tk.Button(frame, text="click me",
                   command=lambda: rand_func(None, 1, 2, 3))
button.pack()

root.mainloop()
like image 29
unutbu Avatar answered Oct 17 '22 11:10

unutbu