_tkinter.TclError:带有pyepics的回调中的堆栈空间(无限循环?)

时间:2015-09-01 08:55:50

标签: tkinter

我正在使用一个名为pyepics的软件包来读取某些硬件的通道(在这种情况下说是湿度)。这具有在值更改时运行回调的功能。我想在gui中显示新值。

import Tkinter
import epics

global root

class AlarmGUI:
    def __init__(self,parent):
        self.ending = False

        Tkinter.Label(text="Weather Alarm",bg="AntiqueWhite2",font=("Helvetica", 10,"bold")).grid(row=0,columnspan=2)

        self.grh2l = Tkinter.Label(text='CFHT RH')
        self.grh2l.grid(row=1,column=2,padx=10,pady=10,sticky=Tkinter.E)

    def cfh(self,value=None,**kw):
        print 'value is',value
        if (value < 80):
            self.grh1 =Tkinter.Label(text=value,bg='Green')
            self.grh1.grid(row=2,column=2, padx=10, pady=10)
        elif (value > 80 and value < 85):
            self.grh1 =Tkinter.Label(text=value,bg='Yellow')
            self.grh1.grid(row=2,column=2, padx=10, pady=10)
        else:
            self.grh1 =Tkinter.Label(text=value,bg='Red')
            self.grh1.grid(row=2,column=2, padx=10, pady=10)

    return gw

def CFHTWeather():
    ag = AlarmGUI(root)
    crh = epics.PV('ws:wsHumid',callback=ag.cfh,auto_monitor=True).get() 

    return cw

def main():
    global root

    root = Tkinter.Tk()
    root.wm_title('Weather Alarms')
    gui = AlarmGUI(root)
    cw = CFHTWeather()

    root.mainloop()

if __name__ == '__main__':
    main()  

但是我得到了Tkinter.Label一行应该显示新值的投诉。

  File "./weatherAlarm.py", line 73, in cfh
    self.grh1 =Tkinter.Label(text=value,bg='Red')
  File "/usr/lib64/python2.6/lib-tk/Tkinter.py", line 2466, in __init__
    Widget.__init__(self, master, 'label', cnf, kw)
  File "/usr/lib64/python2.6/lib-tk/Tkinter.py", line 1932, in __init__
    (widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: out of stack space (infinite loop?)

如果您对PyEpics信息以及我正在使用的PV类感兴趣,请访问:http://cars9.uchicago.edu/software/python/pyepics3/

我从其他关于这个“堆栈空间”的问题中看到它可能是因为我正在运行另一个无限循环。但我不明白我的代码是如何做到的 - 我想要的只是在频道改变时改变的gui。 PV类中的回调功能本身是无限循环吗?

1 个答案:

答案 0 :(得分:1)

没有看到PV类无法肯定地说,但看起来你每次调用回调ag.cfh时都会重新创建所有小部件,而且你看看这会导致out of stack space错误。

而不是像你正在做的那样重新创建小部件来更新它们的值。您应该使用其他小部件将标签的创建移至__init__方法,然后使用self.grh1['text'] = valueself.grh1['background'] = some_color更新小部件。

注意,背景不会自动更改。由于每次都创建了一个新的小部件,我假设它在你的情况下。

或者,您可以创建一个类属性来检查窗口小部件是否已经创建(即 - 计数器或布尔值),并且仅当此计数器小于指定值或某些值时才使用if语句创建窗口小部件如果您不希望在__init__开始时自动创建窗口小部件,请进行其他适当的检查。

另外,我应该注意,从您发布的代码块看来global root似乎是多余的,不需要这个。另外,并非真正的错误,但我发现的一个奇怪之处在于您将root作为父级传递,并且未在创建小部件时指定父级。如果您将tkinter帧作为父级传递,该怎么办?小部件被隐式创建到根窗口。