-1

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)

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.

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.

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.

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()
Ewan321
  • 21
  • 5
  • or this. http://stackoverflow.com/questions/2603169/update-tkinter-label-from-variable – Lafexlos Jan 15 '16 at 12:16
  • 4
    or or http://stackoverflow.com/questions/1918005/making-python-tkinter-label-widget-update actually, one of these last two also should be dupehammered. – Lafexlos Jan 15 '16 at 12:18
  • My point is that these all recommend using .update_idletasks(), which I haven't managed to get to work. – Ewan321 Jan 15 '16 at 12:19
  • No, they are not recommending that. First one does the trick even without `StringVar()`. Just please read answers and compare how they are using `Label(root, text = var, ...)` parts. – Lafexlos Jan 15 '16 at 12:21

1 Answers1

2

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)

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)

Note: you do not need to call update or update_idletasks

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685