主线程不在主循环中并且无法调用canvas命令

时间:2016-07-22 00:44:28

标签: python multithreading canvas

我正在做关于覆盆子pi的最终项目。我的项目将能够显示当前温度并使用matplotlib在图表中显示。现在我需要提供PWM反馈来控制加热板。但是在单个线程中,代码将停留在while循环中,从而产生PWM输出。所以我想开始一个新的主题。但现在它会像输入代码一样显示

Unhandled exception in thread started by <function main.<locals>.start at 0x7367e660>
Traceback (most recent call last):
 File "/home/pi/testthread.py", line 81, in start
while float(temp_MAX.get())>float(temp_current()):
File "/usr/lib/python3.4/tkinter/__init__.py", line 339, in get
value = self._tk.globalgetvar(self._name)
RuntimeError: main thread is not in main loop

我的代码是:

import spidev
import matplotlib
import time
from tkinter import *
import RPi.GPIO as GPIO
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import _thread

matplotlib.use('Tkagg')

GPIO.setwarnings(False)


f1=open('temp.txt','w')
f2=open('time.txt','w')

spi=spidev.SpiDev()
spi.open(0,0)


root=Tk()
root.wm_title('TempControl')



def main():
    def entry_max():
            entry_max=Toplevel(root)
            Max_entry_label=Label(entry_max,text='input youe MAX temperature').grid(row=0,columnspan=3)
            Display_max=Entry(entry_max,textvariable=temp_MAX).grid(row=1,columnspan=3)
            Max_9=Button(entry_max,text='9',command=lambda w=temp_MAX: w.set(w.get()+str(9)),height=2,width=6).grid(row=2,column=2)
            Max_8=Button(entry_max,text='8',command=lambda w=temp_MAX: w.set(w.get()+str(8)),height=2,width=6).grid(row=2,column=1)
            Max_7=Button(entry_max,text='7',command=lambda w=temp_MAX: w.set(w.get()+str(7)),height=2,width=6).grid(row=2,column=0)
            Max_6=Button(entry_max,text='6',command=lambda w=temp_MAX: w.set(w.get()+str(6)),height=2,width=6).grid(row=3,column=2)
            Max_5=Button(entry_max,text='5',command=lambda w=temp_MAX: w.set(w.get()+str(5)),height=2,width=6).grid(row=3,column=1)
            Max_4=Button(entry_max,text='4',command=lambda w=temp_MAX: w.set(w.get()+str(4)),height=2,width=6).grid(row=3,column=0)
            Max_3=Button(entry_max,text='3',command=lambda w=temp_MAX: w.set(w.get()+str(3)),height=2,width=6).grid(row=4,column=2)
            Max_2=Button(entry_max,text='2',command=lambda w=temp_MAX: w.set(w.get()+str(2)),height=2,width=6).grid(row=4,column=1)
            Max_1=Button(entry_max,text='1',command=lambda w=temp_MAX: w.set(w.get()+str(1)),height=2,width=6).grid(row=4,column=0)
            Max_dot=Button(entry_max,text='.',command=lambda w=temp_MAX: w.set(w.get()+str('.')),height=2,width=6).grid(row=5,column=0)
            Clear_max=Button(entry_max,text='CLEAR',bg='red',fg='white',command=lambda w=temp_MAX: w.set(' '),height=2,width=6).grid(row=5,column=2)
            Max_0=Button(entry_max,text='0',command=lambda w=temp_MAX: w.set(w.get()+str(0)),height=2,width=6).grid(row=5,column=1)


    def entry_min():
          entry_min=Toplevel(root)
          Min_entry_label=Label(entry_min,text='input youe MIN temperature').grid(row=0,columnspan=3)
          Display_min=Entry(entry_min,textvariable=temp_MIN).grid(row=1,columnspan=3)
          Min_9=Button(entry_min,text='9',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=2,column=2)
          Min_8=Button(entry_min,text='8',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=2,column=1)
          Min_7=Button(entry_min,text='7',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=2,column=0)
          Min_6=Button(entry_min,text='6',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=3,column=2)
          Min_5=Button(entry_min,text='5',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=3,column=1)
          Min_4=Button(entry_min,text='4',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=3,column=0)
          Min_3=Button(entry_min,text='3',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=4,column=2)
          Min_2=Button(entry_min,text='2',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=4,column=1)
          Min_1=Button(entry_min,text='1',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=4,column=0)
          Min_0=Button(entry_min,text='0',command=lambda y=temp_MIN: y.set(y.get()+str(9)),height=2,width=6).grid(row=5,column=1)
          Min_dot=Button(entry_min,text='  .  ',command=lambda y=temp_MIN: y.set(y.get()+str('.')),height=2,width=6).grid(row=5,column=0)
          Clear_min=Button(entry_min,text='CLEAR',bg='red',fg='white',command=lambda w=temp_MIN: w.set(' '),height=2,width=6).grid(row=5,column=2)

    def Stop_GPIO():
          GPIO.cleanup()
          root.quit()
          root.destroy()

    def Start_Heat():
            _thread.start_new_thread(start,())
            return

    def start():
            GPIO.setmode(GPIO.BOARD)
            GPIO.setup(12,GPIO.OUT)
            a=50
            b=30
            p=GPIO.PWM(12,0.2)
            p.start(0)
            while float(temp_MAX.get())>float(temp_current()):
                    p.ChangeDutyCycle(a)
                    if float(temp_MAX.get())>float(temp_current()):
                            p.ChangeDutyCycle(b)



    Max=Button(root,text='MAX Temperature:',command=entry_max).grid(row=0,column=0)
    temp_MAX=StringVar(0)
    Max_Entry=Entry(root,textvariable=temp_MAX).grid(row=0,column=1)

    Min=Button(root,text='MIN Temperature:',command=entry_min).grid(row=1,column=0)
    temp_MIN=StringVar(0)
    Min_Entry=Entry(root,textvariable=temp_MIN).grid(row=1,column=1)

    temp=Label(root,text='Current Temperature:',anchor='w').grid(row=2,column=0)

    temp_current=DoubleVar()
    temp_display=Label(root,textvariable=temp_current).grid(row=2,column=1)

    Start_Heat=Button(root,text='START',bg='blue',fg='white',command=Start_Heat).grid(row=3,column=0)

    button=Button(root,text='Stop',command=Stop_GPIO).grid(row=3,column=1)

    def readadc(adcnum):
            if adcnum > 7 or adcnum < 0:
                return -1
            r=spi.xfer2([1,8 +adcnum<<4,0])
            adcout=((r[1]&3)<<8)+r[2]
            value=adcout
            volts=('%.3f'%((value*3.3)/4095))
            temperature=('%.3f'%(((((value*3.3)/1023)*4)/(50-   ((value*3.3)/1023)*2))/0.00375))
            return temperature

    m=0
    n=0
    while n==m:
            root.update()
            temp_current.set(readadc(0))
            yfile=open('temp.txt','a')
            yfile.write(str(temp_current.get()))
            yfile.write('\n')
            xfile=open('time.txt','a')
            xfile.write(str(m))
            xfile.write('\n')
            yasix=open('temp.txt','r')
            xasix=open('time.txt','r')
            tempList=yasix.readlines()
            timeList=xasix.readlines()
            tempFloat=[float(x) for x in tempList]
            timeFloat=[float(x) for x in timeList]
            tempArray=np.array(tempFloat)
            timeArray=np.array(timeFloat)
            ff=Figure(figsize=(3,3),dpi=100)
            a=ff.add_subplot(111)
            a.plot(timeArray,tempArray,'-')
            a.set_xlabel('time')
            a.set_ylabel('temperature')
            a.set_xlim(0,n+10)
            a.set_ylim(0,temp_current.get()+10)
            canvas=FigureCanvasTkAgg(ff,master=root)
            canvas.show()
            canvas.get_tk_widget().grid(rowspan=3,column=2)
            canvas._tkcanvas.grid(row=4,columnspan=2,column=0)
            n=n+1
            time.sleep(0.5)
            if n!=m:
                m=m+1
                time.sleep(0.5)
                continue

if __name__=='__main__':
        main()

root.mainloop()

还有一个问题。每当我关闭程序时,它都会显示

   _tkinter.TclError: can't invoke "canvas" command: application has been destroyed

主要问题是第一个,因为我现在不能继续。您可以提供所有建议和猜测。我是python的新手,所以可能还有其他一些错误。

0 个答案:

没有答案