简体   繁体   English

更新 Python TKinter 输入框中的值

[英]Updating a value in a Python TKinter Entry Box

I'm using Python 3.8.1 with tkinter version 8.6.我正在使用 Python 3.8.1 和 tkinter 8.6 版。

I have a GUI class, Pressureinput , which takes in input for a pressure sensor simulator.我有一个 GUI 类Pressureinput ,它接收压力传感器模拟器的输入。 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.我希望条目以 kPa 为单位(传感器的本机单位),但我也希望用户知道 psi 等效值是多少。 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.因此,当用户更新 kpa 值时,我希望 psi 值更新,但我不希望用户能够手动更新 psi 值。 I'm using an entry box for both.我正在为两者使用一个输入框。 They start with a default of 242 kPa.它们以默认值 242 kPa 开始。

I'm trying to use validate="focusout" to trigger an event after the kpa entry box loses focus.我正在尝试使用validate="focusout"在 kpa 输入框失去焦点后触发事件。

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.基本上,如果他们输入的任何内容不是正数,甚至不是整数,我希望它自动舍入输入框中的值,然后我还希望它更新 psi 等效值。

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.我意识到我与pressurevalid函数一起使用的方法将不起作用,因为 entrybox 对象 kpa 和 psi 是不可变的,它不会更改原始对象。

Note that I've set up the StringVar variables psitext and kpatext .请注意,我已经设置了 StringVar 变量psitextkpatext Every time I try to use them in my pressurevalid function, however, I get errors saying they don't exist.然而,每次我尝试在我的pressurevalid函数中使用它们时,我都会收到错误消息,说它们不存在。

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.由于您使用StringVar作为条目,您可以在变量上设置跟踪以在值更改时调用函数。 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上设置跟踪:

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

And finally, write the method self.update_psi .最后,编写方法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.如果无法转换 kPa 的当前值,以下代码会将 PSI 设置为空字符串。

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?有关跟踪函数的参数是什么的更多信息,请参阅Tkinter 变量跟踪方法回调的参数什么? . . 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.请注意,您的代码定义了self.kpa两次——一次不使用textvariable ,一次使用。 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.我的解决方案假设原始self.kpa是您打算使用的那个。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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