我使用Tkinter编写了一个GUI,第一次运行时工作正常。但是,在退出后我尝试再次运行它,我收到以下错误:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Anaconda\lib\lib-tk\Tkinter.py", line 1470, in __call__
return self.func(*args)
File "G...tkinter_ny.py", line 55, in <lambda>
self.myRunModelButton=tk.Button(f1,text='Run Model', command=lambda: self.BeregnModel(), width=15, height=4)
File "G...tkinter_ny.py", line 115, in BeregnModel
sl.sim(self.model,self.data,'2013Q3','2015Q4')
File "stresslos.py", line 115, in sim
print (period,' solved')
File "G...tkinter_ny.py", line 39, in write
**self.text_area.insert(tk.END, str)**
File "C:\Anaconda\lib\lib-tk\Tkinter.py", line 3048, in insert
self.tk.call((self._w, 'insert', index, chars) + args)
TclError: invalid command name ".192096136L.192102984L"
我怀疑在运行用于修改stdput的代码时出现错误:该行封装在**中的问题。
class StdoutRedirector(object):
def __init__(self, text_area):
self.text_area = text_area
def write(self, str):
**self.text_area.insert(tk.END, str)**
self.text_area.see(tk.END)
self.text_area.update() #to be added to get it in real time
任何人都知道为什么会这样吗?
感谢您的回答。 完整代码添加:
import Tkinter as tk
import ttk as ttk
import pandabank as pb
import sys as sys
import subprocess as sp
class StresGUI(tk.Tk, ):
def __init__(self,inputData, inputModel):
tk.Tk.__init__(self)
# w,h=1000,900
# self.geometry("%dx%d+0+0" % (w, h))
self.grid()
self.title(The Name) #name of frame
#initializing data
self.data=pb.databank('')
self.data.set_data(inputData)
self.model=inputModel
self.selection = None
#self.frame=tk.Frame()
nb=ttk.Notebook(self)
nb.pack(fill='both', expand='yes')
#class redirect and update widgets with shell output in real time
class StdoutRedirector(object):
def __init__(self, text_area):
self.text_area = text_area
def write(self, str):
self.text_area.insert(tk.END, str)
self.text_area.see(tk.END)
self.text_area.update() #to be added to get it in real time
# create a child frame for each page
f1 = tk.Frame()
f2 = tk.Frame()
f3 = tk.Frame()
# create the pages
nb.add(f1, text='Solve models')
nb.add(f2, text='Bank information')
nb.add(f3, text='Treeview')
'''Adding items to frame 1 - Solve model'''
#put run model button on frame1
self.myRunModelButton=tk.Button(f1,text='Run Model', command=lambda: self.BeregnModel(), width=15, height=4)
self.myRunModelButton.pack(side=tk.TOP, fill=tk.BOTH)
#Quit program button on fram1
self.myQuitButton=tk.Button(f1,text='Quit', command=self.destroy,width=15, height=4)
self.myQuitButton.pack(side=tk.BOTTOM, fill=tk.BOTH)
outputPanel =tk.Text(f1, wrap='word', height = 25, width=40)
outputPanel1 =tk.Text(f2, wrap='word', height = 25, width=40)
outputPanel.pack(side=tk.BOTTOM)
outputPanel1.pack(side=tk.BOTTOM)
self.out1=StdoutRedirector(outputPanel)
self.out2=StdoutRedirector(outputPanel1)
sys.stdout = self.out1 #setting print output to frame1 initially
f1.bind("<Enter>",lambda e: self.useOut1()) #changig print output when entering the frame
f2.bind("<Enter>",lambda e: self.useOut2()) #changig print output when entering the frame
'''Adding items to frame 2 - Bank info'''
#plot values button
self.myPlotButton=tk.Button(f2,text='Plot values', command=lambda: self.PlotValues(self.data),width=15, height=4)
self.myPlotButton.pack(side=tk.TOP, fill=tk.BOTH)
#print values button
self.myPrintButton=tk.Button(f2,text='Print values', command=lambda:self.PrintValues(self.data),width=15, height=4)
self.myPrintButton.pack(side=tk.TOP, fill=tk.BOTH, anchor=tk.NW,before=self.myPlotButton)
#scrollbar for var selection
f2.scrollbar=ttk.Scrollbar(f2)
f2.scrollbar.pack(side=tk.RIGHT, fill=tk.BOTH)
lb = tk.Listbox(f2, yscrollcommand=f2.scrollbar.set, width=50)
for items in self.model.allvar:
lb.insert(tk.END,items)
lb.bind("<Double-Button-1>", self.SelectVar)
lb.pack(side=tk.LEFT, fill=tk.BOTH)
f2.scrollbar.config(command=lb.yview)
def SelectVar(self, event):
widget = event.widget
selection=widget.curselection()
value = widget.get(selection[0])
self.selection=value
def BeregnModel(self):
import stresslos as sl
try:
os.remove('los.pyc')
except:
pass
sl.simskriv(self.model)
sl.sim(self.model,self.data,'2013Q3','2015Q4')
def PlotValues(self,inputdata):
fig=inputdata.data[app.selection].plot()
return fig
def PrintValues(self,inputdata):
if app.selection == None:
print ('Please select variable to print')
else:
sp.call('cls',shell=True)
inputdata.print_item(app.selection)
def useOut1(self):
sys.stdout = self.out1
def useOut2(self):
sys.stdout = self.out2
if __name__ == "__main__":
app = StresGUI(data,model)
app.mainloop()T
答案 0 :(得分:1)
这必须与spyder有关,或者与你如何设置重定向器有关。我对spyder一无所知,所以我不能肯定地说。问题的关键是,你在一个被破坏的小部件上调用一个方法。
我的猜测是你重定向stdout,然后你退出程序,但stdout仍然被重定向。因此,当spyder需要打印某些东西时,它会尝试去旧的标准输出。当它这样做时,它会尝试将数据插入到已被销毁的旧文本小部件中。