From 8b78d6e95547391f24b1dc7b34ff338fccebf663 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Tue, 4 Sep 2018 19:43:22 -0400 Subject: [PATCH 1/2] Refresh of ALL Demos in prep for 2.20 release --- Demo_All_Widgets.py | 17 ++--- Demo_Canvas.py | 13 ++-- Demo_Chat.py | 2 +- Demo_Color.py | 20 ++---- Demo_Columns.py | 4 +- Demo_Compare_Files.py | 6 +- Demo_Cookbook_Browser.py | 18 ++--- Demo_Dictionary.py | 15 +--- Demo_DisplayHash1and256.py | 21 +++--- Demo_ElementBrowser.py | 24 +++++++ Demo_HowDoI.py | 9 +-- Demo_Keyboard_Realtime.py | 7 +- Demo_Keypad.py | 25 ++++--- Demo_Machine_Learning.py | 4 +- Demo_Matplotlib_Ping_Graph_Large.py | 107 ++++++++++++++++++++++++++++ Demo_Media_Player.py | 8 +-- Demo_NonBlocking_Form.py | 3 +- Demo_Pi_LEDs.py | 59 +++++++++++++++ Demo_Pi_Robotics.py | 12 ++-- Demo_Recipes.py | 62 ++++++++-------- Demo_Script_Launcher.py | 4 +- Demo_Script_Parameters.py | 2 +- Demo_Super_Simple_Form.py | 28 ++++++-- Demo_Tabbed_Form.py | 4 +- 24 files changed, 330 insertions(+), 144 deletions(-) create mode 100644 Demo_ElementBrowser.py create mode 100644 Demo_Matplotlib_Ping_Graph_Large.py create mode 100644 Demo_Pi_LEDs.py diff --git a/Demo_All_Widgets.py b/Demo_All_Widgets.py index 66f6c598..cb03220f 100644 --- a/Demo_All_Widgets.py +++ b/Demo_All_Widgets.py @@ -2,11 +2,11 @@ import PySimpleGUI as sg def Everything(): - # sg.ChangeLookAndFeel('LightGreen') - # sg.SetOptions(input_elements_background_color=sg.COLOR_SYSTEM_DEFAULT) + sg.ChangeLookAndFeel('Dark') + form = sg.FlexForm('Everything bagel', default_element_size=(40, 1)) - column1 = [[sg.Text('Column 1', background_color='#d3dfda', justification='center', size=(10, 1))], + column1 = [[sg.Text('Column 1', background_color='black', justification='center', size=(10, 1))], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2')], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]] @@ -15,17 +15,18 @@ def Everything(): [sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25))], [sg.Text('Here is some text.... and a place to enter text')], [sg.InputText('This is my text')], - [sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)], + [sg.Checkbox('Checkbox'), sg.Checkbox('My second checkbox!', default=True)], [sg.Radio('My first Radio! ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")], [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)), sg.Multiline(default_text='A second multi-line', size=(35, 3))], [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 1)), sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)], + [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))], [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10), - sg.Column(column1, background_color='#d3dfda')], + sg.Column(column1, background_color='black')], [sg.Text('_' * 80)], [sg.Text('Choose A Folder', size=(35, 1))], [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'), @@ -35,7 +36,7 @@ def Everything(): button, values = form.LayoutAndRead(layout) - # sg.MsgBox('Title', 'The results of the form.', 'The button clicked was "{}"'.format(button), 'The values are', values) + sg.Popup('Title', 'The results of the form.', 'The button clicked was "{}"'.format(button), 'The values are', values) + +Everything() -sg.SetOptions(button_color=sg.COLOR_SYSTEM_DEFAULT) -Everything() \ No newline at end of file diff --git a/Demo_Canvas.py b/Demo_Canvas.py index 35eec494..893c9d4f 100644 --- a/Demo_Canvas.py +++ b/Demo_Canvas.py @@ -1,9 +1,7 @@ import PySimpleGUI as gui -canvas = gui.Canvas(size=(100,100), background_color='red') - layout = [ - [canvas], + [gui.Canvas(size=(100,100), background_color='red', key='canvas')], [gui.T('Change circle color to:'), gui.ReadFormButton('Red'), gui.ReadFormButton('Blue')] ] @@ -11,12 +9,13 @@ form = gui.FlexForm('Canvas test') form.Layout(layout) form.ReadNonBlocking() -cir = canvas.TKCanvas.create_oval(50, 50, 100, 100) +cir = form.FindElement('canvas').TKCanvas.create_oval(50, 50, 100, 100) while True: button, values = form.Read() - if button is None: break + if button is None: + break if button is 'Blue': - canvas.TKCanvas.itemconfig(cir, fill = "Blue") + form.FindElement('canvas').TKCanvas.itemconfig(cir, fill = "Blue") elif button is 'Red': - canvas.TKCanvas.itemconfig(cir, fill = "Red") + form.FindElement('canvas').TKCanvas.itemconfig(cir, fill = "Red") diff --git a/Demo_Chat.py b/Demo_Chat.py index 5e4d793b..55bba560 100644 --- a/Demo_Chat.py +++ b/Demo_Chat.py @@ -28,7 +28,7 @@ def ChatBotWithHistory(): ] form.Layout(layout) - # ---===--- Loop taking in user input and using it to query HowDoI --- # + # ---===--- Loop taking in user input and using it --- # command_history = [] history_offset = 0 while True: diff --git a/Demo_Color.py b/Demo_Color.py index 142b19cb..14c64ab8 100644 --- a/Demo_Color.py +++ b/Demo_Color.py @@ -1684,21 +1684,7 @@ def main(): [g.Submit(), g.Quit(), g.SimpleButton('Show me lots of colors!', button_color=('white','#0e6251'))], ] # [g.Multiline(DefaultText=str(printable), Size=(30,20))]] - (button, (hex_input, drop_down_value)) = g.FlexForm('Color Demo', auto_size_text=True, icon=MY_WINDOW_ICON).LayoutAndShow(layout) - - drop_down_value = drop_down_value[0] - - # ------- Form show ------- # - # layout = [[g.Text('Find color')], - # [g.Text('Demonstration of colors')], - # [g.Text('Enter a color name in text or hex #RRGGBB format')], - # [g.InputText()], - # [g.InputCombo(list_of_colors, size=(20,6)), g.T('Or choose from list')], - # [g.Submit(), g.Quit(), g.SimpleButton('Show me lots of colors!', button_color=('white','#0e6251'))], - # ] - # # [g.Multiline(DefaultText=str(printable), Size=(30,20))]] - # (button, (hex_input, drop_down_value)) = g.FlexForm('Color Demo', auto_size_text=True, icon=MY_WINDOW_ICON).LayoutAndShow(layout) - + (button, (hex_input, drop_down_value)) = g.FlexForm('Color Demo', auto_size_text=True, icon=MY_WINDOW_ICON).LayoutAndRead(layout) # ------- OUTPUT results portion ------- # if button == '' or button == 'Quit' or button is None: @@ -1706,6 +1692,8 @@ def main(): elif button == 'Show me lots of colors!': show_all_colors_on_buttons() + drop_down_value = drop_down_value[0] + if hex_input is not '' and hex_input[0] == '#': color_hex = hex_input.upper() color_name = get_name_from_hex(hex_input) @@ -1721,7 +1709,7 @@ def main(): [g.Button(button_text=color_name, button_color=(color_hex, complementary_hex))], [g.Button(button_text=complementary_hex + ' ' + complementary_color, button_color=(complementary_hex , color_hex), size=(30,1))], ] - g.FlexForm('Color demo', default_element_size=(100,1), auto_size_text=True, auto_close=True, auto_close_duration=5, icon=MY_WINDOW_ICON).LayoutAndShow(layout) + g.FlexForm('Color demo', default_element_size=(100,1), auto_size_text=True, auto_close=True, auto_close_duration=5, icon=MY_WINDOW_ICON).LayoutAndRead(layout) diff --git a/Demo_Columns.py b/Demo_Columns.py index 2f07b83b..d58a8fe2 100644 --- a/Demo_Columns.py +++ b/Demo_Columns.py @@ -11,7 +11,6 @@ import PySimpleGUI as sg def ScrollableColumns(): # sg.ChangeLookAndFeel('Dark') - column1 = [[sg.Text('Column 1', justification='center', size=(20, 1))], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1', key='spin1', size=(30,1))], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')], @@ -33,12 +32,13 @@ def ScrollableColumns(): for i in range(50): column2.append([sg.T(f'{i}{j}', size=(4, 1), background_color='gray25', text_color='white', pad=(1, 1)) for j in range(10)]) - layout = [[sg.Column(column2, scrollable=True, size=(400,300)), sg.Column(column1, scrollable=True, size=(200,150))], + layout = [[sg.Column(column2, scrollable=True), sg.Column(column1, scrollable=True, size=(200,150))], [sg.OK()]] form = sg.FlexForm('Form Fill Demonstration', default_element_size=(40, 1)) b, v = form.LayoutAndRead(layout) + sg.Popup(v) def NormalColumns(): # Column layout diff --git a/Demo_Compare_Files.py b/Demo_Compare_Files.py index c5ecf7f2..73cdf604 100644 --- a/Demo_Compare_Files.py +++ b/Demo_Compare_Files.py @@ -1,13 +1,15 @@ import PySimpleGUI as sg +sg.SetOptions(button_color=sg.COLOR_SYSTEM_DEFAULT) + def GetFilesToCompare(): with sg.FlexForm('File Compare') as form: form_rows = [[sg.Text('Enter 2 files to comare')], [sg.Text('File 1', size=(15, 1)), sg.InputText(), sg.FileBrowse()], [sg.Text('File 2', size=(15, 1)), sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]] - rc = form.LayoutAndShow(form_rows) - return rc + button, values = form.LayoutAndRead(form_rows) + return button, values def main(): button, (f1, f2) = GetFilesToCompare() diff --git a/Demo_Cookbook_Browser.py b/Demo_Cookbook_Browser.py index 2e1cc91b..d68e82b0 100644 --- a/Demo_Cookbook_Browser.py +++ b/Demo_Cookbook_Browser.py @@ -56,7 +56,7 @@ def FileBrowse(): form_rows = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], [sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]] - (button, (source_filename,)) = form.LayoutAndShow(form_rows) + (button, (source_filename,)) = form.LayoutAndRead(form_rows) print(button, source_filename) @@ -92,7 +92,7 @@ def Compare2Files(): [sg.Text('File 2', size=(8, 1)), sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]] - button, values = form.LayoutAndShow(form_rows) + button, values = form.LayoutAndRead(form_rows) print(button, values) @@ -364,15 +364,12 @@ def MediaPlayer(): image_next = './ButtonGraphics/Next.png' image_exit = './ButtonGraphics/Exit.png' - # A text element that will be changed to display messages in the GUI - TextElem = sg.Text('', size=(15, 2), font=("Helvetica", 14)) - # Open a form, note that context manager can't be used generally speaking for async forms form = sg.FlexForm('Media File Player', auto_size_text=True, default_element_size=(20, 1), font=("Helvetica", 25)) # define layout of the rows layout = [[sg.Text('Media File Player', size=(17, 1), font=("Helvetica", 25))], - [TextElem], + [sg.Text('', size=(15, 2), font=("Helvetica", 14), key='out')], [sg.ReadFormButton('Restart Song', button_color=(background, background), image_filename=image_restart, image_size=(50, 50), image_subsample=2, border_width=0), sg.Text(' ' * 2), @@ -387,8 +384,7 @@ def MediaPlayer(): border_width=0)], [sg.Text('_' * 20)], [sg.Text(' ' * 30)], - [ - sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', + [sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)), sg.Text(' ' * 2), sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', @@ -398,9 +394,7 @@ def MediaPlayer(): font=("Helvetica", 15))], [sg.Text('Bass', font=("Helvetica", 15), size=(6, 1)), sg.Text('Treble', font=("Helvetica", 15), size=(10, 1)), - sg.Text('Volume', font=("Helvetica", 15), size=(7, 1))] - - ] + sg.Text('Volume', font=("Helvetica", 15), size=(7, 1))] ] # Call the same LayoutAndRead but indicate the form is non-blocking form.LayoutAndRead(layout, non_blocking=True) @@ -412,7 +406,7 @@ def MediaPlayer(): break # If a button was pressed, display it on the GUI by updating the text element if button: - TextElem.Update(button) + form.FindElement('out').Update(button) def ScriptLauncher(): """ diff --git a/Demo_Dictionary.py b/Demo_Dictionary.py index 9b001eae..1b918b7b 100644 --- a/Demo_Dictionary.py +++ b/Demo_Dictionary.py @@ -1,20 +1,12 @@ import PySimpleGUI as sg -# THIS FILE REQIRES THE LATEST PySimpleGUI.py FILE -# IT WILL NOT WORK WITH CURRENT PIP RELEASE (2.7) -# -# If you want to use the return values as Dictionary feature, you need to download the PySimpleGUI.py file -# from GitHub and then place it in your project's folder. This SHOULD cause it to use this downloaded version -# instead of the pip installed one, if you've pip installed it. You can always uninstall the pip one :-) - - -# This design pattern shows how to use return values in dictionary form +# THIS FILE REQUIRES VERSION 2.8 OF PySimpleGUI! form = sg.FlexForm('Simple data entry form') # begin with a blank form layout = [ [sg.Text('Please enter your Name, Address, Phone')], - [sg.Text('Name', size=(15, 1)), sg.InputText('1')], + [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='name')], [sg.Text('Address', size=(15, 1)), sg.InputText('2', key='address')], [sg.Text('Phone', size=(15, 1)), sg.InputText('3', key='phone')], [sg.Submit(), sg.Cancel()] @@ -22,6 +14,5 @@ layout = [ button, values = form.LayoutAndRead(layout) -sg.MsgBox(button, values, values[0], values['address'], values['phone']) +sg.MsgBox(button, values, values['name'], values['address'], values['phone']) -print(values) diff --git a/Demo_DisplayHash1and256.py b/Demo_DisplayHash1and256.py index 4aa3db1d..dfff1e1b 100644 --- a/Demo_DisplayHash1and256.py +++ b/Demo_DisplayHash1and256.py @@ -55,16 +55,16 @@ def HashManuallyBuiltGUI(): form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')], [SG.InputText(), SG.FileBrowse()], [SG.Submit(), SG.Cancel()]] - (button, (source_filename, )) = form.LayoutAndShow(form_rows) + (button, (source_filename, )) = form.LayoutAndRead(form_rows) if button == 'Submit': if source_filename != '': hash_sha1 = compute_sha1_hash_for_file(source_filename).upper() hash_sha256 = compute_sha256_hash_for_file(source_filename).upper() - SG.MsgBox( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75) - else: SG.MsgBoxError('Display A Hash in PySimpleGUI', 'Illegal filename') + SG.Popup( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75) + else: SG.PopupError('Display A Hash in PySimpleGUI', 'Illegal filename') else: - SG.MsgBoxError('Display A Hash in PySimpleGUI', '* Cancelled *') + SG.PopupError('Display A Hash in PySimpleGUI', '* Cancelled *') def HashManuallyBuiltGUINonContext(): # ------- Form design ------- # @@ -72,16 +72,16 @@ def HashManuallyBuiltGUINonContext(): form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')], [SG.InputText(), SG.FileBrowse()], [SG.Submit(), SG.Cancel()]] - button, (source_filename, ) = form.LayoutAndShow(form_rows) + button, (source_filename, ) = form.LayoutAndRead(form_rows) if button == 'Submit': if source_filename != '': hash_sha1 = compute_sha1_hash_for_file(source_filename).upper() hash_sha256 = compute_sha256_hash_for_file(source_filename).upper() - SG.MsgBox( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75) - else: SG.MsgBoxError('Display A Hash in PySimpleGUI', 'Illegal filename') + SG.Popup( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75) + else: SG.PopupError('Display A Hash in PySimpleGUI', 'Illegal filename') else: - SG.MsgBoxError('Display A Hash in PySimpleGUI', '* Cancelled *') + SG.PopupError('Display A Hash in PySimpleGUI', '* Cancelled *') @@ -100,15 +100,16 @@ def HashMostCompactGUI(): # ------- OUTPUT GUI results portion ------- # if rc == True: hash = compute_sha1_hash_for_file(source_filename) - SG.MsgBox('Display Hash - Compact GUI', 'The SHA-1 Hash for the file\n', source_filename, hash) + SG.Popup('Display Hash - Compact GUI', 'The SHA-1 Hash for the file\n', source_filename, hash) else: - SG.MsgBox('Display Hash - Compact GUI', '* Cancelled *') + SG.Popup('Display Hash - Compact GUI', '* Cancelled *') # ---------------------------------------------------------------------- # # Our main calls two GUIs that act identically but use different calls # # ---------------------------------------------------------------------- # def main(): + HashManuallyBuiltGUI() HashManuallyBuiltGUINonContext() HashMostCompactGUI() diff --git a/Demo_ElementBrowser.py b/Demo_ElementBrowser.py new file mode 100644 index 00000000..b75d59fe --- /dev/null +++ b/Demo_ElementBrowser.py @@ -0,0 +1,24 @@ +import PySimpleGUI as sg + +def ShowMainForm(): + + listbox_values = ('Text', 'InputText', 'Checkbox', 'Radio Button', 'Listbox', 'Slider' ) + + column2 = [ [sg.Output(size=(50, 20))], + [sg.ReadFormButton('Show Element'), sg.SimpleButton('Exit')]] + + column1 = [[sg.Listbox(values=listbox_values, size=(20, len(listbox_values)), key='listbox')], + [sg.Text('', size=(10, 15))]] + + layout = [[sg.Column(column1) , sg.Column(column2)]] + + form = sg.FlexForm('Element Browser') + form.Layout(layout) + while True: + button, values = form.Read() + if button is None or button == 'Exit': + break + sg.MsgBox(button, values['listbox'][0]) + + +ShowMainForm() diff --git a/Demo_HowDoI.py b/Demo_HowDoI.py index f97c6df7..1c89cbaa 100644 --- a/Demo_HowDoI.py +++ b/Demo_HowDoI.py @@ -22,12 +22,12 @@ def HowDoI(): form = sg.FlexForm('How Do I ??', default_element_size=(30, 2), icon=DEFAULT_ICON, font=('Helvetica',' 13'), default_button_element_size=(8,2), return_keyboard_events=True) multiline_elem = sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False) - history_elem = sg.T('', size=(40,3)) + history_elem = sg.T('', size=(40,3), text_color=sg.BLUES[0]) layout = [ [sg.Text('Ask and your answer will appear here....', size=(40, 1))], [sg.Output(size=(127, 30), font=('Helvetica 10'))], - [ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'), sg.T('Num Answers',font='Helvetica 15'), sg.Checkbox('Display Full Text', key='full text', font='Helvetica 15')], - [sg.T('Command History'), history_elem], + [ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'), sg.T('Num Answers',font='Helvetica 15'), sg.Checkbox('Display Full Text', key='full text', font='Helvetica 15'), + sg.T('Command History'), history_elem], [multiline_elem, sg.ReadFormButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True), sg.SimpleButton('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))] @@ -40,6 +40,7 @@ def HowDoI(): (button, value) = form.Read() if button is 'SEND': query = value['query'].rstrip() + print(query) QueryHowDoI(query, value['Num Answers'], value['full text']) # send the string to HowDoI command_history.append(query) history_offset = len(command_history)-1 @@ -69,7 +70,7 @@ def QueryHowDoI(Query, num_answers, full_text): ''' howdoi_command = HOW_DO_I_COMMAND full_text_option = ' -a' if full_text else '' - t = subprocess.Popen(howdoi_command + ' '+ Query + ' -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE) + t = subprocess.Popen(howdoi_command + ' \"'+ Query + '\" -n ' + str(num_answers)+full_text_option, stdout=subprocess.PIPE) (output, err) = t.communicate() print('{:^88}'.format(Query.rstrip())) print('_'*60) diff --git a/Demo_Keyboard_Realtime.py b/Demo_Keyboard_Realtime.py index 25812024..ab48ce73 100644 --- a/Demo_Keyboard_Realtime.py +++ b/Demo_Keyboard_Realtime.py @@ -13,8 +13,9 @@ with sg.FlexForm("Realtime Keyboard Test", return_keyboard_events=True, use_defa print(button, value, "exiting") break if button is not None: - print(button) + if len(button) == 1: + print('%s - %s'%(button, ord(button))) + else: + print(button) elif value is None: break - - diff --git a/Demo_Keypad.py b/Demo_Keypad.py index 124f34d0..0c1fbd84 100644 --- a/Demo_Keypad.py +++ b/Demo_Keypad.py @@ -13,34 +13,33 @@ import PySimpleGUI as g # create the 2 Elements we want to control outside the form out_elem = g.Text('', size=(15, 1), font=('Helvetica', 18), text_color='red') -in_elem = g.Input(size=(10,1), do_not_clear=True, key='input') +in_elem = g.Input(size=(10, 1), do_not_clear=True, key='input') -layout = [[g.Text('Choose Test'), g.DropDown(values=['Input', 'Output', 'Some option']), g.ReadFormButton('Input Option', auto_size_button=True)], +layout = [[g.Text('Enter Your Passcode')], [in_elem], [g.ReadFormButton('1'), g.ReadFormButton('2'), g.ReadFormButton('3')], [g.ReadFormButton('4'), g.ReadFormButton('5'), g.ReadFormButton('6')], [g.ReadFormButton('7'), g.ReadFormButton('8'), g.ReadFormButton('9')], - [g.ReadFormButton('Submit'),g.ReadFormButton('0'), g.ReadFormButton('Clear')], + [g.ReadFormButton('Submit'), g.ReadFormButton('0'), g.ReadFormButton('Clear')], [out_elem], ] -form = g.FlexForm('Keypad', default_element_size=(5,2), auto_size_buttons=False) +form = g.FlexForm('Keypad', default_button_element_size=(5, 2), auto_size_buttons=False) form.Layout(layout) # Loop forever reading the form's values, updating the Input field keys_entered = '' while True: - button, values = form.Read() # read the form - if button is None: # if the X button clicked, just exit + button, values = form.Read() # read the form + if button is None: # if the X button clicked, just exit break - if button == 'Clear': # clear keys if clear button + if button is 'Clear': # clear keys if clear button keys_entered = '' elif button in '1234567890': - keys_entered = values['input'] # get what's been entered so far - keys_entered += button # add the new digit - elif button == 'Submit': + keys_entered = values['input'] # get what's been entered so far + keys_entered += button # add the new digit + elif button is 'Submit': keys_entered = values['input'] - out_elem.Update(keys_entered) # output the final string - - in_elem.Update(keys_entered) # change the form to reflect current key string + out_elem.Update(keys_entered) # output the final string + in_elem.Update(keys_entered) # change the form to reflect current key string \ No newline at end of file diff --git a/Demo_Machine_Learning.py b/Demo_Machine_Learning.py index 3d2eeb0b..118de02e 100644 --- a/Demo_Machine_Learning.py +++ b/Demo_Machine_Learning.py @@ -26,7 +26,7 @@ def MachineLearningGUI(): del(form) sg.SetOptions(text_justification='left') - return button, values + print(button, values) def CustomMeter(): @@ -37,7 +37,7 @@ def CustomMeter(): [progress_bar], [sg.Cancel()]] - # create the form + # create the form` form = sg.FlexForm('Custom Progress Meter') # display the form as a non-blocking form form.LayoutAndRead(layout, non_blocking=True) diff --git a/Demo_Matplotlib_Ping_Graph_Large.py b/Demo_Matplotlib_Ping_Graph_Large.py new file mode 100644 index 00000000..20e9b7f8 --- /dev/null +++ b/Demo_Matplotlib_Ping_Graph_Large.py @@ -0,0 +1,107 @@ +import PySimpleGUI as g +import matplotlib.pyplot as plt +import ping +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import tkinter as tk + +#================================================================================ +# Globals +# These are needed because callback functions are used. +# Need to retain state across calls +#================================================================================ +class MyGlobals: + axis_pings = None + ping_x_array = [] + ping_y_array = [] + +g_my_globals = MyGlobals() + +#================================================================================ +# Performs *** PING! *** +#================================================================================ +def run_a_ping_and_graph(): + global g_my_globals # graphs are global so that can be retained across multiple calls to this callback + + #===================== Do the ping =====================# + response = ping.quiet_ping('google.com',timeout=1000) + if response[0] == 0: + ping_time = 1000 + else: + ping_time = response[0] + #===================== Store current ping in historical array =====================# + g_my_globals.ping_x_array.append(len(g_my_globals.ping_x_array)) + g_my_globals.ping_y_array.append(ping_time) + # ===================== Only graph last 100 items =====================# + if len(g_my_globals.ping_x_array) > 100: + x_array = g_my_globals.ping_x_array[-100:] + y_array = g_my_globals.ping_y_array[-100:] + else: + x_array = g_my_globals.ping_x_array + y_array = g_my_globals.ping_y_array + + # ===================== Call graphinc functions =====================# + g_my_globals.axis_ping.clear() # clear before graphing + g_my_globals.axis_ping.plot(x_array,y_array) # graph the ping values + +#================================================================================ +# Function: Set graph titles and Axis labels +# Sets the text for the subplots +# Have to do this in 2 places... initially when creating and when updating +# So, putting into a function so don't have to duplicate code +#================================================================================ +def set_chart_labels(): + global g_my_globals + + g_my_globals.axis_ping.set_xlabel('Time') + g_my_globals.axis_ping.set_ylabel('Ping (ms)') + g_my_globals.axis_ping.set_title('Current Ping Duration', fontsize = 12) + +def draw(fig, canvas): + # Magic code that draws the figure onto the Canvas Element's canvas + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(640 / 2, 480 / 2, image=photo) + figure_canvas_agg = FigureCanvasAgg(fig) + figure_canvas_agg.draw() + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + +#================================================================================ +# Function: MAIN +#================================================================================ +def main(): + global g_my_globals + + canvas_elem = g.Canvas(size=(640, 480)) # get the canvas we'll be drawing on + # define the form layout + layout = [[g.Text('Animated Ping', size=(40,1), justification='center', font='Helvetica 20')], + [canvas_elem], + [g.ReadFormButton('Exit', size=(10,2), pad=((280, 0), 3), font='Helvetica 14')]] + + # create the form and show it without the plot + form = g.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI') + form.Layout(layout) + form.ReadNonBlocking() + + canvas = canvas_elem.TKCanvas + + fig = plt.figure() + g_my_globals.axis_ping = fig.add_subplot(1,1,1) + set_chart_labels() + plt.tight_layout() + + while True: + button, values = form.ReadNonBlocking() + if button is 'Exit' or values is None: + break + + run_a_ping_and_graph() + photo = draw(fig, canvas) + + +if __name__ == '__main__': + main() + + diff --git a/Demo_Media_Player.py b/Demo_Media_Player.py index 87e5586e..3a78113c 100644 --- a/Demo_Media_Player.py +++ b/Demo_Media_Player.py @@ -36,16 +36,16 @@ def MediaPlayerGUI(): sg.Text(' ' * 2), sg.Text(' ' * 2), sg.SimpleButton('Exit', button_color=(background,background), image_filename=image_exit, image_size=(50, 50), image_subsample=2, border_width=0)], - [sg.Text('_'*30)], + [sg.Text('_'*20)], [sg.Text(' '*30)], [ sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)), sg.Text(' ' * 2), sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)), - sg.Text(' ' * 8), + sg.Text(' ' * 2), sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15))], - [sg.Text('Bass', font=("Helvetica", 15), size=(6, 1)), - sg.Text('Treble', font=("Helvetica", 15), size=(10, 1)), + [sg.Text(' Bass', font=("Helvetica", 15), size=(9, 1)), + sg.Text('Treble', font=("Helvetica", 15), size=(7, 1)), sg.Text('Volume', font=("Helvetica", 15), size=(7, 1))] ] diff --git a/Demo_NonBlocking_Form.py b/Demo_NonBlocking_Form.py index 79693a25..d4df658b 100644 --- a/Demo_NonBlocking_Form.py +++ b/Demo_NonBlocking_Form.py @@ -66,7 +66,7 @@ def RemoteControlExample(): # This is the code that reads and updates your window button, values = form.ReadNonBlocking() if button is not None: - sg.Print(button) + print(button) if button == 'Quit' or values is None: break # time.sleep(.01) @@ -98,6 +98,7 @@ def StatusOutputExample_context_manager(): form.CloseNonBlockingForm() def main(): + StatusOutputExample() RemoteControlExample() StatusOutputExample() sg.MsgBox('End of non-blocking demonstration') diff --git a/Demo_Pi_LEDs.py b/Demo_Pi_LEDs.py new file mode 100644 index 00000000..1c08b9fe --- /dev/null +++ b/Demo_Pi_LEDs.py @@ -0,0 +1,59 @@ +import PySimpleGUI as g + +# GUI for switching an LED on and off to GPIO14 + +# GPIO and time library: +import RPi.GPIO as GPIO +import time + +# determine that GPIO numbers are used: +GPIO.setmode(GPIO.BCM) +GPIO.setup(14, GPIO.OUT) + +def SwitchLED(): + varLEDStatus = GPIO.input(14) + + if varLEDStatus == 0: + GPIO.output(14, GPIO.HIGH) + return "LED is switched ON" + else: + GPIO.output(14, GPIO.LOW) + return "LED is switched OFF" + + +def FlashLED(): + for i in range(5): + GPIO.output(14, GPIO.HIGH) + time.sleep(0.5) + GPIO.output(14, GPIO.LOW) + time.sleep(0.5) + +results_elem = g.T('', size=(30,1)) + +layout = [[g.T('Raspberry Pi LEDs')], + [results_elem], + [g.ReadFormButton('Switch LED')], + [g.ReadFormButton('Flash LED')], + [g.ReadFormButton('Show slider value')], + [g.Slider(range=(0, 100), default_value=0, orientation='h', size=(40,20), key='slider')], + [g.Exit()] + ] + +form = g.FlexForm('Raspberry Pi GUI') +form.Layout(layout) + +while True: + button, values = form.Read() + if button is None: + break + if button is 'Switch LED': + results_elem.Update(SwitchLED()) + elif button is 'Flash LED': + results_elem.Update('LED is Flashing') + form.ReadNonBlocking() + FlashLED() + results_elem.Update('') + elif button is 'Show slider value': + results_elem.Update('Slider = %s'%values['slider']) + +g.MsgBox('Done... exiting') diff --git a/Demo_Pi_Robotics.py b/Demo_Pi_Robotics.py index 607fa366..8debc1cb 100644 --- a/Demo_Pi_Robotics.py +++ b/Demo_Pi_Robotics.py @@ -18,9 +18,9 @@ def RemoteControlExample(): status_display_elem = sg.T('', justification='center', size=(19,1)) form_rows = [[sg.Text('Robotics Remote Control')], [status_display_elem], - [sg.T(' '*10), sg.RealtimeButton('Forward', image_filename=image_forward)], + [sg.T(' '*6), sg.RealtimeButton('Forward', image_filename=image_forward)], [ sg.RealtimeButton('Left', image_filename=image_left), sg.T(' '), sg.RealtimeButton('Right', image_filename=image_right)], - [sg.T(' '*10), sg.RealtimeButton('Reverse', image_filename=image_backward)], + [sg.T(' '*6), sg.RealtimeButton('Reverse', image_filename=image_backward)], [sg.T('')], [sg.Quit(button_color=('black', 'orange'))] ] @@ -51,11 +51,11 @@ def RemoteControlExample_NoGraphics(): # Make a form, but don't use context manager form = sg.FlexForm('Robotics Remote Control', auto_size_text=True) status_display_elem = sg.T('', justification='center', size=(19,1)) - form_rows = [[sg.Text('Robotics Remote Control')], + form_rows = [[sg.Text('Robotics Remote Control', justification='center')], [status_display_elem], - [sg.T(' '*10), sg.RealtimeButton('Forward')], - [ sg.RealtimeButton('Left'), sg.T(' '), sg.RealtimeButton('Right')], - [sg.T(' '*10), sg.RealtimeButton('Reverse')], + [sg.T(' '*8), sg.RealtimeButton('Forward')], + [ sg.RealtimeButton('Left'), sg.T(' '), sg.RealtimeButton('Right')], + [sg.T(' '*8), sg.RealtimeButton('Reverse')], [sg.T('')], [sg.Quit(button_color=('black', 'orange'))] ] diff --git a/Demo_Recipes.py b/Demo_Recipes.py index 529b2480..fe7c403a 100644 --- a/Demo_Recipes.py +++ b/Demo_Recipes.py @@ -11,7 +11,7 @@ def SourceDestFolders(): [sg.Submit(), sg.Cancel()]) button, values = form.LayoutAndRead(form_rows) - if button == 'Submit': + if button is 'Submit': sg.MsgBox('Submitted', values, 'The user entered source:', values['source'], 'Destination folder:', values['dest'], 'Using button', button) else: sg.MsgBoxError('Cancelled', 'User Cancelled') @@ -22,7 +22,7 @@ def MachineLearningGUI(): form = sg.FlexForm('Machine Learning Front End', font=("Helvetica", 12)) # begin with a blank form layout = [[sg.Text('Machine Learning Command Line Parameters', font=('Helvetica', 16))], - [sg.Text('Passes', size=(15, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1)), + [sg.Text('Passes', size =(15, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1)), sg.Text('Steps', size=(18, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1))], [sg.Text('ooa', size=(15, 1)), sg.In(default_text='6', size=(10, 1)), sg.Text('nn', size=(15, 1)), sg.In(default_text='10', size=(10, 1))], [sg.Text('q', size=(15, 1)), sg.In(default_text='ff', size=(10, 1)), sg.Text('ngram', size=(15, 1)), sg.In(default_text='5', size=(10, 1))], @@ -71,7 +71,7 @@ def Everything(): sg.Spin(values=('Spin Box 1', '2','3'), initial_value='Spin Box 1')], [sg.Text('_' * 80)], [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Default Folder'), sg.FolderBrowse()], - [sg.Submit(), sg.Cancel(), sg.SimpleButton('Customized', button_color=('black', '#EDE5B7'))] ] + [sg.Submit(), sg.Cancel()] ] button, values = form.LayoutAndRead(layout) @@ -81,7 +81,7 @@ def Everything(): # Be aware that tkinter, which this is based on, is picky about who frees up resources, especially if # you are running multithreaded def Everything_NoContextManager(): - form = sg.FlexForm('Everything bagel', auto_size_text=True, default_element_size=(40, 1)) + form = sg.FlexForm('Everything bagel', default_element_size=(40, 1)) layout = [ [sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25))], [sg.Text('Here is some text.... and a place to enter text')], @@ -101,7 +101,7 @@ def Everything_NoContextManager(): [sg.Text('Choose A Folder', size=(35, 1))], [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Default Folder'), sg.FolderBrowse()], - [sg.Submit(), sg.Cancel(), sg.SimpleButton('Customized', button_color=('white', '#7E6C92'))] + [sg.Submit(), sg.Cancel()] ] button, values = form.LayoutAndRead(layout) @@ -117,9 +117,9 @@ def ProgressMeter(): # Blocking form that doesn't close def ChatBot(): - with sg.FlexForm('Chat Window', auto_size_text=True, default_element_size=(30, 2)) as form: - layout = [[(sg.Text('This is where standard out is being routed', size=[40, 1]))], - [sg.Output(size=(80, 20))], + with sg.FlexForm('Chat Window', auto_size_text=True, default_element_size=(30, 2), default_button_element_size=(10,2)) as form: + layout = [[(sg.Text('This is where standard out is being routed', size=(40, 1)))], + [sg.Output(size=(80, 20), font=('Courier 10'))], [sg.Multiline(size=(70, 5), enter_submits=True), sg.ReadFormButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True), sg.SimpleButton('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]] # notice this is NOT the usual LayoutAndRead call because you don't yet want to read the form # if you call LayoutAndRead from here, then you will miss the first button click @@ -127,10 +127,9 @@ def ChatBot(): # ---===--- Loop taking in user input and using it to query HowDoI web oracle --- # while True: button, value = form.Read() - if button == 'SEND': - print(value) - else: + if button is not 'SEND': break + print(value[0]) # Shows a form that's a running counter # this is the basic design pattern if you can keep your reading of the @@ -138,16 +137,16 @@ def ChatBot(): # then you will want to use the NonBlockingPeriodicUpdateForm example def NonBlockingPeriodicUpdateForm_ContextManager(): with sg.FlexForm('Running Timer', auto_size_text=True) as form: - text_element = sg.Text('', size=(10, 2), font=('Helvetica', 20), text_color='red', justification='center') + text_element = sg.Text('', size=(15, 2), font=('Helvetica', 20), text_color='red', justification='center') layout = [[sg.Text('Non blocking GUI with updates', justification='center')], [text_element], - [sg.T(' ' * 15), sg.Quit()]] + [sg.T(' ' * 22), sg.Quit()]] form.LayoutAndRead(layout, non_blocking=True) for i in range(1,500): text_element.Update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100)) button, values = form.ReadNonBlocking() - if values is None or button == 'Quit': # if user closed the window using X + if values is None or button is 'Quit': # if user closed the window using X break time.sleep(.01) else: @@ -171,9 +170,9 @@ def NonBlockingPeriodicUpdateForm(): while True: i += 1 * (timer_running is True) button, values = form.ReadNonBlocking() - if values is None or button == 'Quit': # if user closed the window using X or clicked Quit button + if values is None or button is 'Quit': # if user closed the window using X or clicked Quit button break - elif button == 'Start/Stop': + elif button is 'Start/Stop': timer_running = not timer_running text_element.Update('{:02d}:{:02d}.{:02d}'.format((i//100)//60, (i//100)%60, i%100)) @@ -202,32 +201,35 @@ def ChangeLookAndFeel(colors): scrollbar_color=(colors['INPUT']), element_text_color=colors['TEXT']) +def OneLineGUI(): + return sg.FlexForm('Get filename example').LayoutAndRead( + [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()]]) + #=---------------------------------- main ------------------------------ def main(): - - Everything() + # button, (filename,) = OneLineGUI() + # DebugTe`st() ChatBot() - - sg.ChangeLookAndFeel('BrownBlue') + Everything() SourceDestFolders() - sg.ChangeLookAndFeel('BlueMono') - Everything() - sg.ChangeLookAndFeel('BluePurple') - Everything() - sg.ChangeLookAndFeel('LightGreen') - Everything() - sg.ChangeLookAndFeel('GreenMono') - MachineLearningGUI() - sg.ChangeLookAndFeel('TealMono') + NonBlockingPeriodicUpdateForm_ContextManager() NonBlockingPeriodicUpdateForm() ChatBot() + Everything() + sg.ChangeLookAndFeel('GreenTan') + Everything() + # ChatBot() + + SourceDestFolders() + MachineLearningGUI() + NonBlockingPeriodicUpdateForm() ProgressMeter() + DebugTest() sg.ChangeLookAndFeel('Purple') Everything_NoContextManager() NonBlockingPeriodicUpdateForm_ContextManager() sg.MsgBox('Done with all recipes') - DebugTest() if __name__ == '__main__': main() diff --git a/Demo_Script_Launcher.py b/Demo_Script_Launcher.py index 807ee013..9c7f65c8 100644 --- a/Demo_Script_Launcher.py +++ b/Demo_Script_Launcher.py @@ -14,7 +14,9 @@ def execute_command_blocking(command, *args): print(out.decode("utf-8")) if err: print(err.decode("utf-8")) - except: pass + except: + out = '' + return out # Executes command and immediately returns. Will not see anything the script outputs def execute_command_nonblocking(command, *args): diff --git a/Demo_Script_Parameters.py b/Demo_Script_Parameters.py index aa16c065..65c9c9c1 100644 --- a/Demo_Script_Parameters.py +++ b/Demo_Script_Parameters.py @@ -21,5 +21,5 @@ else: fname = sys.argv[1] if not fname: - sg.MsgBox("Cancel", "No filename supplied") + sg.Popup("Cancel", "No filename supplied") raise SystemExit("Cancelling: no filename supplied") diff --git a/Demo_Super_Simple_Form.py b/Demo_Super_Simple_Form.py index 54726258..e404d4e8 100644 --- a/Demo_Super_Simple_Form.py +++ b/Demo_Super_Simple_Form.py @@ -1,17 +1,31 @@ import PySimpleGUI as sg +# Very basic form. Return values as a dictionary +form = sg.FlexForm('Simple data entry form') # begin with a blank form + +layout = [ + [sg.Text('Please enter your Name, Address, Phone')], + [sg.Text('Name', size=(15, 1)), sg.InputText('name', key='name')], + [sg.Text('Address', size=(15, 1)), sg.InputText('address', key='address')], + [sg.Text('Phone', size=(15, 1)), sg.InputText('phone', key='phone')], + [sg.Ok(), sg.Cancel()] + ] + +button, values = form.LayoutAndRead(layout) + +print(button, values['name'], values['address'], values['phone']) + form = sg.FlexForm('Simple data entry form') # begin with a blank form layout = [ [sg.Text('Please enter your Name, Address, Phone')], - [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='name')], - [sg.Text('Address', size=(15, 1)), sg.InputText('2', key='address')], - [sg.Text('Phone', size=(15, 1)), sg.InputText('3', key='phone')], - [sg.Submit(), sg.Cancel()] + [sg.Text('Name', size=(15, 1)), sg.InputText('name')], + [sg.Text('Address', size=(15, 1)), sg.InputText('address')], + [sg.Text('Phone', size=(15, 1)), sg.InputText('phone')], + [sg.Ok(), sg.Cancel()] ] button, values = form.LayoutAndRead(layout) -sg.MsgBox(button, values['name'], values['address'], values['phone']) - -print(values) +name, address, phone = values +sg.MsgBox(button, values[0], values[1], values[2]) \ No newline at end of file diff --git a/Demo_Tabbed_Form.py b/Demo_Tabbed_Form.py index 00ac6fd5..3cde91ca 100644 --- a/Demo_Tabbed_Form.py +++ b/Demo_Tabbed_Form.py @@ -35,7 +35,7 @@ def eBaySuperSearcherGUI(): # the form layout with sg.FlexForm('EBay Super Searcher', auto_size_text=True) as form: - with sg.FlexForm('EBay Super Searcher') as form2: + with sg.FlexForm('EBay Super Searcher', auto_size_text=False) as form2: layout_tab_1 = [[sg.Text('eBay Super Searcher!', size=(60,1), font=('helvetica', 15))], [sg.Text('Choose base configuration to run')], [sg.InputCombo(configs)], @@ -65,7 +65,6 @@ def eBaySuperSearcherGUI(): if i == 0: continue # skip first one layout_tab_2.append([sg.Radio(cat,'CATUS'), sg.Radio(german_categories[i],'CATDE')]) - layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))]) layout_tab_2.append([sg.Text('US Search String Override')]) layout_tab_2.append([sg.InputText(size=(100,1))]) @@ -82,6 +81,7 @@ def eBaySuperSearcherGUI(): if __name__ == '__main__': + # sg.SetOptions(background_color='white') results = eBaySuperSearcherGUI() print(results) sg.MsgBox('Results', results) \ No newline at end of file From 5d3481025ee6d35686ea85f6c95243f6368dd9ba Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Tue, 4 Sep 2018 19:47:14 -0400 Subject: [PATCH 2/2] Initial Checkin --- Demo_Timer.py | 47 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 Demo_Timer.py diff --git a/Demo_Timer.py b/Demo_Timer.py new file mode 100644 index 00000000..9031af18 --- /dev/null +++ b/Demo_Timer.py @@ -0,0 +1,47 @@ +import PySimpleGUI as sg +import time + +# form that doen't block +# good for applications with an loop that polls hardware +def Timer(): + sg.ChangeLookAndFeel('TealMono') + # Make a form, but don't use context manager + form = sg.FlexForm('Running Timer', auto_size_text=True) + # Create a text element that will be updated with status information on the GUI itself + # Create the rows + form_rows = [[sg.Text('Stopwatch')], + [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], + [sg.ReadFormButton('Pause/Resume'), sg.ReadFormButton('Reset')]] + # Layout the rows of the form and perform a read. Indicate the form is non-blocking! + form.LayoutAndRead(form_rows, non_blocking=True) + + # + # Some place later in your code... + # You need to perform a ReadNonBlocking on your form every now and then or + # else it won't refresh. + # + # your program's main loop + i = 0 + paused = False + while (True): + # This is the code that reads and updates your window + form.FindElement('text').Update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100)) + button, values = form.ReadNonBlocking() + + if values is None: + break + + if button is 'Reset': + i=0 + elif button is 'Pause/Resume': + paused = not paused + + if not paused: + i += 1 + # Your code begins here + time.sleep(.01) + + # Broke out of main loop. Close the window. + form.CloseNonBlockingForm() + +Timer() \ No newline at end of file