I need to restrict the values in the Entry widget to numbers only. The way I implemented is:
import numpy as np
from Tkinter import *;
import tkMessageBox;
I realize this is quite late for an answer but feel that I can give a lot simpler answer to this... it is really quite simple once you understand how it works.
Use the validating feature that comes with the Entry
widget.
Lets assume 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 don't need to include all of the substitution codes: ('%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W'
), only the ones you'll use are necessary.
The Entry
widget returns a string so you will have to somehow extract any digits in order to separate them from other characters. The easiest way to do this is to use str.isdigit()
. This is a handy little tool built right into python's libraries and needs no extra importing and it will identify any numerics (digits) that it finds from the string that the Entry
widget returns.
The or P == ""
part of the if statement allows you to delete your entire entry, without it, you would not be able to delete the last (1st in entry box) digit due to '%P'
returning an empty value and causing your callback to return False
. I won't go into detail why here.
validate='all'
allows the callback to evaluate the value of P
as you focusin
, focusout
or on any key
stroke changing the contents in the widget and therefore you don't leave any holes for stray characters to be mistakenly entered.
In all, to make things simple. If your callback returns True
it will allow data to be entered. If the callback returns 'False` it will essentially 'ignore' keyboard input.
Check out these two references. They explain what each substitution code means and how to implement them.
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. You can, however, inside the callback, add whatever value P
has to any variable you wish.
I had to deal with an initial insert case as well. This is what I have ended up with:
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 it validates for the following:
self.port.insert(0, '6379')
I'm not sure that the catch is needed, due to isnumeric()
not stating it raises an exception.
The answer is almost perfect, just a little addition to allow for deleting the whole string. The check for floats should be done only 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
if you are dealing with locales that have a comma as 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
I'm 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"
The v = int(v)
triggers a ValueError
on any key other then number keys, but
the if v!="\x08
and v!="":"
statement still allows the backspace, ("\x08")
, and delete, arrow, home, end, etc. keys, (which have an event.char
of ""
), to work normally - otherwise the break
command stops the entry of other characters into the Entry widget.
This uses validatecommand
to restrict valid user input in the tk.Entry
to strings which can be interpreted as floats:
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()
References:
validate
and validatecommand
options. (Thanks to schlenk for the link).