Python Forum

Full Version: Problem with setting variable within a Entry validatecommand
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Hello all,
I am trying to set a variable called orig_mb in a validatecommand of an Entry widget.
The validation routine get_records sets orig_mb to "hello" when a value is entered into the field_id Entry.
Then I want the orig_mb value to be accessible from the update_record routine.
But when I click on the Update Reoord button to call the update_record routine, the orig_mb is blank.
I cannot make orig_mb a global variable since I will be calling the edit_record recursively and each instance of orig_mb may have a different value.
Any help would be appreciated.
Below is example code that demonstrates the problem.
Thanks in advance.
from tkinter import *
from tkinter import ttk

def get_record(orig_mb):
    orig_mb = "hello"
    print("orig_mb is now hello")

def update_record(orig_mb):
    print("orig_mb is "+orig_mb)

def edit_record():
    new_window = Toplevel(mw)
    new_window.wm_title("Modify Record")
    new_window.geometry('700x400+400+200')

    new_frame1 = Frame(new_window)
    new_frame2 = Frame(new_window)
    new_frame3 = Frame(new_window)
    new_frame1.pack(side=TOP,fill=X)
    new_frame2.pack(side=TOP,fill=X)
    new_frame3.pack(side=TOP,fill=X)

    orig_mb = ""

    label1 = Label(new_frame1, text="Record 1",font=("Times",16))
    label1.grid(row=0,column=0)
    field_id_var = StringVar()
    field_id = Entry(new_frame1,width=40,font=("Times",16),textvariable = field_id_var,validate="focusout",validatecommand=lambda: get_record(orig_mb))
    field_id.grid(row=0,column=1)

    label2 = Label(new_frame2, text="Record 2",font=("Times",16))
    label2.grid(row=0,column=0)
    field_id2 = Entry(new_frame2,width=40,font=("Times",16))
    field_id2.grid(row=0,column=1)

    save_button = Button(new_frame3,text='Update Record',font=("Times",16),command=lambda: update_record(orig_mb)).pack(side="left")


current_file = __file__
mw = Tk()
# 999x999 is size of window, 999+999 is the location of the window
mw.geometry('600x200+400+200')
mw.title("test program")

framebot = Frame(mw)
framebot.pack(side=BOTTOM,fill=X)

btn3 = Button(framebot,text='Go',font=("Times",16),command=edit_record).pack(side="left")
mw.mainloop()
Do you really mean recursively? Maybe that doesn't matter. If you can have multiple entry fields you will need to have multiple values. If you don't know how many Entry's there will be ahead of time you'll need a container that can grow. The example below keeps the entry values in a list. Each time an entry is added a corresponding string is added to the field list.

To grow the idea to forms, you would maintain a list of lists, or maybe a list of classes.
from functools import partial
from tkinter import *
from tkinter import ttk

fields = []

def record(entry, index):
    fields[index] = entry.get()
    print(fields)

def add_record():
    index = len(fields)
    fields.append('')

    w = Toplevel(mw)
    w.wm_title("Record")
    w.geometry('200x50')
    frame = Frame(w)
    frame.pack(side=TOP,fill=X)
    label = Label(frame, text="Record")
    label.grid(row=0,column=0)
    idvar = StringVar()
    id = Entry(frame, validate="focusout", textvariable= idvar)
    id.grid(row=0,column=1)
    save_button = Button(frame, text='Update Record', command=partial(record, idvar, index))
    save_button.grid(row=1,column=1)
 
 
current_file = __file__
mw = Tk()
mw.geometry('200x200')
mw.title("test program")
 
framebot = Frame(mw)
framebot.pack(side=BOTTOM,fill=X)
 
btn3 = Button(framebot,text='Go',font=("Times",16),command=add_record).pack(side="left")
mw.mainloop()