让 Pyphons Tkinter 使用变化的变量更新标签

Getting Pyphons Tkinter to update a label with a changing variable

我有一个为 Raspberry Pi 项目编写的 python 脚本,该脚本每秒从千分尺读取一个值,并将该值存储为 TkInter StringVar (http://effbot.org/tkinterbook/variable.htm)

我想要的是该字符串作为标签显示在 UI 上,并在值更改时在 UI 上更新。

我选择使用 Tkinter stringvar 而不是标准字符串,因为我认为 Tkinter 然后会在 UI 上自动更新,但它似乎不起作用。 目前该脚本不显示任何标签,并且在 show 设置 virtual_reading.

时不会更新

从我读过的其他线程来看,Tkinter 方法 update_idletasks() 应该会强制 window 更新,但我无法让它工作。

任何人都可以就我哪里出错提供任何指导吗? 这是我第一次去 Python 很抱歉,如果这很简单。

import datetime
import csv
from tkinter import *
from tkinter import messagebox
import time
import pigpio
import os

os.system("sudo pigpiod")

root = Tk()

winx = 480
winy = 320 


CLOCK=21
DATA=20

g_level=0
g_reading=0
g_bits=0

pi = pigpio.pi()


virtual_reading = StringVar()

def go():
   global cb1
   global cb2
   cb1 = pi.callback(DATA, pigpio.EITHER_EDGE, cbf)
   cb2 = pi.callback(CLOCK, pigpio.EITHER_EDGE, cbf)
   root.after(1000 ,go)



def show(bits, value):

   inch = value & (1<<23)
   minus = value & (1<<20)

   value = value & 0xfffff

   if inch:
      reading = value / 2000.0
      units = "in"
   else:
      reading = value / 100.0
      units = "mm"

   if minus:
      sign = "-"
   else:
      sign = ""
   global virtual_reading
   virtual_reading = StringVar()
   virtual_reading.set("{} {:.3f} {}".format(sign, reading, units))
   print(virtual_reading.get())
   cb2.cancel()
   cb1.cancel()



def measure(event=None):
    todays_date = datetime.date.today()  
    try:
        get_tool_no = int(tool_no_entry.get())
        if get_tool_no <= 0:
            messagebox.showerror("Try Again","Please Enter A Number")
        else:
            with open("thickness records.csv", "a") as thicknessdb: 
                thicknessdbWriter = csv.writer(thicknessdb, dialect='excel', lineterminator='\r')
                thicknessdbWriter.writerow([get_tool_no] + [todays_date] + [virtual_reading.get()])
            thicknessdb.close()
    except:
           messagebox.showerror("Try Again","Please Enter A Number")
    tool_no_entry.delete(0, END)


def cbf(g, l, t):
   global g_level, g_reading, g_bits
   if g == DATA:
      if l == 0:
         g_level = 1
      else:
         g_level = 0
   elif g == CLOCK:
      if l == pigpio.TIMEOUT:
         if g_bits > 10:
            show(g_bits, g_reading)
            g_reading=0
            g_bits=0
      elif l == 0:
          g_reading = g_reading | (g_level<<g_bits)
          g_bits += 1


go()


record_button = Button(root,width = 30,
                               height = 8,
                               text='Measure',
                               fg='black',
                               bg="light grey", command = measure)

tool_no_entry = Entry(root)

reading_display = Label(root, font=("Helvetica", 22), text = virtual_reading.get())

reading_display.place(x = 50, y =80)



root.resizable(width=FALSE, height=FALSE) 
root.geometry('%dx%d' % (winx,winy)) 
root.title("Micrometer Reader V1.0")


record_button.place(x = 340, y = 100, anchor = CENTER)


tool_no_entry.place(x = 120, y = 250, anchor=CENTER)
tool_no_entry.focus_set()


root.bind("<Return>", measure)


root.mainloop()

cb2.cancel()
cb1.cancel()
pi.stop()

您误解了 StringVar 的工作原理。首先,您每秒都在重新创建 StringVar,并且只有原始的那个与标签相关联。您创建的那个没有与任何小部件相关联,因此它永远不会可见。

第二个问题是您错误地将变量与标签相关联。你这样做:

reading_display = Label(..., text = virtual_reading.get())

...当您应该这样做以获得 auto-update 功能时:

reading_display = Label(..., textvariable = virtual_reading)

也就是说,您根本不需要使用 StringVar。您可以使用它,但它只是您必须管理的一个额外对象。您可以随时使用 configure 方法直接设置显示的字符串

text = "{} {:.3f} {}".format(sign, reading, units)
reading_display.configure(text=text)

注意:您不需要调用updateupdate_idletasks