Pysimplegui: [Question] My question is how to make an InputText to only accept integers

Created on 10 Aug 2020  路  9Comments  路  Source: PySimpleGUI/PySimpleGUI

Type of Issues (Question)

Operating System (all)

Python version (3.8)

PySimpleGUI Port and Version (4.19.0)

I am wondering if/how I can set an InputText to only accept numbers/integers. I am relatively new to PySimpleGUI but am coming over from other GUI modules like PyQt, appJar, remi and the like.

Most helpful comment

Here for your reference, not sure is it good for you.

import PySimpleGUI as sg

def valid(text):
    if len(text)==1 and text in '+-':
        return True
    else:
        try:
            number = float(text)
            return True
        except:
            return False

font = ('Helvetica', 20)
layout = [[sg.InputText('', size=(40, 1), font=font, key='-INPUT-', enable_events=True)],
          [sg.Button('Exit', font=font)]]

window = sg.Window('Test', layout)

while True:

    event, values = window.read()
    print(event, values)
    if event in (sg.WINDOW_CLOSED, 'Exit'):
        break
    elif event == '-INPUT-':
        text = values['-INPUT-']
        if not valid(text):
            window['-INPUT-'].update(value=text[:-1])

window.close()

All 9 comments

Here for your reference, not sure is it good for you.

import PySimpleGUI as sg

def valid(text):
    if len(text)==1 and text in '+-':
        return True
    else:
        try:
            number = float(text)
            return True
        except:
            return False

font = ('Helvetica', 20)
layout = [[sg.InputText('', size=(40, 1), font=font, key='-INPUT-', enable_events=True)],
          [sg.Button('Exit', font=font)]]

window = sg.Window('Test', layout)

while True:

    event, values = window.read()
    print(event, values)
    if event in (sg.WINDOW_CLOSED, 'Exit'):
        break
    elif event == '-INPUT-':
        text = values['-INPUT-']
        if not valid(text):
            window['-INPUT-'].update(value=text[:-1])

window.close()

Jason's got it right. This is how input validation is done in PySimpleGUI. There is a Cookbook Recipe that shows you one way of doing this that you'll find here:
https://pysimplegui.readthedocs.io/en/latest/cookbook/#recipe-input-validation

Generally speaking, the quick and dirty way is to use a simple try/except block. Let Python tell you if it's an int.

import PySimpleGUI as sg

layout = [  [sg.Text('Input only int point numbers')],
            [sg.Input(key='-IN-', enable_events=True)],
            [sg.Button('Exit')]  ]

window = sg.Window('Int input validation', layout)

while True:
    event, values = window.read()
    if event in (sg.WIN_CLOSED, 'Exit'):
        break
    # if last character in input element is invalid, remove it
    if event == '-IN-' and values['-IN-']:
        try:
            in_as_int = int(values['-IN-'])
        except:
            if not (len(values['-IN-']) == 1 and values['-IN-'][0] == '-'):
                window['-IN-'].update(values['-IN-'][:-1])
window.close()

Thank you both!!! I am trying out PySimpleGUI with an app I already wrote with appJar and was just trying to find an equivalent to its NumericEntry()

I will give that a try and see how well it works.

both of your ways work very well!!! Thank you very very much. Now to just add that to about 100 inputs (for loop, here i come!)

I know this is probably python 101, using this implementation to validate an input text box. How would/could I make this more generic to handl over 100 boxes?

It depend on how you get input for 100 boxes !

For example, you have 100 boxes in window at the same time, you can set key of each box start with 'INT_', like 'INT_01', 'INT_02', ...

layout = [[sg.Input(key=f'INT_{j}{i}', enable_events=True) for i in range(10)] for j in range(10)]

then the loop event handler can be

elif event.startswith('INT_'):
    ...

Difference case maybe with different way to go !

You can also use tuples as keys.... key=(i,j).

Or if you don't need a row, col kind of thing and it's just 100 inputs in a row, but you want to know it's an input.... it could be

layout = [[sg.Input(key=('INT', i), enable_events=True) for i in range(100)]]

# event loop...
if hasattr(event, tuple):     # if you will have both strings and tuples as keys, check for tuple first
   if event[0] == 'INT':         # You'll know this is one of the inputs to check for int only
      # do the int check / fixup here

It's the exact same kind of mechanism Jason has shown, but with tuples instead of strings. I do like the string version as it requires only 1 check.

Oh, actually, you can safely use a [ ] index into both a string and a tuple, so you maybe don't check for the tuple, but instead check for the first position being "INT". If it's a string, event[0] will be a single character.

if event[0] == 'INT':         # You'll know this is one of the inputs to check for int only
   # do the int check / fixup here

I know this is probably python 101, using this implementation to validate an input text box. How would/could I make this more generic to handl over 100 boxes?

If useful, I have empowered the code above reported to check from a list of keys if the input is a float or int:

import PySimpleGUI as sg

def valid_float(text):
    if len(text)==1 and text in '+-':
        return True
    else:
        try:
            number = float(text)
            return True
        except:
            return False

def valid_int(text):
    if len(text)==1 and text in '+-':
        return True
    else:
        try:
            number = int(text)
            return True
        except:
            return False

font = ('Helvetica', 20)
layout = [[sg.InputText('', size=(40, 1), font=font, key='-INPUT-', enable_events=True)],
          [sg.InputText('', size=(40, 1), font=font, key='-INPUT2-', enable_events=True)],
          [sg.InputText('', size=(40, 1), font=font, key='-INPUT3-', enable_events=True)],
          [sg.Button('Exit', font=font)]]

window = sg.Window('Test', layout)

while True:

    event, values = window.read()
    if event in (sg.WINDOW_CLOSED, 'Exit'):
        break

    # check input(s): float
    check_float=['-INPUT-','-INPUT2-'] # a list with key(s) to check
    for key in check_float:
        if event == key:
            text = values[key]
            if not valid_float(text):
                window[key].update(value=text[:-1])

    # check input(s): int
    check_int=['-INPUT3-'] # a list with key(s) to check
    for key in check_int:
        if event == key:
            text = values[key]
            if not valid_int(text):
                window[key].update(value=text[:-1])

window.close()
Was this page helpful?
0 / 5 - 0 ratings