How to Get an Event Callback When a Tkinter Entry Widget Is Modified

How do I get an event callback when a Tkinter Entry widget is modified?

Add a Tkinter StringVar to your Entry widget. Bind your callback to the StringVar using the trace method.

from Tkinter import *

def callback(sv):
print sv.get()

root = Tk()
sv = StringVar()
sv.trace("w", lambda name, index, mode, sv=sv: callback(sv))
e = Entry(root, textvariable=sv)
e.pack()
root.mainloop()

Event callback after a Tkinter Entry widget

I think this does what you're looking for. I found relevant information here. The bind method is the key.

from Tkinter import *

def callback(sv):
print sv.get()

root = Tk()

sv = StringVar()
e = Entry(root, textvariable=sv)
e.bind('<Return>', (lambda _: callback(e)))

e.pack()
root.mainloop()

Python tkinter text modified callback

I suggest a simpler approach. You can set up a proxy for the widget, and within that proxy you can detect whenever anything was inserted or deleted. You can use that information to generate a virtual event, which can be bound to like any other event.

Let's start by creating a custom text widget class, which you will use like any other text widget:

import Tkinter as tk

class CustomText(tk.Text):
def __init__(self, *args, **kwargs):
"""A text widget that report on internal widget commands"""
tk.Text.__init__(self, *args, **kwargs)

# create a proxy for the underlying widget
self._orig = self._w + "_orig"
self.tk.call("rename", self._w, self._orig)
self.tk.createcommand(self._w, self._proxy)

def _proxy(self, command, *args):
cmd = (self._orig, command) + args
result = self.tk.call(cmd)

if command in ("insert", "delete", "replace"):
self.event_generate("<<TextModified>>")

return result

The proxy in this example does three things:

  1. First it calls the actual widget command, passing in all of the arguments it received.
  2. Next it generates an event for every insert and every delete
  3. Then it then generates a virtual event
  4. And finally it returns the results of the actual widget command

You can use this widget exactly like any other Text widget, with the added benefit that you can bind to <<TextModified>>.

For example, if you wanted to display the number of characters in the text widget you could do something like this:

root = tk.Tk()
label = tk.Label(root, anchor="w")
text = CustomText(root, width=40, height=4)

label.pack(side="bottom", fill="x")
text.pack(side="top", fill="both", expand=True)

def onModification(event):
chars = len(event.widget.get("1.0", "end-1c"))
label.configure(text="%s chars" % chars)

text.bind("<<TextModified>>", onModification)

root.mainloop()

Getting a callback when a Tkinter Listbox selection is changed?

You can bind to the <<ListboxSelect>> event. This event will be generated whenever the selection changes, whether it changes from a button click, via the keyboard, or any other method.

Here's a simple example which updates a label whenever you select something from the listbox:

import tkinter as tk

root = tk.Tk()
label = tk.Label(root)
listbox = tk.Listbox(root)
label.pack(side="bottom", fill="x")
listbox.pack(side="top", fill="both", expand=True)

listbox.insert("end", "one", "two", "three", "four", "five")

def callback(event):
selection = event.widget.curselection()
if selection:
index = selection[0]
data = event.widget.get(index)
label.configure(text=data)
else:
label.configure(text="")

listbox.bind("<<ListboxSelect>>", callback)

root.mainloop()

screenshot

This event is mentioned in the canonical man page for listbox. All predefined virtual events can be found on the bind man page.

Tkinter - Trigger an event when two Entry Widgets are written into,regardless of order

If I'm understanding what you need correctly then it sounds to me like you'd be best off using the .trace() function.

This allows you to raise a callback whenever a variable is written to or read.

In this case we'd create two variables var1 and var2 (for simplicity's sake) and assign these the value of StringVar().

We'd then set the attribute textvariable of each Entry widgets to be var1 and var2 respectively.

We then need to set up the .trace() itself, so we call var1.trace("w", callback) and var2.trace("w", callback) (where the "w" means write) which runs the callback function every time either variable is written to.

This means that no matter which Entry is modified first, we get a callback and more importantly we get a callback for every modification.

See below for a working example:

from tkinter import *

class App:
def __init__(self, root):
self.root = root
self.var1 = StringVar()
self.var2 = StringVar()
self.var1.trace("w", self.callback)
self.var2.trace("w", self.callback)
self.entry1 = Entry(self.root, text="Ok", textvariable=self.var1)
self.entry2 = Entry(self.root, text="Ok", textvariable=self.var2)
self.label = Label(self.root)
self.entry1.pack()
self.entry2.pack()
self.label.pack()
def callback(self, *args):
self.label.configure(text=self.entry1.get()+self.entry2.get())

root = Tk()
App(root)
root.mainloop()

How to call event in entry when button or enter is pressed

You bind the event to the widget in question.
In the example below, '<Return>' is the key in question, and return_pressed is the name of the function or method it triggers when the key is pressed.

See this for some more details.

sidenote: you might also want to read up on bind_all

        self.antwort.bind('<Return>', return_pressed)

Python Tkinter update when entry is changed

What you are looking for is variable trace() method. E.g.:

def callback(*args):
print "variable changed!"

var = DoubleVar()
var.trace("w", callback)

Attach trace callbacks for each of your DoubleVar, for temp_f_number one to update the temp_c_number value and vice versa. You'll likely also need to disable one callback function while inside another one, to avoid recursive update cycle.

Another note - do not edit the Entry fields. Instead, use variables' set() method. Entry fields will be updated automatically.

So, complete code could look like this:

import Tkinter as tk

root = tk.Tk()
temp_f_number = tk.DoubleVar()
temp_c_number = tk.DoubleVar()

tk.Label(root, text="F").grid(row=0, column=0)
tk.Label(root, text="C").grid(row=0, column=1)

temp_f = tk.Entry(root, textvariable=temp_f_number)
temp_c = tk.Entry(root, textvariable=temp_c_number)

temp_f.grid(row=1, column=0)
temp_c.grid(row=1, column=1)

update_in_progress = False

def update_c(*args):
global update_in_progress
if update_in_progress: return
try:
temp_f_float = temp_f_number.get()
except ValueError:
return
new_temp_c = round((temp_f_float - 32) * 5 / 9, 2)
update_in_progress = True
temp_c_number.set(new_temp_c)
update_in_progress = False

def update_f(*args):
global update_in_progress
if update_in_progress: return
try:
temp_c_float = temp_c_number.get()
except ValueError:
return
new_temp_f = round(temp_c_float * 9 / 5 + 32, 2)
update_in_progress = True
temp_f_number.set(new_temp_f)
update_in_progress = False

temp_f_number.trace("w", update_c)
temp_c_number.trace("w", update_f)

root.mainloop()


Related Topics



Leave a reply



Submit