-5

I have the need with tkinter python, to define an entry field that only accepts a float field with 8 integers and 2 decimals, perhaps with an error message if it does not respect the format 8.2. You can help me define a format for this field.

furas
  • 134,197
  • 12
  • 106
  • 148
pdecaro
  • 39
  • 1
  • 7
  • 1
    you mean 8 **digits** and 2 decimals ? – Pac0 Dec 27 '17 at 07:52
  • 1
    you can get string, split using dot and then check both parts for length and digits. – furas Dec 27 '17 at 07:53
  • 1
    Welcome to Stack Overflow, please try searching your problem before posting. See https://stackoverflow.com/questions/1018729/python-tkinter-text-entry-validation for basic validation in tkinter. And https://stackoverflow.com/questions/8579267/validating-a-text-field-containing-a-float-is-a-valid-percentage-value should give you a good starting place for the validation logic. – weirdev Dec 27 '17 at 07:53

1 Answers1

1

Entry has options validate= and validatecommand= which you can see in Interactively validating Entry widget content in tkinter

There is also A Validating Entry Widget

But you can also bind event <KeyRelease> to execute function which you can use to check value in Entry.

I split text using dot. If I get more then 2 parts then there was more then 2 dots.

After that I check second part if it exists, is not empty, has only digits and is not longer than 8 chars. Similar way I check first part.

When string is not valid then I only print message in console but you could do something more - you can display messagebox or replace text in Entry.

import tkinter as tk

def check(event):
    text = event.widget.get()
    print('text:', text)

    parts = text.split('.')
    parts_number = len(parts)

    if parts_number > 2:
        print('too much dots')

    if parts_number > 1 and parts[1]: # don't check empty string
        if not parts[1].isdecimal() or len(parts[1]) > 2:
            print('wrong second part')

    if parts_number > 0 and parts[0]: # don't check empty string
        if not parts[0].isdecimal() or len(parts[0]) > 8:
            print('wrong first part')

root = tk.Tk()

e = tk.Entry(root)
e.pack()
e.bind('<KeyRelease>', check)

root.mainloop()

EDIT: example with validate= - based on example from second link above.

Function check() mostly without changes. It only uses return True/False instead of printing messages. It blocks invalid values.

import tkinter as tk

def check(d, i, P, s, S, v, V, W):
    #print("d='%s'" % d)
    #print("i='%s'" % i)
    #print("P='%s'" % P)
    #print("s='%s'" % s)
    #print("S='%s'" % S)
    #print("v='%s'" % v)
    #print("V='%s'" % V)
    #print("W='%s'" % W)    

    text = P  #e.get()
    print('text:', text)

    parts = text.split('.')
    parts_number = len(parts)

    if parts_number > 2:
        #print('too much dots')
        return False

    if parts_number > 1 and parts[1]: # don't check empty string
        if not parts[1].isdecimal() or len(parts[1]) > 2:
            #print('wrong second part')
            return False

    if parts_number > 0 and parts[0]: # don't check empty string
        if not parts[0].isdecimal() or len(parts[0]) > 8:
            #print('wrong first part')
            return False

    return True

# --- main ---

root = tk.Tk()

vcmd = (root.register(check), '%d', '%i', '%P', '%s', '%S', '%v', '%V', '%W')

e = tk.Entry(root, validate='key', validatecommand=vcmd)
e.pack()

root.mainloop()
furas
  • 134,197
  • 12
  • 106
  • 148
  • 1
    Thanks for help, but that's not what I wanted. in practice it must be possible to insert a numeric only field, with a maximum of 8 integers and 2 decimals. must not allow entry of alphabetic characters. in practice, if I enter 12352.45 at the exit of the field, its format will be 12.352,45. Thank you – pdecaro Dec 27 '17 at 13:15
  • 1
    you can always replace text in entry if new char is not numeric. You can also try to use `validatecommand=` to block some keys. But you have to manually check if string has correct format - similar to my example, or you can try to use regex to check format. – furas Dec 27 '17 at 13:19
  • 1
    I added example with `validate=` – furas Dec 27 '17 at 15:30
  • 1
    Thanks is what I was looking for, you can add that when you leave the focus of the field, update the value with the points of the hundreds. eg : 12345678,69 12.245.678,58 Thank you – pdecaro Dec 27 '17 at 19:38
  • 1
    if I add points of the hundreds then it will no match to existing rules and there will be problem to edit it later - it would need more work. You would have to convert it back to version without points when you focus in or change all rules. – furas Dec 27 '17 at 21:23