Come passare un valore a una voce validatecommand

Sep 15 2020

Sto convalidando un modulo in tkinter usando validatecommand. Ci sono due voci, una dovrebbe accettare solo numeri interi e l'altra float.
Ecco il codice di base:

import tkinter as tk
class Form(tk.Tk):
    def __init__(self):
        tk.Tk.__init__(self)
        validCmd1 = (self.register(self.val1), "%P")
        validCmd2 = (self.register(self.val2), "%P")
        self.lab1 = tk.Label(self, text = "Float:")
        self.lab1.grid(row = 1, column = 0, padx = 10, pady = 10)
        self.ent1 = tk.Entry(self, validate = "key", validatecommand = validCmd1)
        self.ent1.grid(row = 1, column = 1)
        self.lab2 = tk.Label(self, text = "Integer:")
        self.lab2.grid(row = 2, column = 0, padx = 10, pady = (0,10))
        self.ent2 = tk.Entry(self, validate = "key", validatecommand = validCmd2)
        self.ent2.grid(row = 2, column = 1)
    def val1(self, value):
        try:
            float(value)
        except:
            return False
        else:
            return True
    def val2(self, value):
        try:
            int(value)
        except:
            return False
        else:
            return True
app = Form()
app.mainloop()

Invece di scrivere due diverse funzioni per due attività molto simili, ho provato a passare un numero intero al comando validate (1 per float, 2 per intero). Ho provato a usare lambda per passare valori alle funzioni di convalida, prima sulla parte self.register: self.register(lambda: self.val1(1))ma questo ha dato TypeError: <lambda>() takes 0 positional arguments but 1 was givene la seconda volta ho provato a usare lambda sul comando validatecommand: validatecommand = lambda: validCmd1(1)che dà TypeError: 'tuple' object is not callable.
È possibile passare valori a un comando di convalida?

Risposte

1 BryanOakley Sep 15 2020 at 20:31

L' validatecommandopzione accetta una tupla che può avere tutti gli argomenti desiderati. Ad esempio, se vuoi passare un numero intero è facile come questo:

validCmd1 = (self.register(self.val), 1, "%P")
validCmd2 = (self.register(self.val), 2, "%P")

def val(self, arg, value):
    print(f"val1 arg='{arg}' value='{value}'")
    ...

A volte è più facile capire se si separa la registrazione del comando dal valore passato a validatecommand. Per esempio:

vcmd = self.register(self.val)
...
self.ent1 = tk.Entry(..., validatecommand = (vcmd, 1, "%P"))
self.ent2 = tk.Entry(..., validatecommand = (vcmd, 2, "%P"))