简体   繁体   中英

Updating a value in a Python TKinter Entry Box

I'm using Python 3.8.1 with tkinter version 8.6.

I have a GUI class, Pressureinput , which takes in input for a pressure sensor simulator. I want the entry to be in units of kPa (native units of the sensor) but I also want the user to know what the psi equivalent is. So, when the user updates the kpa value, I want the psi value to update, but I don't want the user to be able to update the psi value manually. I'm using an entry box for both. They start with a default of 242 kPa.

I'm trying to use validate="focusout" to trigger an event after the kpa entry box loses focus.

Here's my code so you can see what I'm trying to do. Basically, if they enter anything that's not a positive, even integer, I want it to automatically round the value in the entry box and then I also want it to update the psi equivalent.

I realize the method I'm using with my pressurevalid function won't work because the entrybox objects, kpa and psi are immutable and it won't change the original objects.

Note that I've set up the StringVar variables psitext and kpatext . Every time I try to use them in my pressurevalid function, however, I get errors saying they don't exist.

Everything else I've tried ends up with errors that won't run, and I think this at least illustrates what I want to do:

import tkinter as tkGUI

#global constants for conversion
global psi2kpa
global kpa2psi
psi2kpa = 6.894757
kpa2psi = 1 / psi2kpa

class Pressureinput(tkGUI.Frame):

    def __init__(self,parent):
            tkGUI.Frame.__init__(self,parent)
            self.parent = parent
            self.initialize()

    def initialize(self):

            kpatext = tkGUI.StringVar()
            psitext = tkGUI.StringVar()

            self.IDlabel = tkGUI.Label(self,text="Sensor ID (hex):")
            self.IDlabel.grid(row=0, column=0)
            self.ID = tkGUI.Entry(self)
            self.ID.insert(0,"AABBCCDD")
            self.ID.grid(row=0, column=1)

            self.kpalabel = tkGUI.Label(self,text="Pressure (kPa):")
            self.kpalabel.grid(row=1, column=0)
            self.kpa = tkGUI.Entry(self)
            self.kpa.insert(0,242)
            self.kpa.grid(row=1, column=1)

            self.psilabel = tkGUI.Label(self,text="Pressure (PSI):")
            self.psilabel.grid(row=2, column=0)
            self.psi = tkGUI.Entry(self, textvariable=psitext)
            self.psi.insert(0,float(self.kpa.get())*kpa2psi)
            self.psi.grid(row=2, column=1)
            self.psi.config(state='disabled') #state = 'normal' to restore

            vpressure = self.register(self.pressurevalid(self.kpa,self.psi))
            self.kpa = tkGUI.Entry(self, textvariable=kpatext, validate="focusout", validatecommand=vpressure)

            self.sendbutton = tkGUI.Button(self,text="Send Transmission",state="disabled",command=self.send_data)
            self.sendbutton.grid(row=9,columnspan=2)

    def pressurevalid(self,kpa,psi):
            if len(kpa.get()) < 1:
                    kpa.delete(0,tkGUI.END)
                    kpa.insert(0,"0");
            elif 2*int(round(float(kpa.get())) / 2) != int(kpa.get()):
                    kpa.delete(0,tkGUI.END)
                    kpa.insert(0,2 * int(round(float(kpa.get()))) / 2)

            psi.config(state='normal')
            psi.delete(0,tkGUI.END)
            psi.insert(0,float(kpa.get())*kpa2psi)
            psi.config(state='disabled')
            return True

    def send_data(self):
            ID = int(self.ID.get(),16)
            pressure = int(self.kpa.get())
            if pressure >= 510:
                    pressure = 255
            else:
                 pressure = int(round(pressure/2))

            sendstring =  str(ID) + "," + str(function_code) + "," + str(pressure)
            print (sendstring)

Since you are using a StringVar for the entries, you can set up a trace on the variable to call a function whenever the value changes. This will constantly keep the value updated rather than waiting for a focus-out event.

First, you need to convert the variables into attributes of the class rather than making them local variables:

self.kpatext = tkGUI.StringVar()
self.psitext = tkGUI.StringVar()

You'll also have to adjust other places which reference these variables:

self.psi = tkGUI.Entry(..., textvariable=self.psitext, ...)
self.kpa = tkGUI.Entry(..., textvariable=self.kpatext, ...)

Next, set up a trace on self.kpatext right after you create the variables:

self.kpatext.trace("w", self.update_psi)

And finally, write the method self.update_psi . The following code will set the PSI to an empty string if the current value of kPa isn't able to be converted.

def update_psi(self, *args):
    try:
        psi = int(self.kpatext.get())*kpa2psi
        self.psitext.set(psi)
    except Exception as e:
        self.psitext.set("")

For more information on what the arguments to the trace function are, see What are the arguments to Tkinter variable trace method callbacks? . In this example we don't need them, but the function still must accept them.


Note, your code defines self.kpa twice -- once without using textvariable and once with. I don't understand why you're doing that given that the second one is never added to the screen with pack/place/grid. My solution works under the assumption that the original self.kpa is the one that you intend to use.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM