I use import pySimpleGUI as ps
(started 10 years ago, but about 3 weeks serious experience) Python programming experience
(15 years, entry level) Programming experience overall
yes, but they suck Have used another Python GUI Framework (tkinter, Qt, etc) previously (yes/no is fine)?
Is there a way to delete the default text when I click on the text entry box? For example, using terrible pseudocode:
layout =
line one: text = PLEASE ENTER YOUR NAME BELOW
line two: text entry = [ default text = NAME ]
Basically before I click on the text entry box, I want it to show NAME. But once I click on it, instead of letting me edit the default text, "NAME", I want it to instantly delete the word NAME and let me type in stuff. And as a bonus, if it's not difficult, if the textbox is left blank, the word NAME shows up again, preferably in like a grey color. I know it's probably a hassle to do all that, so just the ability to force the word NAME to go away would be more than awesome by itself.
A short program that isolates and demonstrates the problem (i.e. please don't paste a link to your 400 line program.... instead paste your 10 line program in full).
Yes, it is a pain to narrow down problems, but it's part of the debugging process. Help me help you by providing something that can be executed so that work on getting you a fix or a workaround can immediately begin.
This pre-formatted code block is all set for you to paste in your bit of code:
import PySimpleGUI as sg
print(sg)
print(sg.version)
## Paste your code here
layout = [ inputText("deleteMeOnClick",key = 'myInput')]
window = sg.Window("A title",layout)
event,values = window(read)
I think that should be sufficient enough to show a text entry with default text. There's no button since that's unrelated. Also, wanted to give a shout out again for all the awesome stuff you do. I'm that one persistent guy from Reddit.
There's no binding for FocusIn in PySimpleGUI. Maybe it need youself binding handler.
Maybe there's another quick way from PySimpleGUI, at least I don't know.
Anyway, try this:
import PySimpleGUI as sg
def focus_control(event):
if window['myInput'].get() == '':
window['myInput'].update(value=default_text)
window['myInput'].update(select=True)
# window.refresh()
return None
default_text = "deleteMeOnClick"
layout = [[sg.InputText(default_text, size=(50, 1), key='myInput')],
[sg.InputText(default_text, size=(50, 1), enable_events=True, key='myInput2')],
[sg.Button("OK")],
[sg.Text('', size=(50, 1), key='Message')]]
window = sg.Window("A title", layout, finalize=True)
window['myInput'].Widget.bind("<FocusIn>", focus_control)
window['myInput'].update(select=True)
while True:
event, values = window.read()
print(event, values)
if event == None:
break
elif event == 'OK':
window['Message'].update(value=values['myInput'])
window.close()
This demo shows how to bind events including focus. Not sure if it's what you're looking for or not....
https://pysimplegui.trinket.io/demo-programs#/advanced/focus-events-routing-custom-events-through-window-read
Here's the code posted there:
import PySimpleGUI as sg
"""
Extending PySimpleGUI using the tkinter event bindings
The idea here is to enable you to receive tkinter "Events" through the normal place you
get your events, the window.read() call.
Both elements and windows have a bind method.
window.bind(tkinter_event_string, key) or element.bind(tkinter_event_string, key_modifier)
First parameter is the tkinter event string. These are things like <FocusIn> <Button-1> <Button-3> <Enter>
Second parameter for windows is an entire key, for elements is something added onto a key. This key or modified key is what is returned when you read the window.
If the key modifier is text and the key is text, then the key returned from the read will be the 2 concatenated together. Otherwise your event will be a tuple containing the key_modifier value you pass in and the key belonging to the element the event happened to.
"""
sg.theme('Dark Blue 3')
layout = [ [sg.Text('Move mouse over me', key='-TEXT-')],
[sg.In(key='-IN-')],
[sg.Button('Right Click Me', key='-BUTTON-'), sg.Button('Exit')] ]
window = sg.Window('Window Title', layout, finalize=True)
window.bind('<FocusOut>', '+FOCUS OUT+')
window['-BUTTON-'].bind('<Button-3>', '+RIGHT CLICK+')
window['-TEXT-'].bind('<Enter>', '+MOUSE OVER+')
window['-TEXT-'].bind('<Leave>', '+MOUSE AWAY+')
window['-IN-'].bind('<FocusIn>', '+INPUT FOCUS+')
while True: # Event Loop
event, values = window.read()
print(event, values)
if event in (None, 'Exit'):
break
window.close()
The idea with the bind methods is to continue to route all events through window.read so that the user is not getting any callbacks directly.
This is a very crude focus example. It needs quite a bit of work to get you exactly what you're after because tkinter gives you focus in events like crazy for a window. Tabbing from the Input field to the button for example sends focus in events. You may have to look first for losing focus? Not sure. It's a highly complex kind of case and one that PySimpleGUI may not be able to deliver on. Hopefully you can find a way, but PySimpleGUI is built for the 80% of the use cases, not 100%.
import PySimpleGUI as sg
layout = [ [sg.T('Input field below will be cleared any time window gets focus. Note, windows start with focus')],
[sg.In('Default text', key='-IN-')],
[sg.Button('Button'), sg.Button('Exit')] ]
window = sg.Window('Window Title', layout, finalize=True)
window.bind('<FocusIn>', '+FOCUS IN+')
while True: # Event Loop
event, values = window.read()
print(event, values)
if event in (sg.WIN_CLOSED, 'Exit'):
break
if event == '+FOCUS IN+':
window['-IN-'].update('')
window.close()
EDIT: I have a super cluttered desktop. I decided to move the file into a folder and it began working. I bet I have a stray pysimplegui.py sitting around in my 200 or so icons, so that was probably causing the issue. The file runs now. It doesn't auto-delete the text, but I think that's intentional, right? It highlights the text and then when I start typing, it overwrites it as expected. A clever solution, thanks! I feel like both your and Mike's solutions both have their own situations in which one might be better than the other, but both definitely do the trick.
I do want to say that this might be one of those features that people will love to use as a default feature, but that they just don't realize it yet. I know a lot of websites offer functionality like this where it has default text that gets highlighted/deleted upon focus/clicking. You both have working code, might be a useful function to have as a boolean such as "sg.InputText(default_text, size=(50, 1), key = "myInput", defaultOverwrite = True)?
There's no binding for FocusIn in PySimpleGUI. Maybe it need youself binding handler.
Maybe there's another quick way from PySimpleGUI, at least I don't know.
Anyway, try this:import PySimpleGUI as sg def focus_control(event): if window['myInput'].get() == '': window['myInput'].update(value=default_text) window['myInput'].update(select=True) # window.refresh() return None default_text = "deleteMeOnClick" layout = [[sg.InputText(default_text, size=(50, 1), key='myInput')], [sg.InputText(default_text, size=(50, 1), enable_events=True, key='myInput2')], [sg.Button("OK")], [sg.Text('', size=(50, 1), key='Message')]] window = sg.Window("A title", layout, finalize=True) window['myInput'].Widget.bind("<FocusIn>", focus_control) window['myInput'].update(select=True) while True: event, values = window.read() print(event, values) if event == None: break elif event == 'OK': window['Message'].update(value=values['myInput']) window.close()
Thank you!
I don't know why, but Python is not liking that code.
\Desktop\emptyDefault.py", line 11, in <module>
layout = [[sg.InputText(default_text, size=(50, 1), key='myInput')],
TypeError: __init__() got an unexpected keyword argument 'key'
>>>
I've been using key = for hours, and your usage looks correct to me. I'll play around with a bit to see what's going on. I bet my python install went haywire and it's only happening on my end. And when I deleted that reference to key, it got mad at padding afterwards.
This is a very crude focus example.
This code is extremely similar to what I'd like, yes, thank you! I tried it out in my code and the only issue appears to be that if I click on anything else, it ends up deleting the new text as well. As you said, it's just a proof of concept, and it definitely does that job. I can probably easily get it to work the way I want it to by doing something like
default_text = "please type a number in here"
if window['-IN-'] == "please type a number in here":
window['-IN-'].update('')
else:
continue (or break or whatever the right choice would be)
Or something of the sort. Neato, thanks!
Not sure why you got this error.
layout = [[sg.InputText(default_text, size=(50, 1), key='myInput')],
TypeError: __init__() got an unexpected keyword argument 'key'
Maybe you can check this to ensure PySimleGUI version you use and check all arguements for sg.InputText.
import inspect
import PySimpleGUI as sg
def options(func):
return sorted(inspect.signature(func).parameters.keys())
def print_options(func):
print(f'{func.__name__} with following arguments:')
for i, option in enumerate(options(func)):
print('{:02d} {:s}'.format(i, option))
print('PySimpleGUI Version:', sg.version.split(' ')[0].strip())
print_options(sg.InputText)