2017-10-21 142 views
1

我希望用戶能夠在Spinbox小部件中輸入整數值。如果輸入的值不是整數或是Spinbox限制外的整數,只要Spinbox失去焦點,Spinbox內容中的值必須恢復爲默認值。tkinter中的小部件驗證

在示例代碼中,我使用Entry小部件僅用於Spinbox可能會失去焦點。

如果用戶回到Spinbox輸入新值,則他的輸入未驗證。 我確認馬爾科姆在Interactively validating Entry widget content in tkinter中的評論,只要此命令更新小部件的值,就會清除validatecommand=command功能。

有沒有辦法讓重複驗證的Spinbox中輸入的值不只是一次?

from tkinter import * 


class GUI: 

    def __init__(self): 
     # root window of the whole program 
     self.root = Tk() 
     self.root.title('Validate Spinbox') 

     # registering validate and invalid commands 
     validate_cmd = (self.root.register(self.validate), '%P') 
     invalid_cmd = (self.root.register(self.invalid)) 

     # creating a Label 
     items_lbl = Label(self.root, text="# of items (5-10):") 
     items_lbl.grid(row=0, column=0) 

     # creating a Spinbox widget 
     self.items_var = StringVar() 
     self.items_var.set(7) 
     items_count = Spinbox(self.root, textvariable=self.items_var, 
           from_=5, to=10, width=4, validate='focusout', 
           validatecommand=validate_cmd, 
           invalidcommand=invalid_cmd) 
     items_count.grid(row=0, column=1) 

     # creating an Entry widget 
     self.entry_var = StringVar() 
     self.entry_var.set("Input some text here") 
     text_entry = Entry(self.root, textvariable=self.entry_var) 
     text_entry.grid(row=1, column=0) 

    def validate(self, entry): 
     try: 
      value = int(entry) 
      valid = value in range(5, 11) 
     except ValueError: 
      valid = False 
     if not valid: 
      self.root.bell() 
     return valid 

    def invalid(self): 
     self.items_var.set(7) 


if __name__ == '__main__': 
    main_window = GUI() 
    mainloop() 
+1

'validatecommand'停留OK,這是'驗證「參數綁定到」重點「事件,得到重置 – PRMoureu

+0

@PRMoureu:謝謝你的迴應!有沒有辦法重置** validate **參數?最優選的是:因爲我是Python新手,如果您可以修改我的代碼,我會非常感激。 – nkana

回答

1

我發現了一個很好的解釋這裏(本章的最後一段驗證):

http://stupidpythonideas.blogspot.fr/2013/12/tkinter-validation.html

如果您validatecommand(或invalidcommand)直接或間接地修改條目(例如,通過在其StringVar上調用set),只要函數返回,驗證就會被禁用。 (這是Tk如何防止無限循環的驗證觸發另一個驗證。)您必須重新打開它(通過調用config)。但是你不能從函數內部做到這一點,因爲它在函數返回後被禁用。

但是您需要應用一些更改才能使用此技巧。

你需要讓Spinbox實例屬性,與self

self.items_count = Spinbox(self.root, textvariable=self.items_var, 
         from_=5, to=10, width=4, validate='focusout', 
         validatecommand=validate_cmd, 
         invalidcommand=invalid_cmd) 
self.items_count.grid(row=0, column=1) 

然後你就可以調用self.items_count.after_idle(...)validate方法中:

def validate(self, entry): 
    try: 
     value = int(entry) 
     valid = value in range(5, 11) 
    except ValueError: 
     valid = False 
    if not valid: 
     self.root.bell() 
     self.items_count.after_idle(lambda: self.items_count.config(validate='focusout')) 
    return valid 
+1

非常感謝你!問題解決了!!!!!! – nkana

+0

很高興幫助,我也學到了一些東西,這要感謝這個博客的作者 – PRMoureu