Search code examples
pythontkintertkinter-entry

need assistance with Entry Tkinter in Python 2.5


Is there a way to make an entry in Tkinter react as you type in the field? I'm wanting this feature for the Quantity section of the code.

It auto generates the label4text when clicking the radiobuttons but not when entering the Quantity.

from Tkinter import *

SubnetM = 0

def beenclicked():
    radioValue = relStatus.get()
    return

def changeLabel():
    if relStatus.get() == 'HOSTS':
        if custname.get() == 6:
            label4Text.set("255.255.255.248")
            return
    if relStatus.get() == 'NETWORKS':
        if custname.get() == 6:
            label4Text.set("224.0.0.0")
            return

app = Tk()
app.title("SUBNET MASK CALCULATOR")
app.geometry('400x450+200+200')

labelText = StringVar()
labelText.set("WELCOME!")
label1 = Label(app,textvariable=labelText, height=4)
label1.pack()

relStatus = StringVar()
relStatus.set(None)
radioValue = relStatus.get()
radio1 = Radiobutton(app, text="HOSTS", value="HOSTS", variable=relStatus, command=changeLabel)
radio1.pack()
radio1 = Radiobutton(app, text="NETWORKS", value="NETWORKS", variable=relStatus, command=changeLabel)
radio1.pack()

label2Text = StringVar()
label2Text.set("~Quantity~")
label2 = Label(app, textvariable=label2Text, height=4)
label2.pack()

custname = IntVar(None)
Quantity = Entry(app, textvariable=custname,)
Quantity.pack()

label3Text = StringVar()
label3Text.set("Your Subnet Mask is...")
label3 = Label(app, textvariable=label3Text, height=4)
label3.pack()

label4Text = StringVar()
label4Text.set(SubnetM)
label4 = Label(app, textvariable=label4Text, height=4)
label4.pack()

button1 = Button(app, text="GO!", width=20, command=changeLabel)
button1.pack(padx=15, pady=15)

app.mainloop()

Solution

  • You can use trace() for StringVar() to call changeLabel when custname was changed.

    custname.trace("w", changeLabel)
    

    I change custname from IntVar to StringVar because Entry had problem with converting value to int when it was empty (without number)

    I add *args to changeLabel() because trace send some arguments to function.

    Full code:

    from Tkinter import *
    
    SubnetM = 0
    
    def beenclicked():
        radioValue = relStatus.get()
        return
    
    def changeLabel(*args): # require *args for trace
        print "changeLabel", args
        if relStatus.get() == 'HOSTS':
            if custname.get() == "6":
                label4Text.set("255.255.255.248")
                return
        if relStatus.get() == 'NETWORKS':
            if custname.get() == "6":
                label4Text.set("224.0.0.0")
                return
    
    app = Tk()
    app.title("SUBNET MASK CALCULATOR")
    app.geometry('400x450+200+200')
    
    labelText = StringVar()
    labelText.set("WELCOME!")
    label1 = Label(app,textvariable=labelText, height=4)
    label1.pack()
    
    relStatus = StringVar()
    relStatus.set(None)
    radioValue = relStatus.get()
    radio1 = Radiobutton(app, text="HOSTS", value="HOSTS", variable=relStatus, command=changeLabel)
    radio1.pack()
    radio1 = Radiobutton(app, text="NETWORKS", value="NETWORKS", variable=relStatus, command=changeLabel)
    radio1.pack()
    
    label2Text = StringVar()
    label2Text.set("~Quantity~")
    label2 = Label(app, textvariable=label2Text, height=4)
    label2.pack()
    
    custname = StringVar()
    custname.set("0")
    Quantity = Entry(app, textvariable=custname,)
    Quantity.pack()
    custname.trace("w", changeLabel)
    
    
    label3Text = StringVar()
    label3Text.set("Your Subnet Mask is...")
    label3 = Label(app, textvariable=label3Text, height=4)
    label3.pack()
    
    label4Text = StringVar()
    label4Text.set(SubnetM)
    label4 = Label(app, textvariable=label4Text, height=4)
    label4.pack()
    
    button1 = Button(app, text="GO!", width=20, command=changeLabel)
    button1.pack(padx=15, pady=15)
    
    app.mainloop()
    

    Tested only on Python 2.7

    EDIT:

    I added few modifications more:

    def changeLabel(*args): # require *args for trace
        print "changeLabel", args
    
        custname_int = 0 # default value when error
        try:
            custname_int = int( custname.get() )
        except:
            pass # if error do nothing
    
        if 2 < custname_int <= 6:
            if relStatus.get() == 'HOSTS':
                label4Text.set("255.255.255.248")
            else: #if relStatus.get() == 'NETWORKS':
                label4Text.set("224.0.0.0")
        else:
            label4Text.set("-")
    

    EDIT:

    This way you can write (almost) only digits in Quantity. It will "eat" last char if it is not digit but it can't remove incorrect char betwin digits.

    def changeLabel(*args): # require *args for trace
        #print "changeLabel", args
    
        custname_str = custname.get() 
        custname_int = 0 # default value when error
    
        try:
            custname_int = int( custname_str )
        except:
            if custname_str != "": # if not empty
                custname.set(custname_str[:-1]) # remove last char
                return 
    
        if 2 < custname_int <= 6:
            if relStatus.get() == 'HOSTS':
                label4Text.set("255.255.255.248")
            else: #if relStatus.get() == 'NETWORKS':
                label4Text.set("224.0.0.0")
        else:
            label4Text.set("-")