让 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)
注意:您不需要调用update
或update_idletasks
我有一个为 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)
注意:您不需要调用update
或update_idletasks