Ash
Ash

Reputation: 271

Tk: How to remove tk entry if the user inputs anything than strings?

I want to use the most efficient way to limit the user not to enter anything than digits. For example: when they input a letter in an entry, that exact entry gets cleared. Is there any way to do it with the least changes in the structure?

Here is my code:[the ????? sign is where I'm stuck]

import tkinter as tk
from tkinter import ttk

class App:
    """Main class for a simple application"""

def __init__(self, master):
    """Main initialisation for the main app"""
    # create a top frame or window which we can add things to it
    self.topFrame = tk.Frame(master)
    self.topFrame.pack()
    # create a holder (notebook) for tabs
    self.note = ttk.Notebook(self.topFrame)
    # create four different tabs for the main screen
    self.tab1 = ttk.Frame(self.note)
    self.tab2 = ttk.Frame(self.note)
    self.tab3 = ttk.Frame(self.note)
    self.tab4 = ttk.Frame(self.note)
    # add four different tabs for the main screen with various names
    self.note.add(self.tab1, text='   Demography   ')
    self.note.add(self.tab2, text='   Urban Economy   ')
    self.note.add(self.tab3, text='   Land Use   ')
    self.note.add(self.tab4, text='   Urban Transportation   ')
    self.note.pack()
    # add a frame to each tab
    self.demog_frame = tk.Frame(self.tab1)
    self.demog_frame.pack()
    self.eco_frame = tk.Frame(self.tab2)
    self.eco_frame.pack()        
    self.land_frame = tk.Frame(self.tab3)
    self.land_frame.pack()
    self.trans_frame = tk.Frame(self.tab4)
    self.trans_frame.pack()        
    # add label frames to {DEMOGRAPHY TAB}
    self.demog_flable_1 = tk.LabelFrame(self.demog_frame, text='Population Growth:')
    self.demog_flable_1.grid(row=0, column=0, ipadx=0, ipady=10, padx=0)


    # add info to the first LabelFrame
    self.d_p_grwt_label_fy = tk.Label(self.demog_flable_1, text='population of year n |', pady=0, font='Arial 8')
    self.d_p_grwt_label_fy.grid(row=0, column=0)
    self.d_p_grwt_label_sy = tk.Label(self.demog_flable_1, text='population of year n+1 |', font='Arial 8')
    self.d_p_grwt_label_sy.grid(row=0, column=1)
    self.d_p_grwt_label_fyy = tk.Label(self.demog_flable_1, text='year n eg:1999 |', font='Arial 8')
    self.d_p_grwt_label_fyy.grid(row=2, column=0)
    self.d_p_grwt_label_syy = tk.Label(self.demog_flable_1, text='year n+1 eg:2006 |', font='Arial 8')
    self.d_p_grwt_label_syy.grid(row=2, column=1)
    self.d_p_grwt_entry_fy = tk.Entry(self.demog_flable_1, width=12)
    self.d_p_grwt_entry_fy.bind("<KeyRelease>", func=self.popfunc_1)
    self.d_p_grwt_entry_fy.grid(row=1, column=0)
    self.d_p_grwt_entry_sy = tk.Entry(self.demog_flable_1, width=12)
    self.d_p_grwt_entry_sy.grid(row=1, column=1)
    self.d_p_grwt_entry_fyy = tk.Entry(self.demog_flable_1, width=12)
    self.d_p_grwt_entry_fyy.grid(row=3, column=0)
    self.d_p_grwt_entry_syy = tk.Entry(self.demog_flable_1, width=12)
    self.d_p_grwt_entry_syy.grid(row=3, column=1)
    #----------------------------------------------
    self.d_p_grwt_dscrpt_label = tk.Label(self.demog_flable_1, text='population absolute change \u2193', font='Arial 8')
    self.d_p_grwt_dscrpt_label.grid(row =0, column=2)
    self.d_p_grwt_dscrpt_label1 = tk.Label(self.demog_flable_1, text='population annual absolute change \u2193', font='Arial 8')
    self.d_p_grwt_dscrpt_label1.grid(row =2, column=2)
    self.d_p_grwt_dscrpt_label2 = tk.Label(self.demog_flable_1, text='population annual percent change \u2193', font='Arial 8')
    self.d_p_grwt_dscrpt_label2.grid(row =4, column=2)

def popfunc_1(self, *args):
    try:    
        p1 = int(self.d_p_grwt_entry_fy.get())
        p2 = int(self.d_p_grwt_entry_sy.get())
        y1 = int(self.d_p_grwt_entry_fyy.get())
        y2 = int(elf.d_p_grwt_entry_syy.get())

        print(x1)

    except ValueError:
       ???? 





root = tk.Tk()
root.title('Urban Calculator')
root.geometry('420x200')
app = App(root)

root.mainloop()

At the bottom of the class, I tried to except strings by ValueError. If I write a pass it is good but I want the entry to be cleared too. Is there any way to point to p1 or p2 and say whichever causes the error to be cleared?

Upvotes: 1

Views: 57

Answers (1)

Mike - SMT
Mike - SMT

Reputation: 15226

Is there any way to point to p1 or p2 and say whichever causes the error to be cleared?

Yes but not all at once. You would have to run you try/except on each entry individually.

For example you could load your entry fields into a list and then use a loop to bind each entry to your method and then use the event that is passed to interact with the widget.

See below example and let me know if you have any questions.

import tkinter as tk
from tkinter import ttk


class App(tk.Tk):
    def __init__(self):
        super().__init__()
        self.title('Urban Calculator')
        self.geometry('420x200')
        topFrame = tk.Frame(self)
        topFrame.pack()
        note = ttk.Notebook(topFrame)
        tab1 = ttk.Frame(note)
        note.add(tab1, text='   Demography   ')
        note.pack()
        demog_frame = tk.Frame(tab1)
        demog_frame.pack()
        demog_flable_1 = tk.LabelFrame(demog_frame, text='Population Growth:')
        demog_flable_1.grid(row=0, column=0, ipadx=0, ipady=10, padx=0)
        tk.Label(demog_flable_1, text='population of year n |', pady=0, font='Arial 8').grid(row=0, column=0)
        tk.Label(demog_flable_1, text='population of year n+1 |', font='Arial 8').grid(row=0, column=1)
        tk.Label(demog_flable_1, text='year n eg:1999 |', font='Arial 8').grid(row=2, column=0)
        tk.Label(demog_flable_1, text='year n+1 eg:2006 |', font='Arial 8').grid(row=2, column=1)
        entry_list = [tk.Entry(demog_flable_1, width=12),
                           tk.Entry(demog_flable_1, width=12),
                           tk.Entry(demog_flable_1, width=12),
                           tk.Entry(demog_flable_1, width=12)]
        entry_list[0].grid(row=1, column=0)
        entry_list[1].grid(row=1, column=1)
        entry_list[2].grid(row=3, column=0)
        entry_list[3].grid(row=3, column=1)
        for entry in entry_list:
            entry.bind("<KeyRelease>", func=self.popfunc_1)

        tk.Label(demog_flable_1, text='population absolute change \u2193', font='Arial 8').grid(row=0, column=2)
        tk.Label(demog_flable_1, text='population annual absolute change \u2193',
                 font='Arial 8').grid(row=2, column=2)
        tk.Label(demog_flable_1, text='population annual percent change \u2193',
                 font='Arial 8').grid(row=4, column=2)

    def popfunc_1(self, event):
        x = event.widget.get()
        try:
            entry_value = int(x)
            print(entry_value)
        except ValueError:
            print('error')
            event.widget.delete(len(x) - 1, 'end')


if __name__ == '__main__':
    App().mainloop()

Upvotes: 1

Related Questions