Python-从外部函数更新Window类中的标签文本

时间:2018-08-31 20:05:01

标签: python tkinter

下午好,

我正在尝试编写一个在树莓派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()

1 个答案:

答案 0 :(得分:1)

您的currenttempLabelWindow.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。因此,如果您要采用这种方式,则仍然需要了解所有内容的工作原理,以便自己进行测试和维护。