Обновление значения в поле ввода Python TKinter - PullRequest
0 голосов
/ 30 января 2020

Я использую Python 3.8.1 с версией tkinter 8.6.

У меня есть класс GUI, Pressureinput, который принимает данные для имитатора датчика давления. Я хочу, чтобы запись была в единицах кПа (собственные единицы измерения датчика), но я также хочу, чтобы пользователь знал, каков эквивалент пси. Поэтому, когда пользователь обновляет значение kpa, я хочу, чтобы значение psi обновлялось, но я не хочу, чтобы пользователь мог обновлять значение psi вручную. Я использую поле ввода для обоих. Они начинаются со значения по умолчанию 242 кПа.

Я пытаюсь использовать validate="focusout" для запуска события после того, как поле ввода kpa теряет фокус.

Вот мой код, чтобы вы могли увидеть, что Я пытаюсь сделать. По сути, если они вводят что-либо, что не является положительным, даже целым числом, я хочу, чтобы оно автоматически округляло значение в поле ввода, а затем я также хочу, чтобы оно обновляло эквивалент в пси.

Я понимаю, что метод, который я использую с моей pressurevalid функцией, не будет работать, потому что объекты ввода, kpa и psi неизменны и не изменят исходные объекты.

Обратите внимание, что я установил переменные StringVar psitext и kpatext. Однако каждый раз, когда я пытаюсь использовать их в своей функции pressurevalid, я получаю сообщения о том, что их не существует.

Все остальное, что я пробовал, заканчивается ошибками, которые не запускаются, и я думаю, это хотя бы иллюстрирует то, что я хочу сделать:

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)

1 Ответ

1 голос
/ 30 января 2020

Поскольку вы используете StringVar для записей, вы можете настроить трассировку в переменной, чтобы вызывать функцию при каждом изменении значения. Это будет постоянно держать значение обновленным, а не ждать события фокусировки.

Во-первых, вам нужно преобразовать переменные в атрибуты класса, а не делать их локальными переменными:

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

Вам также придется настроить другие места, которые ссылаются на эти переменные:

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

Далее установите трассировку на self.kpatext сразу после создания переменных:

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

И, наконец, напишите метод self.update_psi. Следующий код установит PSI в пустую строку, если текущее значение кПа не может быть преобразовано.

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

Для получения дополнительной информации о аргументах функции trace см. Каковы аргументы для обратных вызовов метода трассировки переменных Tkinter? . В этом примере они нам не нужны, но функция все равно должна их принимать.


Обратите внимание, ваш код определяет self.kpa дважды - один раз без использования textvariable и один раз с. Я не понимаю, почему вы делаете это, учитывая, что второй никогда не добавляется на экран с пакетом / местом / сеткой. Мое решение работает при условии, что вы собираетесь использовать исходный self.kpa.

...