Reputation: 67
I have a mainframe class and then a 'inforow' class that fills info on the frame row by row but the StringVar and Intvar's dont seem to work. They are being set as the printout shows but the checkbutton doesn't reflect the value that they are being set to. I have made a simpler version that highlights the issue in these two files.
I am using 'Python 2.7.12 (v2.7.12:d33e0cf91556, Jun 27 2016, 15:19:22) [MSC v.1500 32 bit (Intel)] on win32'
When I run mainframe.py all the checkbuttons are blank but I am expecting them to be a mix of set and unset.
mainframe.py
from Tkinter import *
import ttk
import inforow
testinfo = {'ITEM 1': {'one':1, 'two':0, 'three':1}
, 'ITEM 2': {'one':0, 'two':1, 'three':0}}
class MainFrame(Frame):
def __init__(self, parent=None, **options):
Frame.__init__(self, parent, **options)
self.pack(expand=YES, fill=BOTH)
self.addHeader()
self.addInfo(testinfo)
def addHeader(self):
Label(self, text="Item").grid(row=0,column=0)
Label(self, text="one").grid(row=0,column=1)
Label(self, text="two").grid(row=0,column=2)
Label(self, text="three").grid(row=0,column=3)
def addInfo(self, info):
row = 1
for item in info:
inforow.InfoRow(self, row, item, info[item])
row += 1
if __name__ == "__main__":
root = Tk()
MainFrame(root)
root.mainloop()
and inforow.py
from Tkinter import *
import ttk
class InfoRow():
def __init__(self, root, row, item, values):
self.chkUsedVar1 = IntVar()
self.chkUsedVar1.set(values["one"])
self.chkUsedVar2 = IntVar()
self.chkUsedVar2.set(values["two"])
self.chkUsedVar3 = IntVar()
self.chkUsedVar3.set(values["three"])
self.skillLabel = Label(root, width=10, text=item, anchor="w")
self.skillLabel.grid(row=row,column=0,sticky=W)
self.usedChkButton1 = Checkbutton(root, text='Used1', variable=self.chkUsedVar1)
self.usedChkButton1.grid(row=row,column=1)
self.usedChkButton2 = Checkbutton(root, text='Used2', variable=self.chkUsedVar2)
self.usedChkButton2.grid(row=row,column=2)
self.usedChkButton3 = Checkbutton(root, text='Used3', variable=self.chkUsedVar3)
self.usedChkButton3.grid(row=row,column=3)
print 'Row ' + item
print self.chkUsedVar1.get()
print self.chkUsedVar2.get()
print self.chkUsedVar3.get()
print
Upvotes: 0
Views: 3333
Reputation: 9597
Your IntVar
s are referenced only by the instance of your InfoRow
class - and you do not keep any reference to that, so it all gets garbage collected immediately. (Passing a var to Checkbutton()
does not actually store a reference to the var, just its auto-generated name - PY_VAR0
or whatever.)
If you completed this program, you'd obviously need to store the InfoRow
s somewhere, so that you could retrieve the var values - and that would be enough to fix the Checkbuttons.
Upvotes: 3
Reputation: 7176
That was quite a lot of code. I had to reduce it to track down the issue. I found a symptom but I'm unable to see exactly how this should be done. It has something to do with the parent of Checkbutton. Examine my almost working code:
from tkinter import *
class MainFrame(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.pack(expand=YES, fill=BOTH)
chk = IntVar()
chk.set(1)
used1 = Checkbutton(parent, text='Used1', variable=chk)
used1.pack()
print(self.winfo_children()[0])
root = Tk()
MainFrame(root)
root.mainloop()
Now, this code results in the Checkbutton being checked, but the last line in the class, print(self.winfo_children()[0])
generates an error:
Traceback (most recent call last):
File "C:\Users\qwerty\Documents\Python\test.py", line 15, in <module>
MainFrame(root)
File "C:\Users\qwerty\Documents\Python\test.py", line 12, in __init__
print(self.winfo_children()[0])
IndexError: list index out of range
If I remove that line the error disappears, but also the checked state of the Checkbutton. I can't seem to understand this at the moment. I think I need a large coffee.
(I'm using Python 3.6.5 under win10)
Upvotes: 0