From f574f333181482043cb09eeb9883f50623cd6522 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <mike_barnett@hotmail.com> Date: Thu, 30 Aug 2018 22:02:29 -0400 Subject: [PATCH 1/5] Slider addition --- Demo_MIDI_Player.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Demo_MIDI_Player.py b/Demo_MIDI_Player.py index 3e0e81b5..dbaabc0c 100644 --- a/Demo_MIDI_Player.py +++ b/Demo_MIDI_Player.py @@ -41,7 +41,7 @@ class PlayerGUI(): [g.Text('Choose MIDI Output Device', size=(22, 1)), g.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), key='device')], [g.Text('_' * 250, auto_size_text=False, size=(100, 1))], - [g.SimpleButton('PLAY!', size=(10, 2), button_color=('red', 'white'), font=("Helvetica", 15), bind_return_key=True), g.Text(' ' * 2, size=(4, 1)), g.Cancel(size=(8, 2), font=("Helvetica", 15))]] + [g.SimpleButton('PLAY', size=(12, 2), button_color=('red', 'white'), font=("Helvetica", 15), bind_return_key=True), g.Text(' ' * 2, size=(4, 1)), g.Cancel(size=(8, 2), font=("Helvetica", 15))]] self.Form = form @@ -56,11 +56,13 @@ class PlayerGUI(): image_next = './ButtonGraphics/Next.png' image_exit = './ButtonGraphics/Exit.png' - self.TextElem = g.T('Song loading....', size=(85,5 + NumFiles), font=("Helvetica", 14), auto_size_text=False) + self.TextElem = g.T('Song loading....', size=(70,5 + NumFiles), font=("Helvetica", 14), auto_size_text=False) + self.SliderElem = g.Slider(range=(1,100), size=(50, 8), orientation='h', text_color='#f0f0f0') form = g.FlexForm('MIDI File Player', default_element_size=(30,1),font=("Helvetica", 25)) layout = [ [g.T('MIDI File Player', size=(30,1), font=("Helvetica", 25))], [self.TextElem], + [self.SliderElem], [g.ReadFormButton('PAUSE', button_color=g.TRANSPARENT_BUTTON, image_filename=image_pause, image_size=(50,50),image_subsample=2, border_width=0), g.T(' '), g.ReadFormButton('NEXT', button_color=g.TRANSPARENT_BUTTON, @@ -113,10 +115,11 @@ def main(): ''' return int(round(time.time() * 1000)) + pback = PlayerGUI() button, values = pback.PlayerChooseSongGUI() - if button != 'PLAY!': + if button != 'PLAY': g.MsgBoxCancel('Cancelled...\nAutoclose in 2 sec...', auto_close=True, auto_close_duration=2) exit(69) if values['device']: @@ -164,7 +167,7 @@ def main(): # Build list of data contained in MIDI File using only track 0 midi_length_in_seconds = mid.length - display_file_list = '>> ' + '\n'.join([f for i, f in enumerate(filelist[now_playing_number:]) if i < 10]) + display_file_list = '>> ' + '\n'.join([f for i, f in enumerate(filetitles[now_playing_number:]) if i < 10]) paused = cancelled = next_file = False ######################### Loop through MIDI Messages ########################### while(True): @@ -179,6 +182,7 @@ def main(): display_string = 'Now Playing {} of {}\n{}\n {:02d}:{:02d} of {}\nPlaylist:'.\ format(now_playing_number+1, len(filelist), midi_title, *divmod(t, 60), display_midi_len) # display list of next 10 files to be played. + pback.SliderElem.Update(t, range=(1,midi_length_in_seconds)) rc = pback.PlayerPlaybackGUIUpdate(display_string + '\n' + display_file_list) else: # fake rest of code as if GUI did nothing rc = PLAYER_COMMAND_NONE From 310fe845e4fcf16d27b7a23fa81af2a601fe7cb0 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <mike_barnett@hotmail.com> Date: Fri, 31 Aug 2018 09:07:37 -0400 Subject: [PATCH 2/5] Spin Element change_submits feature, can change font when updating Text Element, CHANGE TO PACKED ROWS Important change to how "rows" are placed into form. Switched from Grid to packed. SHOULD be ok, but it's a big change. --- PySimpleGUI.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index e3931bdb..c3c67a85 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -421,7 +421,7 @@ class Checkbox(Element): class Spin(Element): # Values = None # TKSpinBox = None - def __init__(self, values, initial_value=None, scale=(None, None), size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None): + def __init__(self, values, initial_value=None, change_submits=False, scale=(None, None), size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None): ''' Spin Box Element :param values: @@ -434,6 +434,7 @@ class Spin(Element): ''' self.Values = values self.DefaultValue = initial_value + self.ChangeSubmits = change_submits self.TKSpinBox = None bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR @@ -441,6 +442,13 @@ class Spin(Element): super().__init__(ELEM_TYPE_INPUT_SPIN, scale, size, auto_size_text, font=font,background_color=bg, text_color=fg, key=key, pad=pad) return + def SpinChangedHandler(self, event): + # first, get the results table built + # modify the Results table in the parent FlexForm object + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + self.ParentForm.TKroot.quit() # kick the users out of the mainloop + def __del__(self): try: self.TKSpinBox.__del__() @@ -509,7 +517,7 @@ class Text(Element): super().__init__(ELEM_TYPE_TEXT, scale, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, text_color=self.TextColor, pad=pad) return - def Update(self, new_value = None, background_color=None, text_color=None): + def Update(self, new_value = None, background_color=None, text_color=None, font=None): if new_value is not None: self.DisplayText=new_value stringvar = self.TKStringVar @@ -518,6 +526,9 @@ class Text(Element): self.TKText.configure(background=background_color) if text_color is not None: self.TKText.configure(fg=text_color) + if font is not None: + self.TKText.configure(font=font) + def __del__(self): super().__del__() @@ -1803,6 +1814,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKSpinBox.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: element.TKSpinBox.configure(fg=text_color) + if element.ChangeSubmits: + element.TKSpinBox.bind('<ButtonRelease-1>', element.SpinChangedHandler) # ------------------------- OUTPUT element ------------------------- # elif element_type == ELEM_TYPE_OUTPUT: width, height = element_size @@ -1870,7 +1883,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKScale = tkscale #............................DONE WITH ROW pack the row of widgets ..........................# # done with row, pack the row of widgets - tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) + # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) + tk_row_frame.pack(side=tk.TOP, anchor='sw', padx=DEFAULT_MARGINS[0]) if form.BackgroundColor is not None and form.BackgroundColor != COLOR_SYSTEM_DEFAULT: tk_row_frame.configure(background=form.BackgroundColor) From b7c095d9c01a758945b4d0bb14a50c77d08b9969 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <mike_barnett@hotmail.com> Date: Fri, 31 Aug 2018 09:10:15 -0400 Subject: [PATCH 3/5] New demo that shows how to use new spinner change submits capability --- Demo_Font_Sizer.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 Demo_Font_Sizer.py diff --git a/Demo_Font_Sizer.py b/Demo_Font_Sizer.py new file mode 100644 index 00000000..452e22b5 --- /dev/null +++ b/Demo_Font_Sizer.py @@ -0,0 +1,28 @@ + +# Testing async form, see if can have a spinner +# that adjusts the size of text displayed + +import PySimpleGUI as sg + +form = sg.FlexForm("Font size selector") + +fontSize = 12 +sampleText = sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize)) +layout = [ + [sampleText, sg.Spin([sz for sz in range(4,72)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin')], + [sg.OK(), sg.Cancel()] + ] + +sz = fontSize +form.Layout(layout) +while True: + button, values= form.Read() + if button is None: + break + sz = int(values['spin']) + if sz != fontSize: + fontSize = sz + font = "Helvetica " + str(fontSize) + sampleText.Update(font=font) + +print("Done.") From 3793ff81c222dbf39fcf9a7213e875171562d7ee Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <mike_barnett@hotmail.com> Date: Fri, 31 Aug 2018 09:29:00 -0400 Subject: [PATCH 4/5] Slider change_submits feature. Update method for Slider, updated Font Sizer demo --- Demo_Font_Sizer.py | 13 ++++++++++--- PySimpleGUI.py | 29 +++++++++++++++++++++++------ 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/Demo_Font_Sizer.py b/Demo_Font_Sizer.py index 452e22b5..7a5e0b8f 100644 --- a/Demo_Font_Sizer.py +++ b/Demo_Font_Sizer.py @@ -1,5 +1,5 @@ -# Testing async form, see if can have a spinner +# Testing async form, see if can have a slider # that adjusts the size of text displayed import PySimpleGUI as sg @@ -8,8 +8,10 @@ form = sg.FlexForm("Font size selector") fontSize = 12 sampleText = sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize)) +slider = sg.Slider(range=(6,50), orientation='h', size=(10,20), change_submits=True, key='slider') +spin = sg.Spin([sz for sz in range(4,72)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin') layout = [ - [sampleText, sg.Spin([sz for sz in range(4,72)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin')], + [sampleText, spin, slider], [sg.OK(), sg.Cancel()] ] @@ -19,10 +21,15 @@ while True: button, values= form.Read() if button is None: break - sz = int(values['spin']) + sz_spin = int(values['spin']) + sz_slider = int(values['slider']) + sz = sz_spin if sz_spin != fontSize else sz_slider if sz != fontSize: + print(sampleText.Font, sampleText.Size) fontSize = sz font = "Helvetica " + str(fontSize) sampleText.Update(font=font) + slider.Update(sz) + spin.Update(sz) print("Done.") diff --git a/PySimpleGUI.py b/PySimpleGUI.py index c3c67a85..ecac9639 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -442,6 +442,9 @@ class Spin(Element): super().__init__(ELEM_TYPE_INPUT_SPIN, scale, size, auto_size_text, font=font,background_color=bg, text_color=fg, key=key, pad=pad) return + def Update(self, new_value): + self.TKStringVar.set(new_value) + def SpinChangedHandler(self, event): # first, get the results table built # modify the Results table in the parent FlexForm object @@ -888,18 +891,23 @@ class Frame(Element): # Slider # # ---------------------------------------------------------------------- # class Slider(Element): - def __init__(self, range=(None,None), default_value=None, resolution=None, orientation=None, border_width=None, relief=None, scale=(None, None), size=(None, None), font=None, background_color=None, text_color=None, key=None, pad=None): + def __init__(self, range=(None,None), default_value=None, resolution=None, orientation=None, border_width=None, relief=None, change_submits=False, scale=(None, None), size=(None, None), font=None, background_color=None, text_color=None, key=None, pad=None): ''' - Slider Element + Slider :param range: :param default_value: + :param resolution: :param orientation: :param border_width: :param relief: - :param scale: Adds multiplier to size (w,h) - :param size: Size of field in characters - :param background_color: Color for Element. Text or RGB Hex + :param change_submits: + :param scale: + :param size: :param font: + :param background_color: + :param text_color: + :param key: + :param pad: ''' self.TKScale = None self.Range = (1,10) if range == (None, None) else range @@ -908,6 +916,7 @@ class Slider(Element): self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF self.Resolution = 1 if resolution is None else resolution + self.ChangeSubmits = change_submits super().__init__(ELEM_TYPE_INPUT_SLIDER, scale=scale, size=size, font=font, background_color=background_color, text_color=text_color, key=key, pad=pad) return @@ -917,6 +926,12 @@ class Slider(Element): if range != (None, None): self.TKScale.config(from_ = range[0], to_ = range[1]) + def SliderChangedHandler(self, event): + # first, get the results table built + # modify the Results table in the parent FlexForm object + self.ParentForm.LastButtonClicked = '' + self.ParentForm.FormRemainedOpen = True + self.ParentForm.TKroot.quit() # kick the users out of the mainloop def __del__(self): super().__del__() @@ -1871,7 +1886,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): else: range_from = element.Range[0] range_to = element.Range[1] - tkscale = tk.Scale(tk_row_frame, orient=element.Orientation, variable=element.TKIntVar, from_=range_from, to_=range_to, resolution = element.Resolution, length=slider_length, width=slider_width , bd=element.BorderWidth, relief=element.Relief, font=font) + tkscale = tk.Scale(tk_row_frame, orient=element.Orientation, variable=element.TKIntVar, from_=range_from, to_=range_to, resolution = element.Resolution, length=slider_length, width=slider_width , bd=element.BorderWidth, relief=element.Relief, font=font, command=element.SliderChangedHandler) + # if element.ChangeSubmits: + # element.tkscale.bind('<Change>', element.SliderChangedHandler) # tktext_label.configure(anchor=tk.NW, image=photo) tkscale.config(highlightthickness=0) if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: From c4364a210968b984481b916dfc9cbb943a262add Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <mike_barnett@hotmail.com> Date: Fri, 31 Aug 2018 19:03:19 -0400 Subject: [PATCH 5/5] New Pop series of functions Popup, PopupGetFile, PopupGetFolder, PopupGetText, --- PySimpleGUI.py | 80 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index ecac9639..02260b3a 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -911,7 +911,7 @@ class Slider(Element): ''' self.TKScale = None self.Range = (1,10) if range == (None, None) else range - self.DefaultValue = 5 if default_value is None else default_value + self.DefaultValue = self.Range[0] if default_value is None else default_value self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF @@ -2131,6 +2131,11 @@ def MsgBox(*args, button_color=None, button_type=MSG_BOX_OK, auto_close=False, a button, values = form.Show() return button +# ============================== PopUp ============# +# Lazy function. Same as calling MsgBox with parms # +# ===================================================# +Popup = MsgBox + # ============================== MsgBoxAutoClose====# # Lazy function. Same as calling MsgBox with parms # # ===================================================# @@ -2147,6 +2152,8 @@ def MsgBoxAutoClose(*args, button_color=None, auto_close=True, auto_close_durati MsgBox(*args, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, font=font) return +PopupTimed = MsgBoxAutoClose + # ============================== MsgBoxError =====# # Like MsgBox but presents RED BUTTONS # @@ -2164,6 +2171,9 @@ def MsgBoxError(*args, button_color=DEFAULT_ERROR_BUTTON_COLOR, auto_close=False MsgBox(*args, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, font=font) return +PopupError = MsgBoxError + + # ============================== MsgBoxCancel =====# # # # ===================================================# @@ -2180,6 +2190,9 @@ def MsgBoxCancel(*args, button_color=None, auto_close=False, auto_close_duration MsgBox(*args, button_type=MSG_BOX_CANCELLED, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, font=font) return +PopupCancel =MsgBoxCancel + + # ============================== MsgBoxOK =====# # Like MsgBox but only 1 button # # ===================================================# @@ -2196,6 +2209,10 @@ def MsgBoxOK(*args, button_color=None, auto_close=False, auto_close_duration=Non MsgBox(*args, button_type=MSG_BOX_OK, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, font=font) return +PopupOk = MsgBoxOK +PopupOK = MsgBoxOK + + # ============================== MsgBoxOKCancel ====# # Like MsgBox but presents OK and Cancel buttons # # ===================================================# @@ -2212,6 +2229,10 @@ def MsgBoxOKCancel(*args, button_color=None, auto_close=False, auto_close_durati result = MsgBox(*args, button_type=MSG_BOX_OK_CANCEL, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, font=font) return result +PopupOKCancel = MsgBoxOKCancel +PopupOkCancel = MsgBoxOKCancel + + # ==================================== YesNoBox=====# # Like MsgBox but presents Yes and No buttons # # Returns True if Yes was pressed else False # @@ -2229,6 +2250,9 @@ def MsgBoxYesNo(*args, button_color=None, auto_close=False, auto_close_duration= result = MsgBox(*args, button_type=MSG_BOX_YES_NO, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, font=font) return result + +PopupYesNo = MsgBoxYesNo + # ============================== PROGRESS METER ========================================== # def ConvertArgsToSingleString(*args): @@ -2574,6 +2598,24 @@ def GetPathBox(title, message, default_path='', button_color=None, size=(None, N path = input_values[0] return True, path + +GetFolder = GetPathBox +AskForFolder = GetPathBox + + +def PopupGetFolder(message, default_path='', button_color=None, size=(None, None)): + with FlexForm(title=message, auto_size_text=True, button_color=button_color) as form: + layout = [[Text(message, auto_size_text=True)], + [InputText(default_text=default_path, size=size), FolderBrowse()], + [Ok(), Cancel()]] + + (button, input_values) = form.LayoutAndShow(layout) + if button != 'Ok': + return None + else: + path = input_values[0] + return path + # ============================== GetFileBox =========# # Like the Get folder box but for files # # ===================================================# @@ -2590,6 +2632,22 @@ def GetFileBox(title, message, default_path='', file_types=(("ALL Files", "*.*") path = input_values[0] return True, path +GetFile = GetFileBox +AskForFile = GetFileBox + + +def PopupGetFile(message, default_path='', file_types=(("ALL Files", "*.*"),), button_color=None, size=(None, None)): + with FlexForm(title=message, auto_size_text=True, button_color=button_color) as form: + layout = [[Text(message, auto_size_text=True)], + [InputText(default_text=default_path, size=size), FileBrowse(file_types=file_types)], + [Ok(), Cancel()]] + + (button, input_values) = form.LayoutAndShow(layout) + if button != 'Ok': + return None + else: + path = input_values[0] + return path # ============================== GetTextBox =========# # Get a single line of text # @@ -2606,6 +2664,24 @@ def GetTextBox(title, message, Default='', button_color=None, size=(None, None)) else: return True, input_values[0] +GetText = GetTextBox +GetString = GetTextBox +AskForText = GetTextBox +AskForString = GetTextBox + + +def PopupGetText(message, Default='', button_color=None, size=(None, None)): + with FlexForm(title=message, auto_size_text=True, button_color=button_color) as form: + layout = [[Text(message, auto_size_text=True)], + [InputText(default_text=Default, size=size)], + [Ok(), Cancel()]] + + (button, input_values) = form.LayoutAndShow(layout) + if button != 'Ok': + return None + else: + return input_values[0] + # ============================== SetGlobalIcon ======# # Sets the icon to be used by default # @@ -2860,7 +2936,7 @@ def main(): [Text('Here is your sample input form....')], [Text('Source Folder', size=(15, 1), justification='right'), InputText('Source', focus=True),FolderBrowse()], [Text('Destination Folder', size=(15, 1), justification='right'), InputText('Dest'), FolderBrowse()], - [Submit(bind_return_key=True), Cancel()]] + [Ok(bind_return_key=True), Cancel()]] button, (source, dest) = form.LayoutAndRead(form_rows)