PySimpleGUI/DemoPrograms/Demo_Input_Auto_Complete.py

96 lines
4.0 KiB
Python
Raw Normal View History

import PySimpleGUI as sg
"""
Autocomplete input
Thank you to GitHub user bonklers for supplying to basis for this demo!
There are 3 keyboard characters to be aware of:
* Arrow up - Change selected item in list
* Arrow down - Change selected item in list
* Escape - Erase the input and start over
* Return/Enter - use the current item selected from the list
You can easily remove the ignore case option by searching for the "Irnore Case" Check box key:
'-IGNORE CASE-'
The variable "choices" holds the list of strings your program will match against.
Even though the listbox of choices doesn't have a scrollbar visible, the list is longer than shown
and using your keyboard more of it will br shown as you scroll down with the arrow keys
The selection wraps around from the end to the start (and vicea versa). You can change this behavior to
make it stay at the beignning or the end
Copyright 2021 PySimpleGUI
"""
2018-12-01 20:58:41 +00:00
def main():
# The list of choices that are going to be searched
# In this example, the PySimpleGUI Element names are used
choices = sorted([elem.__name__ for elem in sg.Element.__subclasses__()])
input_width = 20
num_items_to_show = 4
layout = [
[sg.CB('Ignore Case', k='-IGNORE CASE-')],
[sg.Text('Input PySimpleGUI Element Name:')],
[sg.Input(size=(input_width, 1), enable_events=True, key='-IN-')],
[sg.pin(sg.Col([[sg.Listbox(values=[], size=(input_width, num_items_to_show), enable_events=True, key='-BOX-',
select_mode=sg.LISTBOX_SELECT_MODE_SINGLE, no_scrollbar=True)]],
key='-BOX-CONTAINER-', pad=(0, 0), visible=False))]
]
window = sg.Window('AutoComplete', layout, return_keyboard_events=True, finalize=True, font= ('Helvetica', 16))
list_element:sg.Listbox = window.Element('-BOX-') # store listbox element for easier access and to get to docstrings
prediction_list, input_text, sel_item = [], "", 0
while True: # Event Loop
event, values = window.read()
# print(event, values)
if event == sg.WINDOW_CLOSED:
break
# pressing down arrow will trigger event -IN- then aftewards event Down:40
elif event.startswith('Escape'):
window['-IN-'].update('')
window['-BOX-CONTAINER-'].update(visible=False)
elif event.startswith('Down') and len(prediction_list):
sel_item = (sel_item + 1) % len(prediction_list)
list_element.update(set_to_index=sel_item, scroll_to_index=sel_item)
elif event.startswith('Up') and len(prediction_list):
sel_item = (sel_item + (len(prediction_list) - 1)) % len(prediction_list)
list_element.update(set_to_index=sel_item, scroll_to_index=sel_item)
elif event == '\r':
if len(values['-BOX-']) > 0:
window['-IN-'].update(value=values['-BOX-'])
window['-BOX-CONTAINER-'].update(visible=False)
elif event == '-IN-':
text = values['-IN-'] if not values['-IGNORE CASE-'] else values['-IN-'].lower()
if text == input_text:
continue
else:
input_text = text
prediction_list = []
if text:
if values['-IGNORE CASE-']:
prediction_list = [item for item in choices if item.lower().startswith(text)]
else:
prediction_list = [item for item in choices if item.startswith(text)]
list_element.update(values=prediction_list)
sel_item = 0
list_element.update(set_to_index=sel_item)
if len(prediction_list) > 0:
window['-BOX-CONTAINER-'].update(visible=True)
else:
window['-BOX-CONTAINER-'].update(visible=False)
elif event == '-BOX-':
window['-IN-'].update(value=values['-BOX-'])
window['-BOX-CONTAINER-'].update(visible=False)
window.close()
if __name__ == '__main__':
main()