diff --git a/Demo_All_Widgets.py b/Demo_All_Widgets.py index 0a89a42f..d4cee3c3 100644 --- a/Demo_All_Widgets.py +++ b/Demo_All_Widgets.py @@ -1,45 +1,40 @@ #!/usr/bin/env Python3 - import PySimpleGUI as sg +sg.ChangeLookAndFeel('GreenTan') -def Everything(): - sg.ChangeLookAndFeel('Dark') +form = sg.FlexForm('Everything bagel', default_element_size=(40, 1), grab_anywhere=False) - form = sg.FlexForm('Everything bagel', default_element_size=(40, 1), grab_anywhere=False) +column1 = [[sg.Text('Column 1', background_color='#F7F3EC', 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')]] - 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')]] +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')], + [sg.InputText('This is my text')], + [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='#F7F3EC')], + [sg.Text('_' * 80)], + [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()] +] - 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')], - [sg.InputText('This is my text')], - [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='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'), - sg.InputText('Default Folder'), sg.FolderBrowse()], - [sg.Submit(), sg.Cancel()] - ] +button, values = form.LayoutAndRead(layout) - button, values = form.LayoutAndRead(layout) - - sg.Popup('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) -if __name__ == '__main__': - Everything() diff --git a/Demo_Desktop_Floating_Toolbar.py b/Demo_Desktop_Floating_Toolbar.py new file mode 100644 index 00000000..5b17d327 --- /dev/null +++ b/Demo_Desktop_Floating_Toolbar.py @@ -0,0 +1,77 @@ +import PySimpleGUI as sg +import subprocess +import os +import sys + +""" + Demo_Toolbar - A floating toolbar with quick launcher + + One cool PySimpleGUI demo. Shows borderless windows, grab_anywhere, tight button layout + You can setup a specific program to launch when a button is clicked, or use the + Combobox to select a .py file found in the root folder, and run that file. + +""" + +ROOT_PATH = './' + +def Launcher(): + + def print(line): + form.FindElement('output').Update(line) + + sg.ChangeLookAndFeel('Dark') + + namesonly = [f for f in os.listdir(ROOT_PATH) if f.endswith('.py') ] + + sg.SetOptions(element_padding=(0,0), button_element_size=(12,1), auto_size_buttons=False) + layout = [[sg.Combo(values=namesonly, size=(35,30), key='demofile'), + sg.ReadFormButton('Run', button_color=('white', '#00168B')), + sg.ReadFormButton('Program 1'), + sg.ReadFormButton('Program 2'), + sg.ReadFormButton('Program 3', button_color=('white', '#35008B')), + sg.SimpleButton('EXIT', button_color=('white','firebrick3'))], + [sg.T('', text_color='white', size=(50,1), key='output')]] + + form = sg.FlexForm('Floating Toolbar', no_titlebar=True, keep_on_top=True) + + form.Layout(layout) + + # ---===--- Loop taking in user input and using it to query HowDoI --- # + while True: + (button, value) = form.Read() + if button is 'EXIT' or button is None: + break # exit button clicked + if button is 'Program 1': + print('Run your program 1 here!') + elif button is 'Program 2': + print('Run your program 2 here!') + elif button is 'Run': + file = value['demofile'] + print('Launching %s'%file) + ExecuteCommandSubprocess('python', os.path.join(ROOT_PATH, file)) + else: + print(button) + +def ExecuteCommandSubprocess(command, *args, wait=False): + try: + if sys.platform == 'linux': + arg_string = '' + for arg in args: + arg_string += ' ' + str(arg) + sp = subprocess.Popen(['python3' + arg_string, ], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + else: + sp = subprocess.Popen([command, list(args)], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + + if wait: + out, err = sp.communicate() + if out: + print(out.decode("utf-8")) + if err: + print(err.decode("utf-8")) + except: pass + + + +if __name__ == '__main__': + Launcher() + diff --git a/docs/cookbook.md b/docs/cookbook.md index 1a89b3af..7352c3ad 100644 --- a/docs/cookbook.md +++ b/docs/cookbook.md @@ -988,7 +988,7 @@ Use the upper half to generate your hash code. Then paste it into the code in t password_hash = sha1hash.hexdigest() if password_hash == hash: return True - else: + else: return False login_password_hash = '5baa61e4c9b93f3f0682250b6cf8331b7ee68fd8' @@ -1089,6 +1089,81 @@ You can easily change colors to match your background by changing a couple of pa Launcher() + + +## Desktop Floating Widget + +This is a little widget you can leave running on your desktop. Will hopefully see more of these for things like checking email, checking server pings, displaying system information, dashboards, etc +. +Much of the code is handling the button states in a fancy way. It could be much simpler if you don't change the button text based on state. + + + import PySimpleGUI as sg + import time + + """ + Timer Desktop Widget Creates a floating timer that is always on top of other windows You move it by grabbing anywhere on the window Good example of how to do a non-blocking, polling program using PySimpleGUI Can be used to poll hardware when running on a Pi NOTE - you will get a warning message printed when you exit using exit button. + It will look something like: invalid command name "1616802625480StopMove"""" + + # ---------------- Create Form ---------------- + sg.ChangeLookAndFeel('Black') + sg.SetOptions(element_padding=(0,0)) + # Make a form, but don't use context manager + # Create the form layout + form_rows = [[sg.Text('')], + [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], + [sg.ReadFormButton('Pause', key='button', button_color=('white', '#001480')), sg.ReadFormButton('Reset', button_color=('white', '#007339')), sg.Exit(button_color=('white','firebrick4'))]] + # Layout the rows of the form and perform a read. Indicate the form is non-blocking! + form = sg.FlexForm('Running Timer', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True) + form.Layout(form_rows) + # + # ---------------- main loop ---------------- + current_time = 0 + paused = False + start_time = int(round(time.time()*100)) + while (True): + # --------- Read and update window -------- + if not paused: + button, values = form.ReadNonBlocking() + current_time = int(round(time.time()*100)) - start_time + else: + button, values = form.Read() + # --------- Do Button Operations -------- + if values is None or button == 'Exit': + break + if button is 'Reset': + start_time = int(round(time.time()*100)) + current_time = 0 + paused_time = start_time + elif button == 'Pause': + paused = True + paused_time = int(round(time.time()*100)) + element = form.FindElement('button') + element.Update(new_text='Run') + elif button == 'Run': + paused = False + start_time = start_time + int(round(time.time()*100)) - paused_time + element = form.FindElement('button') + element.Update(new_text='Pause') + + # --------- Display timer in window -------- + form.FindElement('text').Update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60, + (current_time // 100) % 60, + current_time % 100)) + time.sleep(.01) + + + # --------- After loop -------- + + # Broke out of main loop. Close the window. + form.CloseNonBlockingForm() + + + + + + + ## Menus Menus are nothing more than buttons that live in a menu-bar. When you click on a menu item, you get back a "button" with that menu item's text, just as you would had that text been on a button.