让 Pyphons Tkinter 使用不断变化的变量更新标签 [英] Getting Pyphons Tkinter to update a label with a changing variable

查看:68
本文介绍了让 Pyphons Tkinter 使用不断变化的变量更新标签的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have a python script which I have written for a Raspberry Pi project, the script reads a value from a micrometer every second, and stores this value as a TkInter StringVar (http://effbot.org/tkinterbook/variable.htm)

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

What I want to happen is that that string is displayed on the UI as a label, and updated on the UI when the value changes.

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

I chose to use a Tkinter stringvar instead of a standard string because I thought that Tkinter would then automatically update on the UI, but it doesn't seem to work. Currently the script displays nothing for the label, and does not update when show sets virtual_reading.

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

From other threads I have read, the Tkinter method update_idletasks() should force the window to update, but I haven't been able to get this to work.

任何人都可以就我出错的地方提供任何指导吗?这是我第一次接触 Python,很抱歉,如果这很简单.

Can anyone give any guidance on where I'm going wrong? This is my first go at Python so sorry if this is simple.

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,并且只有原始的与标签相关联.您创建的那个与任何小部件都没有关联,因此它将永远不可见.

You are misunderstanding how StringVars work. For one, you're recreating the StringVar every second, and only the original one is tied to the label. The one you create isn't associated with any widgets so it will never be visible.

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

The second problem is that you're associating the variable with the label incorrectly. You're doing this:

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

...什么时候你应该这样做以获得自动更新功能:

... when you should be doing it like this to get the auto-update feature:

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

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

That being said, you don't need to use a StringVar at all. You can use it, but it's just an extra object you have to manage. You can directly set the displayed string with the configure method anytime you want

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

注意:您不需要调用updateupdate_idletasks

这篇关于让 Pyphons Tkinter 使用不断变化的变量更新标签的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆