下午好,
我正在尝试编写一个在树莓派PI上运行我的HVAC以及许多其他系统的应用程序。我将是第一个承认python和我不是好朋友的人。但是,我正在使用的传感器的驱动程序库似乎与Java或我准备编写代码的其他任何程序都不兼容。我花了几天的时间寻找答案,但未能找到为我工作。
基本上,我正在尝试获取getcurrentTH()函数来更新GUI中的currenttempLabel。我不断收到错误消息。
名称错误:未定义名称currenttempLabel
我猜想这与我试图从外部函数调用类内部的标签有关。任何指针将不胜感激。
代码在下面。
import mysql.connector
import time
import Adafruit_DHT as dht
from tkinter import *
import random
import _thread
import threading
started = 0
currentTemp = 0
currentHumidity = 0
def getcurrentTH():
while started > 0:
global currentTemp
global currentHumidity
h,t = dht.read_retry(dht.DHT22, 4)
currentTemp = ((t *1.8) + 32)
currentHumidity = h
currenttempLabel['text'] = currentTemp
time.sleep(5)
def start():
global started
started = 1
print("started")
print(started)
t3 = threading.Thread(target=getcurrentTH)
t3.start()
def stop():
global started
started = 0
def quitapp():
exit()
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
self.master = master
self.init_window()
def init_window(self):
global currentTemp
global currentHumidty
self.pack(fill=BOTH, expand=1)
startButton = Button(self, height = 3, width = 5, bg = "light green", text= "Start", command=start)
startButton.place(x=625, y=50)
stopButton = Button(self, height =3, width =5, bg = "red", text = "Stop", command=stop)
stopButton.place(x=625, y=150)
statusLabel = Label(self, text = "Current Status: N/A")
statusLabel.place(x=600, y=125)
quitButton = Button(self, height =3, width = 5, text = "Quit", command=quitapp)
quitButton.place(x=625, y=500)
currenttempLabel = Label(self, font = ("Courier",26), text = "No Current Reading" )
currenttempLabel.place(x=50, y=50)
root = Tk()
root.geometry("800x600")
app = Window(root)
root.mainloop()
答案 0 :(得分:1)
您的currenttempLabel
是Window.init_window
中的局部变量。该函数退出后,变量便消失了,无法再访问其值了。
如果要将这些小部件存储在以后可以访问的变量中,最简单的方法是将它们放在对象的属性中:
self.currenttempLabel = Label(self, font = ("Courier",26), text = "No Current Reading" )
self.currenttempLabel.place(x=50, y=50)
现在,您可以通过全局app
变量访问它们。 (最好是传递Window
对象,或者将这些顶级函数移到可以作为Window
进行访问的self
方法中,而不是将其存储为全局对象。因为您当前的设计中已有全局变量,所以可以使用它。)
app.currenttempLabel['text'] = currentTemp
但是,一旦解决该问题,就会遇到另一个主要问题:
t3 = threading.Thread(target=getcurrentTH)
未在主线程中运行的代码不允许接触任何tkinter小部件。视您的平台而定,它可能会引发异常,挂起GUI,崩溃,或者最坏的情况是大约90%的时间都能正常工作,但有时会出错。
有多种方法可以解决此问题。主要的功能在this article in the Tkinter book中进行了描述:创建一个queue.Queue
,对主线程进行轮询q.get_nowait()
并调用它在那里找到的任何函数,并使后台线程只是q.put
个函数而不是直接打电话给他们。
有一个名为mttkinter
的库,它封装了该技术,但它是针对Python 2.3的; Python 2.7的端口看起来非常可靠,但是对于3.x,我只知道the one I slapped together a few years ago because none of the others worked之类的未经测试和未维护的fork。因此,如果您要采用这种方式,则仍然需要了解所有内容的工作原理,以便自己进行测试和维护。