Meriole
Meriole

Reputation: 115

Python tkinter - Change the Label created by a loop, how can I do?

I read a lot for it and I have the sentiment that there is no solution for me.

Context: user has to enter 6-digit calculation number in the entries. The 9x entries are created by a loop. I wrote the condition to detect if the user did a mistake : number which contains less or more than 6 digit or / and contains a letter. They are working, I tested them. Only 6-digit number are accepted (if 0, it's ok since it means that the user just need to get less than 9x documents).

Goal: if the user did one mistake, a message "Error in the number" at the place of the "0" has to appear right next to the concerned and "faulty" entry.

Everything will be activated through a button.

What I tried: with a list, but it doesn't work.

How can I change the Label dynamically created by the loop ?

    user_entries=[]
    error_list_length=[0,0,0,0,0,0,0,0,0]
    error_list_letters=[0,0,0,0,0,0,0,0,0]
    error_calculation_list=[0,0,0,0,0,0,0,0,0]
    nbofcalc=9
    a=0
    b=1
    ddd=791250

#------ Function to check if the entered calculation number are composed of 6 characters (mandatory)    
    def check_calc_number():
        global gg_error
        gg=0
        gg_error=0
        while gg<nbofcalc:
            if len(user_entries[gg].get()) != 6:
                if len(user_entries[gg].get()) ==0:
                    gg_error+=0
                    error_list_length[gg]=0
                else:
                    gg_error+=1
                    error_list_length[gg]=1
            else:
                gg_error+=0
                error_list_length[gg]=0
               
            gg+=1

#------ Function to check if the entered calculation number contains a or many letters (prohibited)
    def check_calc_letter():
        global hh_error
        hh=0
        hh_error=0
        alphabet_x='a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'
        for x in range(nbofcalc):
            for n in user_entries[hh].get():
                if n in alphabet_x:
                    hh_error+=1
                    error_list_letters[hh]=1
                    
            hh+=1

#------ Function to check with entries has an error and update the list "error_calculation_list" to try to displays the message "Error in the number" next to the concerned entries      
    def error_length_letters_display():
        ww=0
        while ww<nbofcalc:
            if error_list_length[ww]==1 :
                error_calculation_list[ww]="Error"
                var_calculation.set(error_calculation_list[ww])
                if error_list_letters[ww]==1:
                    error_calculation_list[ww]="Error"
                    var_calculation.set(error_calculation_list[ww])
                   
            ww+=1

#----- Loop to crate the entries and Label 
    for x in range(nbofcalc):
        cadre1=Frame(fenetre)
        cadre1.pack(side=TOP,anchor=NW)
        cadre=Frame(cadre1)
        cadre.pack()
        c=str(b)
        calc=Label(cadre,text="Calculation "+c+"  ")
        calc.pack(side=LEFT)
        var_entry=StringVar()

        my_entry=Entry(cadre,textvariable=var_entry, bd=5)
        my_entry.insert(0,ddd)
        my_entry.pack(side=LEFT)
        var_calculation=StringVar()
        var_calculation.set(error_calculation_list[a])
        calc_error_frame=Label(cadre, textvariable=var_calculation) # The Label to change if error
        calc_error_frame.pack(side=RIGHT)
        user_entries.append(my_entry)
        a+=1
        b+=1
        ddd+=1

Thank you !

Upvotes: 0

Views: 180

Answers (2)

Zeno Dalla Valle
Zeno Dalla Valle

Reputation: 919

You can store values and objects you need to change, so then you can change them dinamically. See this example

from tkinter import *
r =  Tk()

my_entries = []
for i in range(5):
    e = Label(r, text=i)
    my_entries.append(e)
    e.pack(side='top')
    
r.after(4000, lambda: my_entries[2].configure(text='Example'))
r.mainloop()

EDIT 1:As TheLizzard and Cool Cloud pointed out, it's better to avoid using time.sleep() while using tkinter. Replaced with non-blocking after()

Upvotes: 2

Frederic Chang
Frederic Chang

Reputation: 549

you could setup the trace function for tk.StringVar(), when user enter any value into Entry, it will be checked. for example as shown on below user only can type decimal, and you and setup length as well.

    def create_widgets(self):
        self.vars = tk.StringVar()
        self.vars.trace('w', partial(self.validate2, 1, 1))
        # Min Voltage Validating Part
        self.vars1 = tk.StringVar()
        self.vars1.trace('w', partial(self.validate2, 2, 2))
        # Max Voltage Validating Part
        self.vars2 = tk.StringVar()
        self.vars2.trace('w', partial(self.validate2, 3, 4))
        # Current Validating Part
        self.vars3 = tk.StringVar()
        self.vars3.trace('w', partial(self.validate2, 4, 3))
        # Channel Validating Part
        # function( key, size)

        self.enter_info = tk.Label(self, text="Please enter your information: ", bg="lightgrey")
        self.enter_info.grid(tke_Table_EnterInfo)

        self.voltage = tk.Label(self)
        self.voltage["text"] = "MinVoltage"
        self.voltage.grid(tke_Label_MinVoltage)
        self.voltageInput = tk.Entry(self, width=10, textvariable=self.vars).grid(tke_StringBox_MinVoltage)
        self.vars.set(0)
        # Min Voltage Validating Part
        self.current = tk.Label(self)
        self.current["text"] = "MaxVoltage"
        self.current.grid(tke_Label_MaxVoltage)
        self.currentInput = tk.Entry(self, width=10, textvariable=self.vars1).grid(tke_StringBox_MaxVoltage)
        self.vars1.set(5)
        # Max Voltage Validating Part
        self.power = tk.Label(self)
        self.power["text"] = "Current"
        self.power.grid(tke_Label_MaxCurrent)
        self.powerInput = tk.Entry(self, width=10, textvariable=self.vars2).grid(tke_StringBox_MaxCurrent)
        self.vars2.set(62.5)
        # Max Current Validating Part

        self.channel = tk.Label(self)
        self.channel["text"] = "channel"
        self.channel.grid(tke_Label_Channel)
        self.channelInput = tk.Entry(self, width=10, textvariable=self.vars3).grid(tke_StringBox_Channel)
        self.vars3.set(8)
        # Max Channel Validating Part


    def validate2(self, key, size, *args):
        # TODO:add more information
        if key == 1:
            value = self.vars.get()
        elif key == 2:
            value = self.vars1.get()
        elif key == 3:
            value = self.vars2.get()
        else:
            value = self.vars3.get()

        if not value.isdecimal():
            print(len(value))
            # if len(value) < 2:
            corrected = ''.join(filter(str.isdecimal, value))
            if key == 1:
                self.vars.set(corrected)
            elif key == 2:
                self.vars1.set(corrected)
            elif key == 3:
                self.vars2.set(corrected)
            else:
                self.vars3.set(corrected)
        if key == 1:
            corrected = self.vars.get()
            corrected = corrected[0:size]
            self.vars.set(corrected)
        elif key == 2:
            corrected = self.vars1.get()
            corrected = corrected[0:size]
            self.vars1.set(corrected)
        elif key == 3:
            corrected = self.vars2.get()
            corrected = corrected[0:size]
            self.vars2.set(corrected)
        else:
            corrected = self.vars3.get()
            corrected = corrected[0:size]
            self.vars3.set(corrected)

Upvotes: 1

Related Questions