0

tkinter でいくつかの検証済みの Entry クラスを作成しようとしています。私はPython 3.3、アナコンダを使用しています。

次のコードでは、2 つのエントリのいずれかにテキストを入力し始めると、Python はそのテキストをもう一方のフィールドに挿入します。私はそれを望んでいません。1 つのフィールドは検証済みの日付で、もう 1 つのフィールドは検証済みの整数である必要があります。

私は何を間違っていますか?

すべての 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

textvariable属性の値として通常の python 変数を使用することはできません。StringVarIntVarBooleanVarまたはのインスタンスを使用する必要がありますDoubleVar。通常の python 変数を使用することで、効果的に両方のウィジェットに同じ を与えることになりますtextvariable。そのため、一方を設定すると、もう一方も設定されます。

ただし、実際にはtextvariable属性を何にも使用していないため、オプションを完全に削除するだけでコードが機能します。

この行も疑わしいようです:

self.register(self.__validate_entry())        

それはおそらくあなたが思っていることをしていないでしょう。1 つは、起動時に 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 に答える