I can not change the state of an Entry () widget in Python and Tkinter

4

In my code, my Entry() state is originally as DISABLED . To enable the input, the user would need to check one of checkbuttons . Well, at least that's the idea. What happens is that I mark one of the boxes, but the entry is not released so that you can type in it. Here is the snippet of code:

self.sum_l = Label(self.root, text = 'Soma', bg = 'Lightskyblue2')
self.sum_s = IntVar()
self.sum_c = Checkbutton(self.root, bg = 'Lightskyblue2', command = self.Sum, variable = self.sum_s)

self.sub_l = Label(self.root, text = 'Subtração', bg = 'Lightskyblue2')
self.sub_s = IntVar()
self.sub_c = Checkbutton(self.root, bg = 'Lightskyblue2', command = self.Sub, variable = self.sub_s)

self.mult_l = Label(self.root, text = 'Multiplicação', bg = 'Lightskyblue2')
self.mult_s = IntVar()
self.mult_c = Checkbutton(self.root, bg = 'Lightskyblue2', command = self.Mult, variable = self.mult_s)

self.div_l = Label(self.root, text = 'Divisão', bg = 'Lightskyblue2')
self.div_s = IntVar()
self.div_c = Checkbutton(self.root, bg = 'Lightskyblue2', command = self.Div, variable = self.div_s)

self.entry = Entry(self.root, bg = 'white')
if any([self.sum_s.get(), self.sub_s.get(), self.mult_s.get(), self.div_s.get()]):
    self.entry['state'] = NORMAL
else:
    self.entry['state'] = DISABLED

It's probably something obvious that I did not notice. Can anyone tell you what it is?

    
asked by anonymous 17.08.2015 / 14:10

1 answer

3

Yes - what happens is that when we program to respond to desktop applications (and modern web applications with asynchronous requests) - the thing changes a bit from programming to terminal.

There is no magic possible: if you write a code snippet like the one above, it runs all at once. Then the program is stopped waiting for interaction with the user. When the user interacts, one of the callback functions is executed.

In your case your if any([... is executed once as soon as the window is mounted, but there is no tracking code if there has been any change in the widgets you look at in the list. The check is done once.

So you have to connect a function to run when your variables change - and do not put the code together with the creation of widgets.

This can be done for example with the "trace" method of Tkinter% s: you give it a function or method to call when it is changed - you can change its if into a method - and put a callback for each of your variables. The way to do this "in extenso" - that is, without using IntVar to configure several components at a time is to put after creating each of your for a call of the type:

self.mult_s.trace('w', self.changed) 

('w' indicates that the function will be called when the variable is altered (written))

And then you create the IntVar method where you can put exactly the same changed you put above:

def changed(self, *args):
    if any([self.sum_s.get(), self.sub_s.get(), self.mult_s.get(), self.div_s.get()]):
        self.entry['state'] = NORMAL
    else:
        self.entry['state'] = DISABLED

These changes should be enough for you.

    
18.08.2015 / 21:58