[Tutor] how to "forget" some checkbuttons on a window

Chris Roy-Smith chris_roysmith at internode.on.net
Tue May 19 04:53:33 EDT 2020


On 19/5/20 5:52 pm, Alan Gauld via Tutor wrote:
> On 19/05/2020 06:20, Chris Roy-Smith wrote:
>> I am trying to hide some Checkbuttons.
> 
> Do you actually want them to become invisible?
> Or just to disable them(grey them out?)
> Most GUIS don;t hide controls they just disable them.
> A changing interface is confusing to users.

Hi Alan, Thank you for your assistance, I was thinking that as these 
items would not be of any interest to whoever uses this code once it's 
been checked off. Therefore I didn't consider just greying out. The data 
in the query behind this routine will not be available once the item is 
checked off anyway.

> 
>> from tkinter import *
>> testDat=[0,1,2,3,4,5,6,7,8,9]
>> def    remove(e):
>>       for i in range(9):
>>           r=var[i].get()
>>           if r==True:
>>               e[i].forget()
> 
> Notice no return value here so remove() always returns none.
> 
>> master=Tk()
>> master.title('experiment')
>>
>> e=[" " for i in range(len(testDat))]
> 
> You could just do:
> 
> e = [" "] * 10
> 
> But given your code below thre is no point since
> you just overwrite the values. You might as well
> use an empty list and append the controls below.
> 
>> var=[IntVar() for i in range(len(testDat))]
>> for i in range(len(testDat)):
>>       e[i]=Checkbutton(master, text=str(i), variable=var[i],
>> onvalue=True, offvalue=False).grid(row=i, column=0)
> 
> You could have created the IntVar here as well
> which would save a little bit of time since
> you'd only have one loop..
> 
> 
> But, you've fallen into one of the classic traps of Tkinter
> programming.
> You are storing the return value from grid() Which is None.
> You must create and store the control then grid it.

As I said to Peter Otten, I have been caught by this before, but the 
person who showed me the flaw in my code didn't explain why there was a 
need to separate the grid method from the widget creation. Am I better 
off always keeping the two separate? The OLD python (python 2.6!) text I 
have been using didn't discuss this at all.

> Rewriting your code above:
> 
> var = []
> for i in testDat:  # no need for range
>     var.append(IntVar())
>     e.append(Checkbutton(master, text = str(i),variable = var[-1],
>                          onvalue = true, offvalue=False))
>     e[-1].grid(row=i,column=0)

Is appending preferred to creating lists and lists of lists, if so I'll 
try that out in what I have previously done in other projects.

> 
>> Button(master, text='remove checked', command=lambda i=e:
>> remove(i)).grid(row=11, column=0)
> 
> And here you use grid on the return value of remove, but remove has no
> return value so again you get a none as default.

Knowing why makes things much clearer to me.

> 
>>     File "./frames.py", line 8, in remove
>>       e[i].forget()
>> AttributeError: 'NoneType' object has no attribute 'forget'
> 
> NoneType because of the premature grid() call above.
> 
> 



More information about the Tutor mailing list