Интерактивная проверка содержимого виджета Entry в tkinter (часть 2 - изменение свойств объекта entry) - PullRequest
0 голосов
/ 29 января 2019

Я пытаюсь использовать процедуру проверки из ответа здесь: Интерактивная проверка содержимого виджета ввода в tkinter

Я хочу изменить цвет фона, проверив тип ввода.К сожалению, я не могу передать указатель на вход в функцию проверки: vcmd = (self.register(self.onValidate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W').Таким образом, я попробовал это:

    self.entry = tk.Entry(self, validate="all")
    self.entry['validatecommand'] = self.onValidate2(self.entry)

Но это работает только один раз.Не могли бы вы объяснить, как лучше всего получить доступ к объекту, из которого вызывается функция проверки (или другая), и почему мое использование validatecommand работает только один раз?

Вот полный код изПриведенная выше ссылка с некоторыми исправлениями:

import tkinter as tk  # python 3.x
# import Tkinter as tk # python 2.x

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        # valid percent substitutions (from the Tk entry man page)
        # note: you only have to register the ones you need; this
        # example registers them all for illustrative purposes
        #
        # %d = Type of action (1=insert, 0=delete, -1 for others)
        # %i = index of char string to be inserted/deleted, or -1
        # %P = value of the entry if the edit is allowed
        # %s = value of entry prior to editing
        # %S = the text string being inserted or deleted, if any
        # %v = the type of validation that is currently set
        # %V = the type of validation that triggered the callback
        #      (key, focusin, focusout, forced)
        # %W = the tk name of the widget

        vcmd = (self.register(self.onValidate),
                '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')
 #       self.entry = tk.Entry(self, validate="key", validatecommand=vcmd)
        self.entry = tk.Entry(self, validate="all")
#        self.entry['validatecommand'] = vcmd
        self.entry['validatecommand'] = self.onValidate2(self.entry)
        self.text = tk.Text(self, height=10, width=40)
        self.entry.pack(side="top", fill="x")
        self.text.pack(side="bottom", fill="both", expand=True)

def onValidate(self, d, i, P, s, S, v, V, W):
        self.text.delete("1.0", "end")
        self.text.insert("end","OnValidate:\n")
        self.text.insert("end","d='%s'\n" % d)
        self.text.insert("end","i='%s'\n" % i)
        self.text.insert("end","P='%s'\n" % P)
        self.text.insert("end","s='%s'\n" % s)
        self.text.insert("end","S='%s'\n" % S)
        self.text.insert("end","v='%s'\n" % v)
        self.text.insert("end","V='%s'\n" % V)
        self.text.insert("end","W='%s'\n" % W)
        self.text.insert("end","W='%s'\n" % W)
        W.config({"background": "Red"})

        # Disallow anything but lowercase letters
        if S == S.lower():
            return True
        else:
            self.bell()
            return False


    def onValidate2(self, entry):
        try:
            entry.config({"background": "White"})
            value = int(entry.get())
            print("Int Value=",value)
#                return int(value)
        except ValueError:
            entry.config({"background": "Red"})

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()

1 Ответ

0 голосов
/ 29 января 2019

Я не могу передать указатель записи в функцию проверки

Вы можете передать имя виджета записи и использовать метод nametowidget tkinter для преобразования этого имени вэкземпляр виджета.

Не могли бы вы объяснить, почему моя команда validate работает только один раз?

Вы неправильно настраиваете команду validate.Рассмотрим этот код:

self.entry['validatecommand'] = self.onValidate2(self.entry)

Приведенный выше код функционально идентичен этому:

result = self.onValidate2(self.entry)
self.entry['validatecommand'] = result

Другими словами, вы немедленно вызываете свою функцию проверки, а затемустановка опции validatecommand на None.для опции validationcommand должно быть установлено значение callable .


Вот рабочий пример того, чего вы пытаетесь достичь.Обычно команда validate должна возвращать True для правильной записи и False для недействительной записи, но я предполагаю, что вы действительно хотите разрешить недопустимые записи и вместо этого просто хотите сделать фон красным.

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

import tkinter as tk

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        vcmd = self.register(self.onValidate)

        for i in range(4):
            entry = tk.Entry(self, validate="all")
            entry.configure(validatecommand=(vcmd, "%W", "%P"))
            entry.pack(side="top", fill="x")

    def onValidate(self, entry_name, new_value):
        entry = self.nametowidget(entry_name)
        entry.configure(background="white")
        try:
            int(new_value)
        except ValueError:
            entry.configure(background="red")
        return True

if __name__ == "__main__":
    root = tk.Tk()
    Example(root).pack(fill="both", expand=True)
    root.mainloop()
...