Focus set and return key handling options

Exposed the ability to set where the initial forus is as well as which elements should be bound to the return key.
This commit is contained in:
MikeTheWatchGuy 2018-08-09 09:35:21 -04:00
parent 4962b02799
commit 49e89c7875
1 changed files with 68 additions and 67 deletions

View File

@ -174,6 +174,15 @@ class Element():
self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR
self.Key = key # dictionary key for return values
def ReturnKeyHandler(self, event):
MyForm = self.ParentForm
# search through this form and find the first button that will exit the form
for row in MyForm.Rows:
for element in row:
if element.Type == ELEM_TYPE_BUTTON:
if element.BindReturnKey:
element.ButtonCallBack()
def __del__(self):
try:
self.TKStringVar.__del__()
@ -196,7 +205,7 @@ class Element():
# Input Class #
# ---------------------------------------------------------------------- #
class InputText(Element):
def __init__(self, default_text ='', scale=(None, None), size=(None, None), auto_size_text=None, password_char='', background_color=None, text_color=None, key=None):
def __init__(self, default_text ='', scale=(None, None), size=(None, None), auto_size_text=None, password_char='', background_color=None, text_color=None, key=None, focus=False):
'''
Input a line of text Element
:param default_text: Default value to display
@ -209,17 +218,10 @@ class InputText(Element):
self.DefaultText = default_text
self.PasswordCharacter = password_char
bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
self.Focus = focus
super().__init__(ELEM_TYPE_INPUT_TEXT, scale=scale, size=size, auto_size_text=auto_size_text, background_color=bg, text_color=text_color, key=key)
def ReturnKeyHandler(self, event):
MyForm = self.ParentForm
# search through this form and find the first button that will exit the form
for row in MyForm.Rows:
for element in row:
if element.Type == ELEM_TYPE_BUTTON:
if element.BType == BUTTON_TYPE_CLOSES_WIN or element.BType == BUTTON_TYPE_READ_FORM:
element.ButtonCallBack()
return
def __del__(self):
super().__del__()
@ -385,7 +387,7 @@ class Spin(Element):
# Multiline #
# ---------------------------------------------------------------------- #
class Multiline(Element):
def __init__(self, default_text='', enter_submits = False, scale=(None, None), size=(None, None), auto_size_text=None, background_color=None, text_color=None, key=None):
def __init__(self, default_text='', enter_submits = False, scale=(None, None), size=(None, None), auto_size_text=None, background_color=None, text_color=None, key=None, focus=False):
'''
Input Multi-line Element
:param default_text:
@ -398,18 +400,10 @@ class Multiline(Element):
self.DefaultText = default_text
self.EnterSubmits = enter_submits
bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR
self.Focus = focus
super().__init__(ELEM_TYPE_INPUT_MULTILINE, scale=scale, size=size, auto_size_text=auto_size_text, background_color=bg, text_color=text_color, key=key)
return
def ReturnKeyHandler(self, event):
MyForm = self.ParentForm
# search through this form and find the first button that will exit the form
for row in MyForm.Rows:
for element in row:
if element.Type == ELEM_TYPE_BUTTON:
if element.BType == BUTTON_TYPE_CLOSES_WIN or element.BType == BUTTON_TYPE_READ_FORM:
element.ButtonCallBack()
return
def __del__(self):
super().__del__()
@ -568,7 +562,7 @@ class Output(Element):
# Button Class #
# ---------------------------------------------------------------------- #
class Button(Element):
def __init__(self, button_type=BUTTON_TYPE_CLOSES_WIN, target=(None, None), button_text='', file_types=(("ALL Files", "*.*"),), image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
def __init__(self, button_type=BUTTON_TYPE_CLOSES_WIN, target=(None, None), button_text='', file_types=(("ALL Files", "*.*"),), image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, focus=False):
'''
Button Element - Specifies all types of buttons
:param button_type:
@ -597,6 +591,8 @@ class Button(Element):
self.ImageSubsample = image_subsample
self.UserData = None
self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
self.BindReturnKey = bind_return_key
self.Focus = focus
super().__init__(ELEM_TYPE_BUTTON, scale, size, font=font)
return
@ -659,16 +655,6 @@ class Button(Element):
self.ParentForm.TKroot.quit() # kick the users out of the mainloop
return
def ReturnKeyHandler(self, event):
MyForm = self.ParentForm
# search through this form and find the first button that will exit the form
for row in MyForm.Rows:
for element in row:
if element.Type == ELEM_TYPE_BUTTON:
if element.BType == BUTTON_TYPE_CLOSES_WIN or element.BType == BUTTON_TYPE_READ_FORM:
element.ButtonCallBack()
return
def __del__(self):
try:
self.TKButton.__del__()
@ -818,6 +804,7 @@ class FlexForm:
self.ReturnValuesDictionary = None
self.ResultsBuilt = False
self.UseDictionary = use_dictionary
self.UseDefaultFocus = False
# ------------------------- Add ONE Row to Form ------------------------- #
def AddRow(self, *args):
@ -858,6 +845,19 @@ class FlexForm:
self.NumCols = max(len(row) for row in self.Rows)
self.NonBlocking=non_blocking
# Search through entire form to see if any elements set the focus
# if not, then will set the focus to the first input element
found_focus = False
for row in self.Rows:
for element in row:
try:
if element.Focus:
found_focus = True
break
except:
pass
if not found_focus:
self.UseDefaultFocus = True
# -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ##
StartupTK(self)
return self.ReturnValues
@ -1001,11 +1001,11 @@ class UberForm():
# ====================================================================== #
# ------------------------- INPUT TEXT Element lazy functions ------------------------- #
def In(default_text ='', scale=(None, None), size=(None, None), auto_size_text=None):
return InputText(default_text=default_text, scale=scale, size=size, auto_size_text=auto_size_text)
def In(default_text ='', scale=(None, None), size=(None, None), auto_size_text=None, focus=False):
return InputText(default_text=default_text, scale=scale, size=size, auto_size_text=auto_size_text, focus=focus)
def Input(default_text ='', scale=(None, None), size=(None, None), auto_size_text=None):
return InputText(default_text=default_text, scale=scale, size=size, auto_size_text=auto_size_text)
def Input(default_text ='', scale=(None, None), size=(None, None), auto_size_text=None, focus=False):
return InputText(default_text=default_text, scale=scale, size=size, auto_size_text=auto_size_text, focus=focus)
# ------------------------- INPUT COMBO Element lazy functions ------------------------- #
def Combo(values, scale=(None, None), size=(None, None), auto_size_text=None, background_color=None):
@ -1032,45 +1032,44 @@ def FileBrowse(target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), button_
return Button(BUTTON_TYPE_BROWSE_FILE, target, button_text=button_text, file_types=file_types, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
# ------------------------- SUBMIT BUTTON Element lazy function ------------------------- #
def Submit(button_text='Submit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
def Submit(button_text='Submit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, bind_return_key=bind_return_key, focus=focus)
# ------------------------- OK BUTTON Element lazy function ------------------------- #
def OK(button_text='OK', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
def OK(button_text='OK', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, bind_return_key=bind_return_key, focus=focus)
# ------------------------- YES BUTTON Element lazy function ------------------------- #
def Ok(button_text='Ok', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
def Ok(button_text='Ok', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, bind_return_key=bind_return_key, focus=focus)
# ------------------------- CANCEL BUTTON Element lazy function ------------------------- #
def Cancel(button_text='Cancel', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
def Cancel(button_text='Cancel', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, bind_return_key=bind_return_key, focus=focus)
# ------------------------- QUIT BUTTON Element lazy function ------------------------- #
def Quit(button_text='Quit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
def Quit(button_text='Quit', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, bind_return_key=bind_return_key, focus=focus)
# ------------------------- YES BUTTON Element lazy function ------------------------- #
def Yes(button_text='Yes', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
def Yes(button_text='Yes', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, bind_return_key=bind_return_key, focus=focus)
# ------------------------- NO BUTTON Element lazy function ------------------------- #
def No(button_text='No', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color)
def No(button_text='No', scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, bind_return_key=False, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, bind_return_key=bind_return_key, focus=focus)
# ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
# this is the only button that REQUIRES button text field
def SimpleButton(button_text, image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, button_text=button_text, border_width=border_width, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
def SimpleButton(button_text, image_filename=None, image_size=(None, None), image_subsample=None, border_width=None, scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, focus=False):
return Button(BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, button_text=button_text, border_width=border_width, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, bind_return_key=bind_return_key, focus=focus)
# ------------------------- GENERIC BUTTON Element lazy function ------------------------- #
# this is the only button that REQUIRES button text field
def ReadFormButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(BUTTON_TYPE_READ_FORM, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
def ReadFormButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, focus=False):
return Button(BUTTON_TYPE_READ_FORM, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, bind_return_key=bind_return_key, focus=focus)
def RealtimeButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None):
return Button(BUTTON_TYPE_REALTIME, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font)
def RealtimeButton(button_text, image_filename=None, image_size=(None, None),image_subsample=None,border_width=None,scale=(None, None), size=(None, None), auto_size_button=None, button_color=None, font=None, bind_return_key=False, focus=False):
return Button(BUTTON_TYPE_REALTIME, image_filename=image_filename, image_size=image_size, image_subsample=image_subsample, border_width=border_width, button_text=button_text, scale=scale, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, bind_return_key=bind_return_key, focus=focus)
#------------------------------------------------------------------------------------------------------#
# ------- FUNCTION InitializeResults. Sets up form results matrix ------- #
@ -1152,6 +1151,8 @@ def BuildResults(form):
value=element.TKStringVar.get()
results[row_num][col_num] = value
input_values.append(value)
if not form.NonBlocking:
element.TKStringVar.set('')
try:
input_values_dictionary[element.Key] = value
except: pass
@ -1364,7 +1365,7 @@ def ConvertFlexToTK(MyFlexForm):
tkbutton.image = photo
tkbutton.configure(wraplength=wraplen+10, font=font) # set wrap to width of widget
tkbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
if not focus_set and btype == BUTTON_TYPE_CLOSES_WIN:
if element.Focus is True or (MyFlexForm.UseDefaultFocus and not focus_set):
focus_set = True
element.TKButton.bind('<Return>', element.ReturnKeyHandler)
element.TKButton.focus_set()
@ -1382,7 +1383,7 @@ def ConvertFlexToTK(MyFlexForm):
if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
element.TKEntry.configure(fg=text_color)
element.TKEntry.pack(side=tk.LEFT,padx=element.Pad[0], pady=element.Pad[1])
if not focus_set:
if element.Focus is True or (MyFlexForm.UseDefaultFocus and not focus_set):
focus_set = True
element.TKEntry.focus_set()
# ------------------------- COMBO BOX (Drop Down) element ------------------------- #
@ -1453,7 +1454,7 @@ def ConvertFlexToTK(MyFlexForm):
element.TKText.pack(side=tk.LEFT,padx=element.Pad[0], pady=element.Pad[1])
if element.EnterSubmits:
element.TKText.bind('<Return>', element.ReturnKeyHandler)
if not focus_set:
if element.Focus is True or (MyFlexForm.UseDefaultFocus and not focus_set):
focus_set = True
element.TKText.focus_set()
if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT:
@ -1748,19 +1749,19 @@ def MsgBox(*args, button_color=None, button_type=MSG_BOX_OK, auto_close=False, a
pad =1
# show either an OK or Yes/No depending on paramater
if button_type is MSG_BOX_YES_NO:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Yes(button_color=button_color), No(
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Yes(button_color=button_color, focus=True, bind_return_key=True), No(
button_color=button_color))
(button_text, values) = form.Show()
return button_text == 'Yes'
elif button_type is MSG_BOX_CANCELLED:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('Cancelled', button_color=button_color))
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True))
elif button_type is MSG_BOX_ERROR:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('ERROR', size=(5, 1), button_color=button_color))
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('ERROR', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True))
elif button_type is MSG_BOX_OK_CANCEL:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('OK', size=(5, 1), button_color=button_color),
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True),
SimpleButton('Cancel', size=(5, 1), button_color=button_color))
else:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('OK', size=(5, 1), button_color=button_color))
form.AddRow(Text('', size=(pad, 1), auto_size_text=False), SimpleButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True))
button, values = form.Show()
return button
@ -2169,7 +2170,7 @@ def ScrolledTextBox(*args, button_color=None, yes_no=False, auto_close=False, au
height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed
if height:
height_computed = height
form.AddRow(Multiline(complete_output, size=(max_line_width, height_computed)), auto_size_text=True)
form.AddRow(Multiline(complete_output, size=(max_line_width, height_computed)))
pad = max_line_total-15 if max_line_total > 15 else 1
# show either an OK or Yes/No depending on paramater
if yes_no:
@ -2415,9 +2416,9 @@ def main():
form_rows = [[Text('You are running the PySimpleGUI.py file itself')],
[Text('You should be importing it rather than running it\n')],
[Text('Here is your sample input form....')],
[Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), InputText('Source'),FolderBrowse()],
[Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), InputText('Source', focus=True),FolderBrowse()],
[Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), InputText('Dest'), FolderBrowse()],
[Submit(), Cancel()]]
[Submit(bind_return_key=True), Cancel()]]
button, (source, dest) = form.LayoutAndRead(form_rows)