Limit value in Tkinter login widgets

I need to limit the values โ€‹โ€‹in Entry widgets to just numbers. The way I was implemented:

import numpy as np from Tkinter import *; import tkMessageBox; class window2: def __init__(self,master1): self.panel2=Frame(master1) self.panel2.grid() self.button2=Button(self.panel2,text="Quit",command=self.panel2.quit) self.button2.grid() self.text1=Entry(self.panel2) self.text1.grid() self.text1.bind('<KeyPress>', self.keybind1) self.text1.focus() def keybind1 (self,event): if event.int in np.linspace(0,9,10): print event.int root1=Tk() window2(root1) root1.mainloop() 

I keep getting an error that the Event instance does not have the attribute 'int'. What should I do?

+8
source share
6 answers

This uses the validatecommand command to limit valid user input in tk.Entry strings that can be interpreted as float:

 import tkinter as tk class window2: def __init__(self, master1): self.panel2 = tk.Frame(master1) self.panel2.grid() self.button2 = tk.Button(self.panel2, text = "Quit", command = self.panel2.quit) self.button2.grid() vcmd = (master1.register(self.validate), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W') self.text1 = tk.Entry(self.panel2, validate = 'key', validatecommand = vcmd) self.text1.grid() self.text1.focus() def validate(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name): if value_if_allowed: try: float(value_if_allowed) return True except ValueError: return False else: return False root1 = tk.Tk() window2(root1) root1.mainloop() 

Recommendations:

  • The Tk manual page explains the validate and validatecommand command options. (Thanks to Schlenk for the link).
  • I learned how to do it in Python here .
+15
source

I understand that itโ€™s already quite late for an answer, but I feel that I can give a much simpler answer to this ... it is really quite simple when you understand how it works.

Use the validation feature that comes with the Entry widget.

Suppose self is a widget:

 vcmd = (self.register(self.callback)) w = Entry(self, validate='all', validatecommand=(vcmd, '%P')) w.pack() def callback(self, P): if str.isdigit(P) or P == "": return True else: return False 

You do not need to include all replacement codes: ( '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W' ), only those that you will use are needed.

The Entry widget returns a string, so you need to somehow extract any numbers to separate them from other characters. The easiest way to do this is to use str.isdigit() . This is a handy little tool that is built directly into the Python libraries and does not require additional import, and it identifies any digits (digits) found in the string returned by the Entry widget.

The or P == "" the or P == "" if statement allows you to delete your entire record, without it you cannot delete the last (first in the input field) digit because '%P' returns an empty value and calling your callback to return False . I will not go into details why here.

validate='all' allows focusin focusout evaluate the value of P when focusin , focusout or any key focusout contents of the widget, and therefore, you do not leave any holes for erroneous input of random characters.

In general, to make everything simple. If your callback returns True this will allow you to enter data. If the callback returns โ€œFalse,โ€ it essentially โ€œignoresโ€ keyboard input.

Check out these two links. They explain what each replacement code means and how to implement it.

http://infohost.nmt.edu/tcc/help/pubs/tkinter/web/entry-validation.html http://stupidpythonideas.blogspot.ca/2013/12/tkinter-validation.html

EDIT: This will only take care of what is allowed in the box. However, inside the callback, you can add any P value to any variable of your choice.

+7
source

The answer is almost perfect, just a small addition to delete the entire line. Checking for floats should only be done when inserting text

 def validate_float(self, action, index, value_if_allowed, prior_value, text, validation_type, trigger_type, widget_name): # action=1 -> insert if(action=='1'): if text in '0123456789.-+': try: float(value_if_allowed) return True except ValueError: return False else: return False else: return True 
+5
source

I also had to deal with the original insertion register. This is what I came across:

  def _checkNumberOnly(self, action, value_if_allowed): if action != '1': return True try: return value_if_allowed.isnumeric() except ValueError: return False vcmd = (self.register(self._checkNumberOnly), '%d', '%P') self.port = ttk.Entry(self, width=35, validate='key', validatecommand=vcmd) 

Therefore, he checks the following:

  self.port.insert(0, '6379') 

I'm not sure what catch is required, due to isnumeric() not indicating that it throws an exception.

+1
source

I am new to python and Tkinker, but this works best for me:

  def keybind1 (self,event): v = event.char try: v = int(v) except ValueError: if v!="\x08" and v!="": return "break" 

v = int(v) launches a ValueError on any key other than the numeric keys, and if v!="\x08 and v!="":" operators still allow backspace mode, ("\x08") and delete, arrow, home, end, etc. (which have event.char of "" ). The break command stops writing an unwanted character to the input field.

0
source

if you are dealing with locales that have a comma as a decimal point:

 locale.setlocale(locale.LC_ALL,'de_DE.UTF-8') # German 

 vcmd = (self.root.register(self.entry_numericonly), '%d', '%P') 

 self.my_float_entry = tk.Entry(self.root, ... , validate='key', validatecommand=vcmd) 

 def entry_numericonly(self, action, value_if_allowed): if(action == "1"): try: loc_float = locale.atof(value_if_allowed) loc_float_format = locale.format("%f", loc_float) try: loc_same_length = loc_float_format[:len(value_if_allowed)] return value_if_allowed == loc_same_length except: return False except: return False else: return True 
0
source

Source: https://habr.com/ru/post/906577/


All Articles