0

我正在尝试在 tkinter 中编写一些经过验证的 Entry 类。我在 Python 3.3 上,Anacondas。

在下面的代码中,当我开始在两个条目之一中输入文本时,python 在我输入时将该文本插入到另一个字段中。我不要那个。一个字段应该是经过验证的日期,而另一个应该是经过验证的整数。

我究竟做错了什么?

如果我注释掉所有 e1 行,那么它可以工作。如果我注释掉 e2 行,那么它可以工作。但是,如果我将两者都放在一起,那么它们会以某种方式联系在一起。

import pandas as pd
from tkinter import *


class ValidatedEntry(Entry):

    def __init__(self,*args,**kwargs):
        Entry.__init__(self,*args,**kwargs)

        if 'default_value' in kwargs.keys():
            self.default_value = kwargs['default_value']
        else:
            self.default_value = 0

        self.previous_value = self.default_value            
        self.config(textvariable=self.default_value)

        self.register(self.__validate_entry())        
        self.config(validate='focusout',validatecommand=self.__validate_entry)

    def __validate_entry(self):

        print('validating')
        try:

            self.validation_function(self.get())
            self.previous_value = self.get()
            return True
        except Exception:            
            self.delete(0,END)
            self.insert(0,self.previous_value)
            return False

    def validation_function(self,value):
        print('should we get here?')
        i=int(self.get())
        #raise NotImplemented('This is abstract so you can''t implement it.')        

class IntegerEntry(ValidatedEntry):           

    def validation_function(self,value):
        print('checking int {0}'.format(value))
        i=int(self.get())

class DateEntry(ValidatedEntry):

    def validation_function(self,value):
        print('checking date {0}'.format(value))
        d=pd.datetime.strptime(value,'%Y-%m-%d')


master = Tk()

e1 = IntegerEntry(master)
e1.pack()
e1.focus_set()

e2 = DateEntry(master)
e2.pack()

b = Button(master, text="get", width=10)
b.pack()

mainloop()
4

2 回答 2

1

您不能使用普通的 python 变量作为textvariable属性的值。您需要使用StringVarIntVarBooleanVar的实例DoubleVar。通过使用普通的 python 变量,您可以有效地为两个小部件提供相同的textvariable,这就是您设置一个,另一个也设置的原因。

但是,由于您实际上并没有将textvariable属性用于任何事情,您可以简单地完全删除该选项,您的代码就可以工作。

这条线看起来也很可疑:

self.register(self.__validate_entry())        

它可能没有做你认为它正在做的事情。一方面,它在启动时调用您的 validate_entry 函数,这可能没有做任何有用的事情,因为用户尚未输入任何数据——您只是在验证默认值。其次,调用的唯一原因register是使用它返回的值,而您完全忽略了它返回的值。你应该简单地删除那条线,它没用。

于 2013-08-08T12:24:47.567 回答
0

此代码提供了一个有效的解决方案:

import pandas as pd
from tkinter import *
from tkinter import messagebox


class ValidatedEntry(Entry):

    def __init__(self,master,default_value):
        Entry.__init__(self,master)

        if not self.validate_value(default_value):
            raise ValueError('default_value of wrong type')

        self.previous_value = default_value           
        self.insert(0,default_value)        

        self.config(validate='focusout',validatecommand=self.__validate_entry)

    def __validate_entry(self):

        if self.validate_value(self.get()):
            self.previous_value = self.get()
            return True
        else:
            messagebox.showinfo('Validation Error', 'validation failed - reverting to previous value of {0}'.format(self.previous_value))
            self.delete(0,END)
            self.insert(0,self.previous_value)
            return False

    def validate_value(self,value):
        raise NotImplemented('This is abstract so you can''t implement it.')        

class FloatEntry(ValidatedEntry):

    def validate_value(self,value):
        print('checking float {0}'.format(value))
        try:
            f=float(value)
            return True
        except Exception:
            return False    

class IntegerEntry(ValidatedEntry):

    def validate_value(self,value):
        print('checking int {0}'.format(value))
        try:
            i=int(value)
            return True
        except Exception:
            return False             

class DateEntry(ValidatedEntry):

    def validate_value(self,value):
        print('checking date {0}'.format(value))
        try:
            d=pd.datetime.strptime(value,'%Y-%m-%d')
            return True
        except Exception:
            return False



master = Tk()

e1 = IntegerEntry(master,'0')
e1.pack()
e1.focus_set()

e2 = DateEntry(master,'2013-01-01')
e2.pack()

e3 = FloatEntry(master,'10.0')
e3.pack()

b = Button(master, text="get", width=10)
b.pack()

mainloop()
于 2013-08-08T13:22:24.910 回答