Table cell value does not update
vnahmias opened this issue · comments
Hello i am facing a really weird issue,
I have a file "editorWindow2.py" which when it's called creates a tk frame containing several tableCanvas :
Everything works like a charm i can click on cells and change their values to finally export the whole thing into an xml file.
However sometimes i call the same file from an other entry point in the program but this time the cells are no more editable and i have no clues why. I have checked that i call the window with exactly the same type of objects and data as i do in the case where it works.
Here is the code :
class editionWindowModel2():
def __init__(self):
pass
class editionWindowView2():
def __init__(self,master,count):
self.frames=[]
for i in range(count):
self.frames.append(tk.Frame(master))
self.frames[i].pack(fill=tk.BOTH, expand=True)
class editionWindowController2():
def __init__(self,data,count):
self.root = tk.Tk()
self.root.geometry("1920x1200")
self.canvas=tk.Canvas(self.root)
self.container=tk.Frame(self.canvas)
self.model=editionWindowModel2()
self.view=editionWindowView2(self.container,count)
self.vsb = tk.Scrollbar(self.root, orient="vertical", command=self.canvas.yview)
self.canvas.configure(yscrollcommand=self.vsb.set)
self.vsb.pack(side="right", fill="y")
self.canvas.pack(side="left", fill=tk.BOTH, expand=True)
self.canvas.create_window(4,4,window=self.container, anchor="nw", tags="self.container")
self.container.bind("<Configure>", self.onFrameConfigure)
self.data=data
tables=[]#This variable will regroup as many table as the number of metric present in the orginal file
y=0
for metric in self.data :
x=0
tables.append(TableCanvas(self.view.frames[y],editable=True,width=1700,cellwidth=200,rows=metric.rows,cols=5,rowselectedcolor='#B0E0E6',colselectedcolor='#B0E0E6'))
colname=tables[y].model.getColumnName(4)
self.colorCol(tables[y],"#98FB98")
tables[y].model.columnwidths[colname]=1100
tables[y].show()
tables[y].model.setValueAt("Metric ID :",x,0)
#rest of the table is filled like the line above.
I precise that i am beginner with tkinter so please don't be too hard on me ahah
Let me explain more clearly : my program has two ways to be used, First user can chose to edit an xml file so he can import a file in order to edit it.
class firstWindowView():
def __init__(self,master):
self.frame = tk.Frame(master).grid(row=0,column=0,sticky="NSEW")
class firstWindowController():
def __init__(self):
self.root = tk.Tk()
self.model=firstWindowModel()
self.view=firstWindowView(self.root)
L1 = tk.Label(self.root, text = "Chose an action :").grid(row=0,column=1)
importButton=tk.Button(self.root,text="Import from XML",width=20,command=self.importXml).grid(row=0,column=2)
exportButton=tk.Button(self.root,text="Create your own",width=20,command=self.exportToXml).grid(row=1,column=2)
def run(self):
self.root.title("Raspberry Pi Data Sender")
self.root.mainloop()
def importXml(self):
self.root.destroy()
browser=XmlBrowserController()
browser.run()
def exportToXml(self):
self.root.destroy()
metricsCreator=metricsController()
metricsCreator.run()
in case where he choses "import", next window called is this one :
class XmlBrowserView():
def __init__(self,master):
self.frame = tk.Frame(master)
class XmlBrowserController():
def __init__(self):
self.root = tk.Tk()
self.model=XmlBrowserModel()
self.view=XmlBrowserView(self.root)
self.fileName=tk.StringVar()
self.fileName = fd.askopenfilename(initialdir = "../",title = "Select file")
L1 = tk.Label(self.root, text = "XML file Path : "+self.fileName).grid(row=0,column=0)
editButton=tk.Button(self.root,text="Edit",width=10,command=self.open).grid(row=0,column=1)
cancelButton=tk.Button(self.root,text="Cancel",width=10,command=self.quit).grid(row=1,column=1)
def run(self):
self.root.title("Load an XML file")
self.root.mainloop()
def open(self):
self.model.fileName=self.fileName
serializer=Serializer()
self.model.root=serializer.importFromFile(self.model.fileName)
display=displayController(self.model.root)
self.root.destroy()
display.run()
and finally
class displayView():
def __init__(self,master):
self.frame = tk.Frame(master).grid(row=0,column=0,sticky="NSEW")
class displayController():
def __init__(self,xmlElement):
self.root = tk.Tk()
self.root.grid_rowconfigure(0, weight=1)
self.root.grid_columnconfigure(0, weight=1)
self.model=displayModel(xmlElement)
self.tree=xmlElement
self.view=displayView(self.root)
self.fileName=tk.StringVar()
self.count=0
tree=self.prettify(xmlElement)
L1 = tk.Label(self.root,justify="left",anchor="w",text = tree).grid(row=0,column=0,sticky="NSEW")
saveButton2=tk.Button(self.root,text="Edit",width=10,command=self.save2).grid(row=self.count+2,column=0)
cancelButton=tk.Button(self.root,text="Cancel",width=10,command=self.quit).grid(row=self.count+1,column=0)
def save2(self):
root=self.model.xmlElement
metricsTable=[]
count=1
testCounter=0
for metric in root.findall("{http://standards.iso.org/iso-iec/19086/-2/ed-1/en}Metric"):
testCounter+=1
count+=1
params=[]
rules=[]
metricRefs=[]
expressions=[]
m=Metric(metric.get('id'),metric.get('source'),metric.get('scale'),metric.get('description'),metric.get('note'),metric.get('category'))
for param in metric.findall('{http://standards.iso.org/iso-iec/19086/-2/ed-1/en}Parameter'):
p=Parameter(param.get('id'),param.get('parameterStatement'),param.get('unit'),param.get('description'),param.get('note'))
params.append(p)
for expression in metric.findall('{http://standards.iso.org/iso-iec/19086/-2/ed-1/en}Expression'):
e=Expression(expression.get('id'),expression.get('expressionStatement'),expression.get('expressionLanguage'),expression.get('description'),expression.get('note'),expression.get('unit'))
expressions.append(e)
for rule in metric.findall('{http://standards.iso.org/iso-iec/19086/-2/ed-1/en}Rule'):
r=Rule(rule.get('id'),rule.get('ruleStatement'),rule.get('ruleLanguage'),rule.get('description'),rule.get('note'))
rules.append(r)
for ref in metric.findall('{http://standards.iso.org/iso-iec/19086/-2/ed-1/en}UnderlyingMetricRef'):
reference=UnderlyingMetricRef(ref.get('refid'))
metricRefs.append(reference)
m.parameters=params
m.rules=rules
m.underlyingMetrics=metricRefs
m.expression=expressions
m.rows=self.metricRowsCounter(metric,m)
metricsTable.append(m)
#print(type(metricsTable))
#print(metricsTable)
self.root.destroy()
editor=editionWindowController2(metricsTable,count)
editor.run()
and the last window called is the one i first showed you with the tkintertable.
the other use case changes only in the first windows :
class metricsView():
def __init__(self,master):
self.frame = tk.Frame(master)
class metricsController():
def __init__(self):
self.root = tk.Tk()
self.model=metricsModel()
self.view=metricsView(self.root)
self.metricList=[]
newMetricButton=tk.Button(self.root,text="Add a new metric",width=20,command= lambda : self.newMetric(self.metricList)).grid(row=0,column=0)
printButton=tk.Button(self.root,text="Print your file",width=20,command= lambda : self.toString(self.metricList)).grid(row=0,column=1)
saveButton=tk.Button(self.root,text="Save",width=20,command=lambda:self.save(self.metricList)).grid(row=0,column=2)
cancelButton=tk.Button(self.root,text="Quit",width=20,command=self.cancel).grid(row=0,column=3)
def run(self):
self.root.title("Metrics Creator")
self.root.mainloop()
def toString(self,metrics):
xmlTree=self.treeBuilder(metrics)
print(type(xmlTree))
display=displayController(xmlTree)
display.run()
and at this point the display is called with an object of the same type as it is in the first case.
Hi @dmnfarrell do you have any news for this bug ?
Did you say you can interact with the table. There is code in tkintertable/Testing.py that tests this very thing and it seems to work. You could take a look at it. It might be a key binding problem but you have given no error messages. It sounds like more to do with your own app.
The thing is that i checked every common mistakes i may have made, i checked the type of what comes out of the display controller and what comes it my editorController in both cases and they are all of the same type. I checked binding of every function and their buttons. In the case where i can't modify the table, i simply can't do anything else.
It would be best if you made a minimal example of 2 tables that works and then add more features into it bit by bit. If a minimal example works then something specific to your app is causing it. Your code is quite long and I can't go through it all in detail.
Hello @dmnfarrell i tried to print every variables in both cases and they have same types each time i don't see what i am missing man. I also have duplicated files for both use cases to try to see a difference between both behavior, i try to modify the second file to get something working but it doesn't here is the code where i can't edit cells :
class editionWindowView2():
def __init__(self,master,count):
self.frames=[]
for i in range(count):
self.frames.append(tk.Frame(master))
self.frames[i].pack(fill=tk.BOTH, expand=True)
class editionWindowController2():
def __init__(self,data,count):
self.root = tk.Tk()
self.root.geometry("1920x1200")
self.model=editionWindowModel2()
self.view=editionWindowView2(self.root,count)
y=0
self.data=data
tables=[]#This variable will regroup as many table as the number of metric present in the orginal file
for i in range(len(self.data)) :
table=(TableCanvas(self.view.frames[i],editable=True,width=1700,cellwidth=200,rows=data[i].rows,cols=5,rowselectedcolor='#B0E0E6',colselectedcolor='#B0E0E6'))
table.show()
tables.append(table)
for metric in self.data :
x=0
tables[y].model.setValueAt("Metric ID :",x,0)
tables[y].model.setValueAt("Metric Source :",x+1,0)
tables[y].model.setValueAt("Metric Scale :",x+2,0)
tables[y].model.setValueAt(metric.id,x,1)
tables[y].model.setValueAt(metric.source,x+1,2)
tables[y].model.setValueAt(metric.scale,x+2,2)
x+=3
if(metric.description!=None):
tables[y].model.setValueAt("Metric Description :",x,0)
tables[y].model.setValueAt(metric.description,x,2)
x+=1
elif(metric.category!=None):
tables[y].model.setValueAt("Metric Category :",x,0)
tables[y].model.setValueAt(metric.category,x,2)
x+=1
for expression in metric.expression:
tables[y].model.setValueAt("Expression ID :",x,0)
tables[y].model.setValueAt("Expression Statement :",x+1,0)
tables[y].model.setValueAt("Expression Language:",x+2,0)
tables[y].model.setValueAt(expression.id,x,3)
tables[y].model.setValueAt(expression.expressionStatement,x+1,4)
tables[y].model.setValueAt(expression.expressionLanguage,x+2,4)
x+=3
if(expression.description!=None):
tables[y].model.setValueAt("Expression Description :",x,0)
tables[y].model.setValueAt(expression.description,x,4)
x+=1
elif(expression.note!=None):
tables[y].model.setValueAt("Expression Note :",x,0)
tables[y].model.setValueAt(expression.note,x,4)
x+=1
elif(expression.unit!=None):
tables[y].model.setValueAt("Expression Unit :",x,0)
tables[y].model.setValueAt(expression.unit,x,4)
x+=1
try:
for param in metric.parameters:
tables[y].model.setValueAt("Parameter ID :",x,0)
tables[y].model.setValueAt("Parameter Statement :",x+1,0)
tables[y].model.setValueAt("Parameter Unit :",x+2,0)
tables[y].model.setValueAt(param.id,x,3)
tables[y].model.setValueAt(param.parameterStatement,x+1,4)
tables[y].model.setValueAt(param.unit,x+2,4)
x=x+3
if(param.description!=None):
tables[y].model.setValueAt("Parameter Description :",x,0)
tables[y].model.setValueAt(param.description,x,4)
x+=1
elif(param.note!=None):
tables[y].model.setValueAt("Parameter Note :",x,0)
tables[y].model.setValueAt(param.note,x,4)
x+=1
except :
pass
try:
for rule in metric.rules:
tables[y].model.setValueAt("Rule ID :",x,0)
tables[y].model.setValueAt("Rule Statement :",x+1,0)
tables[y].model.setValueAt("Rule Language :",x+2,0)
tables[y].model.setValueAt(rule.id,x,3)
tables[y].model.setValueAt(rule.ruleStatement,x+1,4)
tables[y].model.setValueAt(rule.ruleLanguage,x+2,4)
x=x+3
if(rule.description!=None):
tables[y].model.setValueAt("Rule Description :",x,0)
tables[y].model.setValueAt(rule.description,x,4)
x+=1
elif(rule.note!=None):
tables[y].model.setValueAt("Rule Note :",x,0)
tables[y].model.setValueAt(rule.note,x,4)
x+=1
except :
pass
try:
for ref in metric.underlyingMetrics:
tables[y].model.setValueAt("UnderlyingMetricRef :",x,0)
tables[y].model.setValueAt(ref.refid,x,3)
x=x+1
except :
pass
colname=tables[y].model.getColumnName(4)
self.colorCol(tables[y],"#98FB98")
tables[y].model.columnwidths[colname]=1100
tables[y].show()
y+=1
exportButton=tk.Button(self.root,text="Export To Xml",width=15,command=lambda: self.exportToXml(tables)).pack()
cancelButton=tk.Button(self.root,text="Quit",width=15,command=self.quit).pack()
I have finally found what causes cells not alterable, in file MetricsController
function toString()
, i had not wrote the line self.root.destroy()
which closes previous window before dsiplaying the new one, because wanted to be able to come back to that previous window. I think there is some kind of conflict between tkintertable and tk loops or something like this. Please if you have some time take a look at it and if you find what is wrong please keep me updated i wanna know !
So if your change fixes the problem why do you still think tkintertable cause a conflict of some kind? there is only one tkinter thread running at once and all the widgets run in that I believe.