Major update of all demo programs to use new PEP8 bindings, etc

This commit is contained in:
PySimpleGUI 2019-10-23 16:10:03 -04:00
parent 3f7c87c562
commit 7f52778bcc
307 changed files with 19546 additions and 3297 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

View file

@ -1,11 +1,11 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
'''
Example of (almost) all widgets, that you can use in PySimpleGUI.
'''
sg.ChangeLookAndFeel('GreenTan')
import PySimpleGUI as sg
sg.change_look_and_feel('GreenTan')
# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
@ -14,41 +14,49 @@ menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']],
# ------ Column Definition ------ #
column1 = [[sg.Text('Column 1', background_color='lightblue', 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 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.Menu(menu_def, tearoff=True)],
[sg.Text('(Almost) All widgets in one Window!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
[sg.Text('(Almost) All widgets in one Window!', size=(
30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)],
[sg.Text('Here is some text.... and a place to enter text')],
[sg.InputText('This is my text')],
[sg.Frame(layout=[
[sg.Checkbox('Checkbox', size=(10,1)), sg.Checkbox('My second checkbox!', default=True)],
[sg.Radio('My first Radio! ', "RADIO1", default=True, size=(10,1)), sg.Radio('My second Radio!', "RADIO1")]], title='Options',title_color='red', relief=sg.RELIEF_SUNKEN, tooltip='Use these to set flags')],
[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.CBox('Checkbox', size=(10, 1)),
sg.CBox('My second checkbox!', default=True)],
[sg.Radio('My first Radio! ', "RADIO1", default=True, size=(10, 1)),
sg.Radio('My second Radio!', "RADIO1")]], title='Options',
title_color='red',
relief=sg.RELIEF_SUNKEN,
tooltip='Use these to set flags')],
[sg.MLine(default_text='This is the default Text should you decide not to type anything', size=(35, 3)),
sg.MLine(default_text='A second multi-line', size=(35, 3))],
[sg.Combo(('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.OptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))],
[sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)),
sg.Frame('Labelled Group',[[
sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=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='lightblue')]])],
sg.Frame('Labelled Group', [[
sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, tick_interval=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.Col(column1, background_color='lightblue')]])
],
[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.Text('Your Folder', size=(15, 1), justification='right'),
sg.InputText('Default Folder'), sg.FolderBrowse()],
[sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]]
window = sg.Window('Everything bagel', default_element_size=(40, 1), grab_anywhere=False).Layout(layout)
event, values = window.Read()
window = sg.Window('Everything bagel', layout,
default_element_size=(40, 1), grab_anywhere=False)
sg.Popup('Title',
event, values = window.read()
sg.popup('Title',
'The results of the window.',
'The button clicked was "{}"'.format(event),
'The values are', values)

File diff suppressed because one or more lines are too long

View file

@ -1,6 +1,24 @@
import PySimpleGUI as sg
import random
# Bars drawing in PySimpleGUI
#
# .--.
# | |
# .--.| |.--.
# | || || |
# | || || |
# | || || |
# .--.| || || |
# .--.| || || || |.--.
# | || || || || || |
# | || || || || || |
# .--.| || || || || || |.--.
# | || || || || || || || |.--.
# | || || || || || || || || |
# '--''--''--''--''--''--''--''--''--'
BAR_WIDTH = 50
BAR_SPACING = 75
EDGE_OFFSET = 3
@ -9,21 +27,25 @@ DATA_SIZE = (500,500)
graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE)
layout = [[sg.Text('Bar graphs using PySimpleGUI')],
layout = [[sg.Text('Labelled Bar graphs using PySimpleGUI')],
[graph],
[sg.Button('OK')]]
[sg.Button('OK'), sg.T('Click to display more data'), sg.Exit()]]
window = sg.Window('Window Title', layout)
while True:
event, values = window.Read()
graph.Erase()
if event is None:
event, values = window.read()
if event in (None, 'Exit'):
break
graph.erase()
for i in range(7):
graph_value = random.randint(0, 400)
graph.DrawRectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
graph.draw_rectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='blue')
graph.DrawText(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
window.Close()
graph.draw_text(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
window.close()
# del window
while True:
pass

View file

@ -1,27 +1,27 @@
# Base64 Encoder - encodes a folder of PNG files and creates a .py file with definitions
import PySimpleGUI as sg
import os
import base64
'''
Base64 Encoder - encodes a folder of PNG files and creates a .py file with definitions
Make base64 images
input: folder with .png .ico .gif 's
output: output.py file with variables
'''
OUTPUT_FILENAME = 'output.py'
def main():
# folder = r'C:\Python\PycharmProjects\GooeyGUI\Uno Cards'
folder=''
folder = sg.PopupGetFolder('Source folder for images\nImages will be encoded and results saved to %s'%OUTPUT_FILENAME,
title='Base64 Encoder',
default_path=folder, initial_folder=folder )
OUTPUT_FILENAME = 'output.py'
if folder is None or folder == '':
sg.PopupCancel('Cancelled - No valid folder entered')
folder = sg.popup_get_folder('Source folder for images\nImages will be encoded and results saved to %s'%OUTPUT_FILENAME,
title='Base64 Encoder')
if not folder:
sg.popup_cancel('Cancelled - No valid folder entered')
return
try:
namesonly = [f for f in os.listdir(folder) if f.endswith('.png') or f.endswith('.ico') or f.endswith('.gif')]
except:
sg.PopupCancel('Cancelled - No valid folder entered')
sg.popup_cancel('Cancelled - No valid folder entered')
return
outfile = open(os.path.join(folder, OUTPUT_FILENAME), 'w')
@ -29,12 +29,11 @@ def main():
for i, file in enumerate(namesonly):
contents = open(os.path.join(folder, file), 'rb').read()
encoded = base64.b64encode(contents)
outfile.write('\n{} = {}\n\n'.format(file[:file.index(".")], encoded))
sg.OneLineProgressMeter('Base64 Encoding', i+1, len(namesonly),key='_METER_')
outfile.write('\n{} = {}'.format(file[:file.index(".")], encoded))
sg.OneLineProgressMeter('Base64 Encoding', i+1, len(namesonly), key='-METER-')
outfile.close()
sg.Popup('Completed!', 'Encoded %s files'%(i+1))
sg.popup('Completed!', 'Encoded %s files'%(i+1))
if __name__ == '__main__':
main()
main()

View file

@ -1,22 +1,17 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Turn off padding in order to get a really tight looking layout.
"""
# Turn off padding in order to get a really tight looking layout.
sg.ChangeLookAndFeel('Dark')
sg.SetOptions(element_padding=(0, 0))
sg.change_look_and_feel('Dark')
sg.set_options(element_padding=(0, 0))
layout = [[sg.T('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User 2'), size=(20, 1)),
sg.T('0', size=(8, 1))],
[sg.T('Customer:', pad=((3, 0), 0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20, 1)),
sg.T('1', size=(8, 1))],
[sg.T('Notes:', pad=((3, 0), 0)), sg.In(size=(44, 1), background_color='white', text_color='black')],
layout = [[sg.Text('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User 2'), size=(20, 1)),
sg.Text('0', size=(8, 1))],
[sg.Text('Customer:', pad=((3, 0), 0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20, 1)),
sg.Text('1', size=(8, 1))],
[sg.Text('Notes:', pad=((3, 0), 0)),
sg.Input(size=(44, 1), background_color='white', text_color='black')],
[sg.Button('Start', button_color=('white', 'black')),
sg.Button('Stop', button_color=('gray50', 'black')),
sg.Button('Reset', button_color=('white', '#9B0023')),
@ -24,6 +19,7 @@ layout = [[sg.T('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User
sg.Button('Exit', button_color=('white', '#00406B'))]]
window = sg.Window("Borderless Window",
layout,
default_element_size=(12, 1),
text_justification='r',
auto_size_text=False,
@ -32,11 +28,7 @@ window = sg.Window("Borderless Window",
grab_anywhere=True,
default_button_element_size=(12, 1))
window.Layout(layout)
while True:
event, values = window.Read()
if event is None or event == 'Exit':
event, values = window.read()
if event in (None, 'Exit'):
break

View file

@ -1,33 +1,37 @@
#!/usr/bin/env python
import winsound
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
if not sys.platform.startswith('win'):
sg.PopupError('Sorry, you gotta be on Windows')
sys.exit()
import winsound
sg.popup_error('Sorry, you gotta be on Windows')
sys.exit(0)
# sg.ChangeLookAndFeel('Dark')
# sg.SetOptions(element_padding=(0,0))
# sg.change_look_and_feel('Dark')
# sg.set_options(element_padding=(0,0))
layout = [
[sg.Button('Start', button_color=('white', 'black'), key='start'),
sg.Button('Stop', button_color=('white', 'black'), key='stop'),
sg.Button('Reset', button_color=('white', 'firebrick3'), key='reset'),
sg.Button('Submit', button_color=('white', 'springgreen4'), key='submit')]
]
[sg.Button('Start', button_color=('white', 'black'), key='start'),
sg.Button('Stop', button_color=('white', 'black'), key='stop'),
sg.Button('Reset', button_color=('white', 'firebrick3'), key='reset'),
sg.Button('Submit', button_color=('white', 'springgreen4'), key='submit')]
]
window = sg.Window("Button Click", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False, default_button_element_size=(12,1), use_default_focus=False).Layout(layout).Finalize()
window = sg.Window("Button Click", layout, finalize=True,
default_element_size=(12, 1), text_justification='r',
auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(12, 1), use_default_focus=False )
window.FindElement('submit').Update(disabled=True)
window['submit'].update(disabled=True)
recording = have_data = False
while True:
event, values = window.Read(timeout=100)
event, values = window.read(timeout=100)
if event is None:
sys.exit(69)
winsound.PlaySound("ButtonClick.wav", 1) if event != sg.TIMEOUT_KEY else None
break
if event != sg.TIMEOUT_KEY:
winsound.PlaySound("ButtonClick.wav", 1)
window.close()

View file

@ -1,10 +1,6 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Demo Button Function Calls
@ -18,21 +14,24 @@ It is quite easy to simulate these callbacks however. The way to do this is to
to your Event Loop
"""
def callback_function1():
sg.Popup('In Callback Function 1')
sg.popup('In Callback Function 1')
print('In the callback function 1')
def callback_function2():
sg.Popup('In Callback Function 2')
sg.popup('In Callback Function 2')
print('In the callback function 2')
layout = [ [sg.Text('Demo of Button Callbacks')],
[sg.Button('Button 1'), sg.Button('Button 2')] ]
window = sg.Window('Button Callback Simulation').Layout(layout)
layout = [[sg.Text('Demo of Button Callbacks')],
[sg.Button('Button 1'), sg.Button('Button 2')]]
window = sg.Window('Button Callback Simulation', layout)
while True: # Event Loop
event, values = window.Read()
event, values = window.read()
if event is None:
break
elif event == 'Button 1':
@ -40,4 +39,4 @@ while True: # Event Loop
elif event == 'Button 2':
callback_function2() # call the "Callback" function
window.Close()
window.close()

View file

@ -1,51 +1,60 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Demonstrates using a "tight" layout with a Dark theme.
Shows how button states can be controlled by a user application. The program manages the disabled/enabled
states for buttons and changes the text color to show greyed-out (disabled) buttons
"""
sg.ChangeLookAndFeel('Dark')
sg.SetOptions(element_padding=(0,0))
sg.change_look_and_feel('Dark')
sg.set_options(element_padding=(0, 0))
layout = [[sg.T('User:', pad=((3,0),0)), sg.OptionMenu(values = ('User 1', 'User 2'), size=(20,1)), sg.T('0', size=(8,1))],
[sg.T('Customer:', pad=((3,0),0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20,1)), sg.T('1', size=(8,1))],
[sg.T('Notes:', pad=((3,0),0)), sg.In(size=(44,1), background_color='white', text_color='black')],
[sg.Button('Start', button_color=('white', 'black'), key='_Start_'),
sg.Button('Stop', button_color=('white', 'black'), key='_Stop_'),
sg.Button('Reset', button_color=('white', 'firebrick3'), key='_Reset_'),
sg.Button('Submit', button_color=('white', 'springgreen4'), key='_Submit_')]]
layout = [[sg.Text('User:', pad=((3, 0), 0)), sg.OptionMenu(values=('User 1', 'User 2'), size=(20, 1)), sg.Text('0', size=(8, 1))],
[sg.Text('Customer:', pad=((3, 0), 0)), sg.OptionMenu(
values=('Customer 1', 'Customer 2'), size=(20, 1)), sg.Text('1', size=(8, 1))],
[sg.Text('Notes:', pad=((3, 0), 0)), sg.Input(size=(44, 1),
background_color='white', text_color='black')],
[sg.Button('Start', button_color=('white', 'black'), key='-Start-'),
sg.Button('Stop', button_color=('white', 'black'), key='-Stop-'),
sg.Button('Reset', button_color=('white', 'firebrick3'), key='-Reset-'),
sg.Button('Submit', button_color=('white', 'springgreen4'), key='-Submit-')]]
window = sg.Window("Time Tracker", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(12,1)).Layout(layout).Finalize()
window = sg.Window("Time Tracker", layout,
default_element_size=(12, 1),
text_justification='r',
auto_size_text=False,
auto_size_buttons=False,
default_button_element_size=(12, 1),
finalize=True)
for key, state in {'_Start_': False, '_Stop_': True, '_Reset_': True, '_Submit_': True}.items():
window.FindElement(key).Update(disabled=state)
for key, state in {'-Start-': False, '-Stop-': True, '-Reset-': True, '-Submit-': True}.items():
window[key].update(disabled=state)
recording = have_data = False
while True:
event, values = window.Read()
event, values = window.read()
print(event)
if event is None:
sys.exit(69)
if event == '_Start_':
for key, state in {'_Start_':True, '_Stop_':False, '_Reset_':False, '_Submit_':True}.items():
window.FindElement(key).Update(disabled=state)
break
if event == '-Start-':
for key, state in {'-Start-': True, '-Stop-': False, '-Reset-': False, '-Submit-': True}.items():
window[key].update(disabled=state)
recording = True
elif event == '_Stop_' and recording:
[window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':False, '_Submit_':False}.items()]
elif event == '-Stop-' and recording:
[window[key].update(disabled=value) for key, value in {
'-Start-': False, '-Stop-': True, '-Reset-': False, '-Submit-': False}.items()]
recording = False
have_data = True
elif event == '_Reset_':
[window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':True, '_Submit_':True}.items()]
elif event == '-Reset-':
[window[key].update(disabled=value) for key, value in {
'-Start-': False, '-Stop-': True, '-Reset-': True, '-Submit-': True}.items()]
recording = False
have_data = False
elif event == '_Submit_' and have_data:
[window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':True, '_Submit_':False}.items()]
elif event == '-Submit-' and have_data:
[window[key].update(disabled=value) for key, value in {
'-Start-': False, '-Stop-': True, '-Reset-': True, '-Submit-': False}.items()]
recording = False
window.close()

File diff suppressed because one or more lines are too long

View file

@ -1,50 +1,44 @@
#!/usr/bin/env python
import sys
import time
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
def show_win():
sg.SetOptions(border_width=0, margins=(0,0), element_padding=(5,3))
sg.set_options(border_width=0, margins=(0, 0), element_padding=(5, 3))
frame_layout = [
[sg.Button('', image_data=mac_red,
button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='-exit-'),
sg.Button('', image_data=mac_orange,
button_color=('white', sg.COLOR_SYSTEM_DEFAULT)),
sg.Button('', image_data=mac_green,
button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='-minimize-'),
sg.Text(' '*40)], ]
frame_layout = [ [sg.Button('', image_data=mac_red, button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='_exit_'),
sg.Button('', image_data=mac_orange, button_color=('white', sg.COLOR_SYSTEM_DEFAULT)),
sg.Button('', image_data=mac_green, button_color=('white', sg.COLOR_SYSTEM_DEFAULT), key='_minimize_'),
sg.Text(' '*40)],]
layout = [[sg.Frame('', frame_layout)],
[sg.Text('')],
[sg.Text('My Mac-alike window', size=(25, 2))], ]
layout = [[sg.Frame('',frame_layout)],
[sg.T('')],
[ sg.Text(' My Mac-alike window', size=(25,2)) ],]
window = sg.Window('My new window',
no_titlebar=True,
grab_anywhere=True,
alpha_channel=0,
).Layout(layout).Finalize()
window = sg.Window('My new window', layout,
no_titlebar=True, grab_anywhere=True,
alpha_channel=0, finalize=True)
for i in range(100):
window.SetAlpha(i/100)
window.eet_alpha(i/100)
time.sleep(.01)
while True: # Event Loop
event, values = window.Read()
if event is None or event == '_exit_':
event, values = window.read()
if event is None or event == '-exit-':
break
if event == '_minimize_':
if event == '-minimize-':
# window.Minimize() # cannot minimize a window with no titlebar
pass
print(event, values)
mac_red = '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'
mac_green = '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'
mac_orange = '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'
show_win()
show_win()

File diff suppressed because one or more lines are too long

View file

@ -1,15 +1,13 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
layout = [[sg.T('Calendar Test')],
[sg.In('', size=(20,1), key='input')],
layout = [[sg.Text('Calendar Test')],
[sg.Input('', size=(20, 1), key='input')],
[sg.CalendarButton('Choose Date', target='input', key='date')],
[sg.Ok(key=1)]]
window = sg.Window('Calendar', grab_anywhere=False).Layout(layout)
event,values = window.Read()
sg.Popup(values['input'])
window = sg.Window('Calendar', layout, grab_anywhere=False)
event, values = window.read()
sg.popup(values['input'])
windowclose()

View file

@ -1,22 +1,18 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
layout = [
[sg.Canvas(size=(150, 150), background_color='red', key='canvas')],
[sg.T('Change circle color to:'), sg.Button('Red'), sg.Button('Blue')]
]
[sg.Canvas(size=(150, 150), background_color='red', key='canvas')],
[sg.Text('Change circle color to:'), sg.Button('Red'), sg.Button('Blue')]
]
window = sg.Window('Canvas test').Layout(layout).Finalize()
window = sg.Window('Canvas test', layout, finalize=True)
cir = window.FindElement('canvas').TKCanvas.create_oval(50, 50, 100, 100)
cir = window['canvas'].TKCanvas.create_oval(50, 50, 100, 100)
while True:
event, values = window.Read()
event, values = window.read()
if event is None:
break
if event in ('Blue', 'Red'):
window.FindElement('canvas').TKCanvas.itemconfig(cir, fill=event)
window['canvas'].TKCanvas.itemconfig(cir, fill=event)

View file

@ -7,12 +7,13 @@ import PySimpleGUI as sg
In this program, as soon as a listbox entry is clicked, the read returns.
"""
sg.ChangeLookAndFeel('GreenTan')
sg.change_look_and_feel('GreenTan')
layout = [ [sg.Text('Look and Feel Browser')],
[sg.Text('Click a look and feel color to see demo window')],
[sg.Listbox(values=sg.list_of_look_and_feel_values(), size=(20,12), key='-LIST-', enable_events=True)],
[sg.Button('Show Window'), sg.Button('Exit')] ]
layout = [[sg.Text('Look and Feel Browser')],
[sg.Text('Click a look and feel color to see demo window')],
[sg.Listbox(values=sg.list_of_look_and_feel_values(),
size=(20, 12), key='-LIST-', enable_events=True)],
[sg.Button('Show Window'), sg.Button('Exit')]]
window = sg.Window('Look and Feel Browser', layout)
@ -22,4 +23,5 @@ while True: # Event Loop
break
sg.change_look_and_feel(values['-LIST-'][0])
sg.popup_get_text('This is {}'.format(values['-LIST-'][0]))
window.close()

View file

@ -1,48 +1,46 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Demonstrates the new change_submits parameter for inputtext elements
It ONLY submits when a button changes the field, not normal user input
Be careful on persistent forms to not clear the input
"""
layout = [[ sg.Text('Test of reading input field') ],
[sg.T('This input is normal'), sg.In()],
[sg.T('This input change submits'), sg.In(change_submits=True)],
[sg.T('This multiline input change submits'), sg.Multiline(change_submits=True, do_not_clear=True)],
[sg.T('This input is normal'), sg.In(), sg.FileBrowse()],
[sg.T('File Browse submits'), sg.In(change_submits=True,
do_not_clear=True,
key='_in1_'), sg.FileBrowse()],
[sg.T('Color Chooser submits'), sg.In(change_submits=True,
do_not_clear=True,
key='_in2_'), sg.ColorChooserButton('Color...', target=(sg.ThisRow, -1))],
[sg.T('Folder Browse submits'), sg.In(change_submits=True,
do_not_clear=True,
key='_in3_'), sg.FolderBrowse()],
[sg.T('Calendar Chooser submits'), sg.In(change_submits=True,
do_not_clear=True,
key='_in4_'), sg.CalendarButton('Date...', target=(sg.ThisRow, -1))],
[sg.T('Disabled input submits'), sg.In(change_submits=True,
do_not_clear=True,
disabled=True,
key='_in5'), sg.FileBrowse()],
[sg.T('This input clears after submit'),sg.In(change_submits=True,
key='_in6_'), sg.FileBrowse()],
[ sg.Button('Read')]]
layout = [[sg.Text('Test of reading input field')],
[sg.Text('This input is normal'), sg.Input()],
[sg.Text('This input change submits'),
sg.Input(change_submits=True)],
[sg.Text('This multiline input change submits'),
sg.ML('', change_submits=True)],
[sg.Text('This input is normal'),
sg.Input(), sg.FileBrowse()],
[sg.Text('File Browse submits'),
sg.Input(change_submits=True,
key='-in1-'), sg.FileBrowse()],
[sg.Text('Color Chooser submits'),
sg.Input(change_submits=True,
key='-in2-'), sg.ColorChooserButton('Color...', target=(sg.ThisRow, -1))],
[sg.Text('Folder Browse submits'),
sg.Input(change_submits=True,
key='-in3-'), sg.FolderBrowse()],
[sg.Text('Calendar Chooser submits'),
sg.Input(change_submits=True,
key='-in4-'), sg.CalendarButton('Date...', target=(sg.ThisRow, -1))],
[sg.Text('Disabled input submits'),
sg.Input(change_submits=True,
disabled=True,
key='_in5'), sg.FileBrowse()],
[sg.Text('This input clears after submit'),
sg.Input(change_submits=True, key='-in6-'), sg.FileBrowse()],
[sg.Button('Read')]]
window = sg.Window('Demonstration of InputText with change_submits',
auto_size_text=False,
default_element_size=(22,1),
text_justification='right',
).Layout(layout)
layout, auto_size_text=False, default_element_size=(22, 1),
text_justification='right')
while True: # Event Loop
event, values = window.Read()
event, values = window.read()
print(event, values)
if event is None:
break
window.close()

View file

@ -1,9 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
'''
A chat window. Add call to your send-routine, print the response and you're done
@ -15,27 +11,27 @@ Note that the size of the display on repl.it is smaller than most, so the sizes
Multiline and Output text areas were reduced in the online version. Nothing else was changed
'''
sg.ChangeLookAndFeel('GreenTan') # give our window a spiffy set of colors
# give our window a spiffy set of colors
sg.change_look_and_feel('GreenTan')
layout = [ [sg.Text('Your output will go here', size=(40, 1))],
[sg.Output(size=(127, 30), font=('Helvetica 10'))],
[sg.Multiline(size=(85, 5), enter_submits=True, key='query'),
sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
layout = [[sg.Text('Your output will go here', size=(40, 1))],
[sg.Output(size=(127, 30), font=('Helvetica 10'))],
[sg.MLine(size=(85, 5), enter_submits=True, key='query'),
sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
window = sg.Window('Chat window',
layout,
default_element_size=(30, 2),
font=('Helvetica',' 13'),
default_button_element_size=(8,2)).Layout(layout)
font=('Helvetica', ' 13'),
default_button_element_size=(8, 2))
# ---===--- Loop taking in user input and using it --- #
while True:
event, value = window.Read()
event, value = window.read()
if event == 'SEND':
query = value['query'].rstrip()
# EXECUTE YOUR COMMAND HERE
print('The command you entered was {}'.format(query))
elif event in (None, 'EXIT'): # quit if exit button or X
break
sys.exit(69)

View file

@ -1,9 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
'''
A chatbot with history
@ -15,46 +11,60 @@ Special keyboard keys:
Control C - exit form
'''
def ChatBotWithHistory():
# ------- Make a new Window ------- #
sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors
# give our form a spiffy set of colors
sg.change_look_and_feel('GreenTan')
layout = [[sg.Text('Your output will go here', size=(40, 1))],
[sg.Output(size=(127, 30), font=('Helvetica 10'))],
[sg.T('Command History'), sg.T('', size=(20,3), key='history')],
[sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
layout = [[sg.Text('Your output will go here', size=(40, 1))],
[sg.Output(size=(127, 30), font=('Helvetica 10'))],
[sg.Text('Command History'),
sg.Text('', size=(20, 3), key='history')],
[sg.ML(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
window = sg.Window('Chat window with history', default_element_size=(30, 2), font=('Helvetica',' 13'), default_button_element_size=(8,2), return_keyboard_events=True).Layout(layout)
window = sg.Window('Chat window with history', layout,
default_element_size=(30, 2),
font=('Helvetica', ' 13'),
default_button_element_size=(8, 2),
return_keyboard_events=True)
# ---===--- Loop taking in user input and using it --- #
command_history = []
history_offset = 0
while True:
(event, value) = window.Read()
event, value = window.read()
if event == 'SEND':
query = value['query'].rstrip()
# EXECUTE YOUR COMMAND HERE
print('The command you entered was {}'.format(query))
command_history.append(query)
history_offset = len(command_history)-1
window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear
window.FindElement('history').Update('\n'.join(command_history[-3:]))
# manually clear input because keyboard events blocks clear
window['query'].update('')
window['history'].update('\n'.join(command_history[-3:]))
elif event in (None, 'EXIT'): # quit if exit event or X
break
elif 'Up' in event and len(command_history):
command = command_history[history_offset]
history_offset -= 1 * (history_offset > 0) # decrement is not zero
window.FindElement('query').Update(command)
# decrement is not zero
history_offset -= 1 * (history_offset > 0)
window['query'].update(command)
elif 'Down' in event and len(command_history):
history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list
# increment up to end of list
history_offset += 1 * (history_offset < len(command_history)-1)
command = command_history[history_offset]
window.FindElement('query').Update(command)
window['query'].update(command)
elif 'Escape' in event:
window.FindElement('query').Update('')
sys.exit(69)
window['query'].update('')
ChatBotWithHistory()

View file

@ -1,10 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
from chatterbot import ChatBot
import chatterbot.utils
@ -18,36 +13,40 @@ to collect user input that is sent to the chatbot. The reply is displayed in th
# Create the 'Trainer GUI'
# The Trainer GUI consists of a lot of progress bars stacked on top of each other
sg.ChangeLookAndFeel('GreenTan')
sg.change_look_and_feel('GreenTan')
# sg.DebugWin()
MAX_PROG_BARS = 20 # number of training sessions
bars = []
texts = []
training_layout = [[sg.T('TRAINING PROGRESS', size=(20, 1), font=('Helvetica', 17))], ]
training_layout = [[sg.Text('TRAINING PROGRESS', size=(20, 1), font=('Helvetica', 17))]]
for i in range(MAX_PROG_BARS):
bars.append(sg.ProgressBar(100, size=(30, 4)))
texts.append(sg.T(' ' * 20, size=(20, 1), justification='right'))
training_layout += [[texts[i], bars[i]],] # add a single row
texts.append(sg.Text(' ' * 20, size=(20, 1), justification='right'))
training_layout += [[texts[i], bars[i]], ] # add a single row
training_window = sg.Window('Training').Layout(training_layout)
training_window = sg.Window('Training', training_layout)
current_bar = 0
# callback function for training runs
def print_progress_bar(description, iteration_counter, total_items, progress_bar_length=20):
global current_bar
global bars
global texts
global training_window
# update the window and the bars
button, values = training_window.Read(timeout=0)
button, values = training_window.read(timeout=0)
if button is None: # if user closed the window on us, exit
sys.exit(69)
return
if bars[current_bar].UpdateBar(iteration_counter, max=total_items) is False:
sys.exit(69)
texts[current_bar].Update(description) # show the training dataset name
return
# show the training dataset name
texts[current_bar].update(description)
if iteration_counter == total_items:
current_bar += 1
# redefine the chatbot text based progress bar with a graphical one
chatterbot.utils.print_progress_bar = print_progress_bar
@ -59,18 +58,19 @@ chatbot.train("chatterbot.corpus.english")
################# GUI #################
layout = [[sg.Output(size=(80, 20))],
[sg.Multiline(size=(70, 5), enter_submits=True),
[sg.MLine(size=(70, 5), enter_submits=True),
sg.Button('SEND', bind_return_key=True), sg.Button('EXIT')]]
window = sg.Window('Chat Window', auto_size_text=True, default_element_size=(30, 2)).Layout(layout)
window = sg.Window('Chat Window', layout,
default_element_size=(30, 2))
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
while True:
event, (value,) = window.Read()
event, (value,) = window.read()
if event != 'SEND':
break
string = value.rstrip()
print(' '+string)
print(' ' + string)
# send the user input to chatbot to get a response
response = chatbot.get_response(value.rstrip())
print(response)
print(response)

View file

@ -1,13 +1,7 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
from chatterbot import ChatBot
import chatterbot.utils
from gtts import gTTS
from pygame import mixer
import time
@ -22,18 +16,18 @@ to collect user input that is sent to the chatbot. The reply is displayed in th
# Create the 'Trainer GUI'
# The Trainer GUI consists of a lot of progress bars stacked on top of each other
sg.ChangeLookAndFeel('NeutralBlue')
sg.change_look_and_feel('NeutralBlue')
# sg.DebugWin()
MAX_PROG_BARS = 20 # number of training sessions
bars = []
texts = []
training_layout = [[sg.T('TRAINING PROGRESS', size=(20, 1), font=('Helvetica', 17))], ]
training_layout = [[sg.Text('TRAINING PROGRESS', size=(20, 1), font=('Helvetica', 17))], ]
for i in range(MAX_PROG_BARS):
bars.append(sg.ProgressBar(100, size=(30, 4)))
texts.append(sg.T(' ' * 20, size=(20, 1), justification='right'))
texts.append(sg.Text(' ' * 20, size=(20, 1), justification='right'))
training_layout += [[texts[i], bars[i]],] # add a single row
training_window = sg.Window('Training').Layout(training_layout)
training_window = sg.Window('Training', training_layout)
current_bar = 0
# callback function for training runs
@ -43,12 +37,12 @@ def print_progress_bar(description, iteration_counter, total_items, progress_bar
global texts
global training_window
# update the window and the bars
button, values = training_window.Read(timeout=0)
button, values = training_window.read(timeout=0)
if button is None: # if user closed the window on us, exit
sys.exit(69)
if bars[current_bar].UpdateBar(iteration_counter, max=total_items) is False:
sys.exit(69)
texts[current_bar].Update(description) # show the training dataset name
return
if bars[current_bar].update_bar(iteration_counter, max=total_items) is False:
return
texts[current_bar].update(description) # show the training dataset name
if iteration_counter == total_items:
current_bar += 1
@ -79,14 +73,14 @@ chatbot.train("chatterbot.corpus.english")
################# GUI #################
layout = [[sg.Output(size=(80, 20))],
[sg.Multiline(size=(70, 5), enter_submits=True),
[sg.MLine(size=(70, 5), enter_submits=True),
sg.Button('SEND', bind_return_key=True), sg.Button('EXIT')]]
window = sg.Window('Chat Window', auto_size_text=True, default_element_size=(30, 2)).Layout(layout)
window = sg.Window('Chat Window', layout, default_element_size=(30, 2))
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
while True:
event, (value,) = window.Read()
event, (value,) = window.read()
if event != 'SEND':
break
string = value.rstrip()
@ -94,4 +88,6 @@ while True:
# send the user input to chatbot to get a response
response = chatbot.get_response(value.rstrip())
print(response)
speak(str(response))
speak(str(response))
window.close()

View file

@ -1,16 +1,12 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
MY_WINDOW_ICON = 'E:\\TheRealMyDocs\\Icons\\The Planets\\jupiter.ico'
reverse = {}
colorhex = {}
colors = {
"abbey" : ( 76, 79, 86),
"abbey" : ( 76, 79, 86),
"acadia" : ( 27, 20, 4),
"acapulco" : (124, 176, 161),
"aero blue" : (201, 255, 229),
@ -1583,9 +1579,9 @@ def build_reverse_dict():
global colors
for color in colors:
rgb = colors[color]
hex = '#%02X%02X%02X' % (rgb)
reverse[hex] = color
colorhex[color] = hex
hex_val = '#%02X%02X%02X' % (rgb)
reverse[hex_val] = color
colorhex[color] = hex_val
return
@ -1621,9 +1617,9 @@ def get_name_from_hex(hex):
global colorhex
global colors
hex = hex.upper()
hex_val = hex.upper()
try:
name = reverse[hex]
name = reverse[hex_val]
except:
name = 'No Hex For Name'
return name
@ -1635,22 +1631,22 @@ def get_hex_from_name(name):
name = name.lower()
try:
hex = colorhex[name]
hex_val = colorhex[name]
except:
hex = '#000000'
return hex
hex_val = '#000000'
return hex_val
def show_all_colors_on_buttons():
global reverse
global colorhex
global colors
window = sg.Window('Colors on Buttons Demo', default_element_size=(3, 1), location=(0, 0), icon=MY_WINDOW_ICON, font=("Helvetica", 7))
window = sg.Window('Colors on Buttons Demo', default_element_size=(3, 1), location=(0, 0), font=("Helvetica", 7))
row = []
row_len = 20
for i, c in enumerate(colors):
hex = get_hex_from_name(c)
button1 = sg.CButton(button_text=c, button_color=(get_complementary_hex(hex), hex), size=(8, 1))
button2 = sg.CButton(button_text=c, button_color=(hex, get_complementary_hex(hex)), size=(8, 1))
hex_val = get_hex_from_name(c)
button1 = sg.CButton(button_text=c, button_color=(get_complementary_hex(hex_val), hex_val), size=(8, 1))
button2 = sg.CButton(button_text=c, button_color=(hex_val, get_complementary_hex(hex_val)), size=(8, 1))
row.append(button1)
row.append(button2)
if (i+1) % row_len == 0:
@ -1678,18 +1674,18 @@ def main():
list_of_colors = [c for c in colors]
printable = '\n'.join(map(str, list_of_colors))
# show_all_colors_on_buttons()
sg.SetOptions(element_padding=(0,0))
sg.set_options(element_padding=(0,0))
while True:
# ------- Form show ------- #
layout = [[sg.Text('Find color')],
[sg.Text('Demonstration of colors')],
[sg.Text('Enter a color name in text or hex #RRGGBB format')],
[sg.InputText(key='hex')],
[sg.Listbox(list_of_colors, size=(20, 30), bind_return_key=True, key='listbox'), sg.T('Or choose from list')],
[sg.Listbox(list_of_colors, size=(20, 30), bind_return_key=True, key='listbox'), sg.Text('Or choose from list')],
[sg.Submit(), sg.Button('Many buttons', button_color=('white', '#0e6251'), key='Many buttons'), sg.ColorChooserButton( 'Chooser', target=(3,0), key='Chooser'), sg.Quit(),],
]
# [g.Multiline(DefaultText=str(printable), Size=(30,20))]]
event, values = sg.Window('Color Demo', auto_size_buttons=False).Layout(layout).Read()
event, values = sg.Window('Color Demo', layout, auto_size_buttons=False).read()
# ------- OUTPUT results portion ------- #
if event == 'Quit' or event is None:
@ -1720,7 +1716,8 @@ def main():
[sg.CloseButton(button_text=color_name, button_color=(color_hex, complementary_hex))],
[sg.CloseButton(button_text=complementary_hex + ' ' + complementary_color, button_color=(complementary_hex , color_hex), size=(30, 1))],
]
sg.Window('Color demo', default_element_size=(100, 1), auto_size_text=True, auto_close=True, auto_close_duration=5, icon=MY_WINDOW_ICON).Layout(layout).Read()
sg.Window('Color demo', layout, default_element_size=(100, 1),
auto_close=True, auto_close_duration=5).read()

View file

@ -1,10 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
@ -671,17 +666,18 @@ color_map = {
}
sg.SetOptions(button_element_size=(12,1), element_padding=(0,0), auto_size_buttons=False, border_width=1, tooltip_time=100)
sg.set_options(button_element_size=(12, 1),
element_padding=(0, 0),
auto_size_buttons=False,
border_width=1, tooltip_time=100)
#start layout with the tittle
layout = [[sg.Text('Hover mouse to see RGB value, click for white & black text',
text_color='blue',
font='Any 15',
relief=sg.RELIEF_SUNKEN,
justification='center',
size=(100,1),
background_color='light green',
pad=(0,(0,20))),]]
# start layout with the tittle
layout = [
[sg.Text('Hover mouse to see RGB value, click for white & black text',
justification='center',
text_color='blue', background_color='light green',
size=(100, 1), pad=(0, (0, 20)))]
]
# -- Create primary color viewer window --
color_list = [key for key in color_map]
@ -691,19 +687,25 @@ for rows in range(40):
for i in range(12):
try:
color = color_list[rows+40*i]
row.append(sg.Button(color, button_color=('black', color), key=color, tooltip=color_map[color]))
row.append(sg.Button(color, button_color=('black', color),
key=color, tooltip=color_map[color]))
except:
pass
layout.append(row)
window = sg.Window('Color Viewer', grab_anywhere=False, font=('any 9')).Layout(layout)
window = sg.Window('Color Viewer', layout, grab_anywhere=False, font=('any 9'))
# -- Event loop --
while True:
event, values = window.Read()
event, values = window.read()
if event is None:
break
# -- Create a secondary window that shows white and black text on chosen color
layout2 =[[sg.DummyButton(event, button_color=('white', event), tooltip=color_map[event]), sg.DummyButton(event, button_color=('black', event), tooltip=color_map[event])] ]
sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).Read(timeout=0)
layout2 = [[
sg.DummyButton(event, button_color=(
'white', event), tooltip=color_map[event]),
sg.DummyButton(event, button_color=('black', event), tooltip=color_map[event])
]]
sg.Window('Buttons with white and black text',
layout2, keep_on_top=True).read(timeout=0)

View file

@ -1,9 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Color names courtesy of Big Daddy's Wiki-Python
@ -15,7 +11,6 @@ else:
"""
COLORS = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'old lace',
'linen', 'antique white', 'papaya whip', 'blanched almond', 'bisque', 'peach puff',
'navajo white', 'lemon chiffon', 'mint cream', 'azure', 'alice blue', 'lavender',
@ -93,17 +88,18 @@ COLORS = ['snow', 'ghost white', 'white smoke', 'gainsboro', 'floral white', 'ol
'grey84', 'grey85', 'grey86', 'grey87', 'grey88', 'grey89', 'grey90', 'grey91', 'grey92',
'grey93', 'grey94', 'grey95', 'grey97', 'grey98', 'grey99']
sg.set_options(button_element_size=(12, 1),
element_padding=(0, 0),
auto_size_buttons=False,
border_width=0)
sg.SetOptions(button_element_size=(12,1), element_padding=(0,0), auto_size_buttons=False, border_width=0)
layout = [[sg.Text('Click on a color square to see both white and black text on that color', text_color='blue', font='Any 15')]]
layout = [[sg.Text('Click on a color square to see both white and black text on that color',
text_color='blue', font='Any 15')]]
row = []
layout = []
# -- Create primary color viewer window --
for rows in range(40):
row = []
for i in range(12):
try:
@ -113,20 +109,16 @@ for rows in range(40):
pass
layout.append(row)
# for i, color in enumerate(COLORS):
# row.append(sg.Button(color, button_color=('black', color), key=color))
# if (i+1) % 12 == 0:
# layout.append(row)
# row = []
window = sg.Window('Color Viewer', grab_anywhere=False, font=('any 9')).Layout(layout)
window = sg.Window('Color Viewer', layout, grab_anywhere=False, font=('any 9'))
# -- Event loop --
while True:
event, values = window.Read()
event, values = window.read()
if event is None:
break
# -- Create a secondary window that shows white and black text on chosen color
layout2 =[[sg.DummyButton(event, button_color=('white', event)), sg.DummyButton(event, button_color=('black', event))]]
sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).Read(timeout=0)
layout2 = [[sg.DummyButton(event, button_color=('white', event)),
sg.DummyButton(event, button_color=('black', event))]]
sg.Window('Buttons with white and black text', layout2, keep_on_top=True).read(timeout=0)
window.close()

View file

@ -1,6 +1,16 @@
import PySimpleGUI as sg
# this one long import has the effect of making the code more compact as there is no 'sg.' prefix required for Elements
from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu, Canvas, Column, Col, Combo, Frame, Graph, Image, InputText, Input, In, Listbox, LBox, Menu, Multiline, ML, MLine, OptionMenu, Output, Pane, ProgressBar, Radio, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, TreeData, VerticalSeparator, Window, Sizer
import PySimpleGUI as sg
from PySimpleGUI import InputCombo, Combo, Multiline, ML,
MLine, Checkbox, CB, Check,
Button, B, Btn, ButtonMenu,
Canvas, Column, Col, Combo,
Frame, Graph, Image, InputText,
Input, In, Listbox, LBox, Menu,
Multiline, ML, MLine, OptionMenu,
Output, Pane, ProgressBar, Radio,
Slider, Spin, StatusBar, Tab,
TabGroup, Table, Text, Txt, T,
Tree, TreeData, VerticalSeparator, Window, Sizer
"""
Demo Columns and Frames
@ -14,29 +24,33 @@ from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, C
sg.change_look_and_feel('GreenTan')
col2 = Column([[Frame('Accounts:', [[Column([[Listbox(['Account '+str(i) for i in range(1,16)], key='-ACCT-LIST-', size=(15,20)),]],size=(150,400))]])]], pad=(0,0))
col2 = Column([[Frame('Accounts:', [[Column([[Listbox(['Account '+str(i) for i in range(1, 16)],
key='-ACCT-LIST-', size=(15, 20)), ]], size=(150, 400))]])]], pad=(0, 0))
col1 = Column([
# Categories frame
[Frame('Categories:', [[Radio('Websites', 'radio1', default=True, key='-WEBSITES-', size=(10, 1)),
Radio('Software', 'radio1',key='-SOFTWARE-', size=(10, 1))]],)],
Radio('Software', 'radio1', key='-SOFTWARE-', size=(10, 1))]],)],
# Information frame
[Frame('Information:', [[Column([[Text('Account:')],
[Input(key='-ACCOUNT-IN-', size=(19, 1))],
[Text('User Id:')],
[Input(key='-USERID-IN-', size=(19, 1)), Button('Copy', key='-USERID-')],
[Text('Password:')],
[Input(key='-PW-IN-', size=(19, 1)), Button('Copy', key='-PASS-')],
[Text('Location:')],
[Input(key='-LOC-IN-', size=(19, 1)), Button('Copy', key='-LOC')],
[Text('Notes:')],
[Multiline(key='-NOTES-', size=(25, 5))],
], size=(235,350),pad=(0,0))]])],], pad=(0,0))
[Input(key='-ACCOUNT-IN-', size=(19, 1))],
[Text('User Id:')],
[Input(key='-USERID-IN-', size=(19, 1)),
Button('Copy', key='-USERID-')],
[Text('Password:')],
[Input(key='-PW-IN-', size=(19, 1)),
Button('Copy', key='-PASS-')],
[Text('Location:')],
[Input(key='-LOC-IN-', size=(19, 1)),
Button('Copy', key='-LOC')],
[Text('Notes:')],
[Multiline(key='-NOTES-', size=(25, 5))],
], size=(235, 350), pad=(0, 0))]])], ], pad=(0, 0))
col3 = Column([[Frame('Actions:', [[Column([[Button('Save'), Button('Clear'), Button('Delete'),]], size=(450,45), pad=(0,0))]])]], pad=(0,0))
col3 = Column([[Frame('Actions:', [[Column([[Button('Save'), Button(
'Clear'), Button('Delete'), ]], size=(450, 45), pad=(0, 0))]])]], pad=(0, 0))
layout = [ [col1, col2],
[col3]]
layout = [[col1, col2], [col3]]
window = Window('Passwords', layout)
@ -45,4 +59,5 @@ while True:
print(event, values)
if event is None:
break
window.close()

View file

@ -1,25 +1,28 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
sg.ChangeLookAndFeel('BlueMono')
'''
Usage of Column Element
'''
sg.change_look_and_feel('BlueMono')
css = {'text_color': 'white', 'background_color': 'blue'}
# Column layout
col = [[sg.Text('col Row 1', text_color='white', background_color='blue')],
[sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')],
[sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]]
col = [[sg.Text('col Row 1', **css)],
[sg.Text('col Row 2', **css), sg.Input('col input 1')],
[sg.Text('col Row 3', **css), sg.Input('col input 2')]]
# Window layout
layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'),
select_mode=sg.LISTBOX_SELECT_MODE_MULTIPLE, size=(20, 3)),
sg.Column(col, background_color='blue')],
sg.Col(col, background_color='blue')],
[sg.Input('Last input')],
[sg.OK()]]
# Display the window and get values
event, values = sg.Window('Compact 1-line form with column').Layout(layout).Read()
window = sg.Window('Compact 1-line form with column', layout)
event, values = window.read()
sg.Popup(event, values, line_width=200)
sg.popup(event, values, line_width=200)
window.close()

View file

@ -1,7 +1,4 @@
import PySimpleGUI as sg
# Import the elements individually to save space
from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, Check, Button, B, Btn, ButtonMenu,BMenu, Canvas, Column, Col, Combo, DropDown, Drop, DD, Frame, Graph, Image, InputText, Input, In, I, Listbox, LBox, LB, Menu, Multiline, ML, MLine, OptionMenu, Output, Pane, ProgressBar, Prog, PBar, Radio, R, Rad, Sizer, Slider, Spin, StatusBar, Tab, TabGroup, Table, Text, Txt, T, Tree, TreeData, VerticalSeparator, Window, Print
"""
Demo - Compact Layouts and Element Renaming
@ -10,7 +7,7 @@ from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, C
programmers, there is little additional knowledge to be gained by writing
sg.Text('My text')
rather than using one of the shortcuts such as
sg.T('My text')
sg.Text('My text')
However, even with shortcut usage, you continue to have the package prefix of
sg.
That's 3 characters per element that are added to your layout!
@ -19,7 +16,7 @@ from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, C
If you don't want to use that very-long import or perhaps want to use your own shortcut names, you can easily
create your shortcut by simple assignment:
T = sg.Text
T = sg.T
This enables you to use T just as if you imported the Class T from PySimpleGUI. You could develop your own
template that you copy and paste at the top of all of your PySimpleGUI programs. Or perhaps perform an import
of those assignments from a .py file you create.
@ -37,11 +34,14 @@ from PySimpleGUI import InputCombo, Combo, Multiline, ML, MLine, Checkbox, CB, C
# A user created shortcut....
# Suppose this user's layout contains many Multiline Elements. It could be advantageous to have a single letter
# shortcut version for Multiline
M = sg.Multiline
M = sg.MLine
B = sg.B
# This layout uses the user defined "M" element as well as the PySimpleGUI Button shortcut, B.
layout = [[M(size=(30,3))],
layout = [[M(size=(30, 3))],
[B('OK')]]
event, values = Window('Shortcuts', layout).read()
window = sg.Window('Shortcuts', layout).read()
event, values = window.read()
sg.popup_scrolled(event, values)
window.close()

View file

@ -1,30 +1,32 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
# sg.SetOptions(button_color=sg.COLOR_SYSTEM_DEFAULT)
'''
Simple "diff" in PySimpleGUI
'''
def GetFilesToCompare():
form_rows = [[sg.Text('Enter 2 files to comare')],
[sg.Text('File 1', size=(15, 1)), sg.InputText(key='file1'), sg.FileBrowse()],
[sg.Text('File 2', size=(15, 1)), sg.InputText(key='file2'), sg.FileBrowse(target='file2')],
[sg.Text('File 1', size=(15, 1)),
sg.InputText(key='-file1-'), sg.FileBrowse()],
[sg.Text('File 2', size=(15, 1)), sg.InputText(key='-file2-'),
sg.FileBrowse(target='file2')],
[sg.Submit(), sg.Cancel()]]
window = sg.Window('File Compare')
event, values = window.Layout(form_rows).Read()
window = sg.Window('File Compare', form_rows)
event, values = window.read()
window.close()
return event, values
def main():
button, values = GetFilesToCompare()
f1 = values['file1']
f2 = values['file2']
if any((button != 'Submit', f1 =='', f2 == '')):
sg.PopupError('Operation cancelled')
sys.exit(69)
def main():
button, values = GetFilesToCompare()
f1, f2 = values['-file1-'], values['-file2-']
if any((button != 'Submit', f1 == '', f2 == '')):
sg.popup_error('Operation cancelled')
return
# --- This portion of the code is not GUI related ---
with open(f1, 'rb') as file1:
@ -34,11 +36,12 @@ def main():
for i, x in enumerate(a):
if x != b[i]:
sg.Popup('Compare results for files', f1, f2, '**** Mismatch at offset {} ****'.format(i))
sg.popup('Compare results for files', f1, f2,
'**** Mismatch at offset {} ****'.format(i))
break
else:
if len(a) == len(b):
sg.Popup('**** The files are IDENTICAL ****')
sg.popup('**** The files are IDENTICAL ****')
if __name__ == '__main__':

View file

@ -23,11 +23,11 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import numpy
import PySimpleGUI as sg # Take your pick! Tkinter
# import PySimpleGUIWeb as sg # Or the Web! (Remi!)
import PySimpleGUI as sg
BOX_SIZE = 15
class GameOfLife:
def __init__(self, N=20, T=200):
@ -98,40 +98,56 @@ class GameOfLife:
self.t += 1
def init_graphics(self):
self.graph = sg.Graph((600, 600), (0, 0), (450, 450), key='_GRAPH_', change_submits=True, drag_submits=False, background_color='lightblue')
self.graph = sg.Graph((600, 600), (0, 0), (450, 450),
key='-GRAPH-',
change_submits=True,
drag_submits=False,
background_color='lightblue')
layout = [
[sg.Text('Game of Life ', font='ANY 15'), sg.Text('', key='_OUTPUT_', size=(30,1), font='ANY 15')],
[sg.Text('Game of Life', font='ANY 15'),
sg.Text('', key='-OUTPUT-', size=(30, 1), font='ANY 15')],
[self.graph],
[sg.Button('Go!', key='_DONE_'),
sg.Text(' Delay (ms)') , sg.Slider([0,800], orientation='h', key='_SLIDER_', enable_events=True, size=(15,15)), sg.T('', size=(3,1), key='_S1_OUT_'),
sg.Text(' Num Generations'), sg.Slider([0, 20000],default_value=4000, orientation='h',size=(15,15),enable_events=True, key='_SLIDER2_'), sg.T('', size=(3,1), key='_S2_OUT_')]
[sg.Button('Go!', key='-DONE-'),
sg.Text(' Delay (ms)'),
sg.Slider([0, 800],
orientation='h',
key='-SLIDER-',
enable_events=True,
size=(15, 15)),
sg.Text('', size=(3, 1), key='-S1-OUT-'),
sg.Text(' Num Generations'), sg.Slider([0, 20000],
default_value=4000,
orientation='h',
size=(15, 15),
enable_events=True,
key='-SLIDER2-'),
sg.Text('', size=(3, 1), key='-S2-OUT-')]
]
self.window = sg.Window('Window Title', ).Layout(layout).Finalize()
event, values = self.window.Read(timeout=0)
self.delay = values['_SLIDER_']
self.window.Element('_S1_OUT_').Update(values['_SLIDER_'])
self.window.Element('_S2_OUT_').Update(values['_SLIDER2_'])
self.window = sg.Window('Window Title', layout, finalize=True)
event, values = self.window.read(timeout=0)
self.delay = values['-SLIDER-']
self.window['-S1-OUT-'].update(values['-SLIDER-'])
self.window['-S2-OUT-'].update(values['-SLIDER2-'])
def draw_board(self):
BOX_SIZE = 15
self.graph.Erase()
self.graph.erase()
for i in range(self.N):
for j in range(self.N):
if self.old_grid[i][j]:
self.graph.DrawRectangle((i * BOX_SIZE, j * BOX_SIZE),
(i * BOX_SIZE + BOX_SIZE, j * (BOX_SIZE) + BOX_SIZE),
line_color='black', fill_color='yellow')
event, values = self.window.Read(timeout=self.delay)
if event in (None, '_DONE_'):
exit()
self.delay = values['_SLIDER_']
self.T = int(values['_SLIDER2_'])
self.window.Element('_S1_OUT_').Update(values['_SLIDER_'])
self.window.Element('_S2_OUT_').Update(values['_SLIDER2_'])
self.window.Element('_OUTPUT_').Update('Generation {}'.format(self.t))
self.graph.draw_rectangle((i * BOX_SIZE, j * BOX_SIZE),
(i * BOX_SIZE + BOX_SIZE,
j * (BOX_SIZE) + BOX_SIZE),
line_color='black', fill_color='yellow')
event, values = self.window.read(timeout=self.delay)
if event in (None, '-DONE-'):
return
self.delay = values['-SLIDER-']
self.T = int(values['-SLIDER2-'])
self.window['-S1-OUT-'].update(values['-SLIDER-'])
self.window['-S2-OUT-'].update(values['-SLIDER2-'])
self.window['-OUTPUT-'].update('Generation {}'.format(self.t))
def manual_board_setup(self):
ids = []
@ -140,31 +156,33 @@ class GameOfLife:
for j in range(self.N):
ids[i].append(0)
while True: # Event Loop
event, values = self.window.Read()
if event is None or event == '_DONE_':
event, values = self.window.read()
if event is None or event == '-DONE-':
break
self.window.Element('_S1_OUT_').Update(values['_SLIDER_'])
self.window.Element('_S2_OUT_').Update(values['_SLIDER2_'])
mouse = values['_GRAPH_']
self.window['-S1-OUT-'].update(values['-SLIDER-'])
self.window['-S2-OUT-'].update(values['-SLIDER2-'])
mouse = values['-GRAPH-']
if event == '_GRAPH_':
if event == '-GRAPH-':
if mouse == (None, None):
continue
box_x = mouse[0] // BOX_SIZE
box_y = mouse[1] // BOX_SIZE
if self.old_grid[box_x][box_y] == 1:
id = ids[box_x][box_y]
self.graph.DeleteFigure(id)
id_val = ids[box_x][box_y]
self.graph.delete_figure(id_val)
self.old_grid[box_x][box_y] = 0
else:
id = self.graph.DrawRectangle((box_x * BOX_SIZE, box_y * BOX_SIZE),
(box_x * BOX_SIZE + BOX_SIZE, box_y * (BOX_SIZE) + BOX_SIZE),
line_color='black', fill_color='yellow')
ids[box_x][box_y] = id
id_val = self.graph.draw_rectangle((box_x * BOX_SIZE, box_y * BOX_SIZE),
(box_x * BOX_SIZE + BOX_SIZE,
box_y * (BOX_SIZE) + BOX_SIZE),
line_color='black', fill_color='yellow')
ids[box_x][box_y] = id_val
self.old_grid[box_x][box_y] = 1
self.window.Element('_DONE_').Update(text='Exit')
self.window['-DONE-'].update(text='Exit')
if (__name__ == "__main__"):
game = GameOfLife(N=35, T=200)
game.play()
game.window.Close()
game.window.close()

View file

@ -1,9 +1,4 @@
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
# import PySimpleGUIWeb as sg # take your pick of ports. Runs on both
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import random
import string
@ -17,38 +12,41 @@ import string
BOX_SIZE = 25
layout = [
[sg.Text('Crossword Puzzle Using PySimpleGUI'), sg.Text('', key='_OUTPUT_')],
[sg.Graph((800,800), (0,450), (450,0), key='_GRAPH_', change_submits=True, drag_submits=False)],
[sg.Button('Show'), sg.Button('Exit')]
]
[sg.Text('Crossword Puzzle Using PySimpleGUI'), sg.Text('', key='-OUTPUT-')],
[sg.Graph((800, 800), (0, 450), (450, 0), key='-GRAPH-',
change_submits=True, drag_submits=False)],
[sg.Button('Show'), sg.Button('Exit')]
]
window = sg.Window('Window Title', ).Layout(layout).Finalize()
window = sg.Window('Window Title', layout, finalize=True)
g = window.FindElement('_GRAPH_')
g = window['-GRAPH-']
for row in range(16):
for col in range(16):
if random.randint(0,100) > 10:
g.DrawRectangle((col * BOX_SIZE + 5, row * BOX_SIZE + 3), (col * BOX_SIZE + BOX_SIZE + 5, row * BOX_SIZE + BOX_SIZE + 3), line_color='black')
if random.randint(0, 100) > 10:
g.draw_rectangle((col * BOX_SIZE + 5, row * BOX_SIZE + 3), (col * BOX_SIZE + BOX_SIZE + 5, row * BOX_SIZE + BOX_SIZE + 3), line_color='black')
else:
g.DrawRectangle((col * BOX_SIZE + 5, row * BOX_SIZE + 3), (col * BOX_SIZE + BOX_SIZE + 5, row * BOX_SIZE + BOX_SIZE + 3), line_color='black', fill_color='black')
g.draw_rectangle((col * BOX_SIZE + 5, row * BOX_SIZE + 3), (col * BOX_SIZE + BOX_SIZE + 5, row * BOX_SIZE + BOX_SIZE + 3), line_color='black', fill_color='black')
g.DrawText('{}'.format(row * 6 + col + 1), (col * BOX_SIZE + 10, row * BOX_SIZE + 8))
g.draw_text('{}'.format(row * 6 + col + 1),
(col * BOX_SIZE + 10, row * BOX_SIZE + 8))
while True: # Event Loop
event, values = window.Read()
event, values = window.read()
print(event, values)
if event is None or event == 'Exit':
if event in (None, 'Exit'):
break
mouse = values['_GRAPH_']
mouse = values['-GRAPH-']
if event == '_GRAPH_':
if event == '-GRAPH-':
if mouse == (None, None):
continue
box_x = mouse[0]//BOX_SIZE
box_y = mouse[1]//BOX_SIZE
letter_location = (box_x * BOX_SIZE + 18, box_y * BOX_SIZE + 17)
print(box_x, box_y)
g.DrawText('{}'.format(random.choice(string.ascii_uppercase)), letter_location, font='Courier 25')
g.draw_text('{}'.format(random.choice(string.ascii_uppercase)),
letter_location, font='Courier 25')
window.Close()
window.close()

View file

@ -32,31 +32,30 @@ pixmaps and page re-visits will re-use a once-created display list.
import sys
import fitz
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import tkinter as tk
from PIL import Image, ImageTk
import time
if len(sys.argv) == 1:
fname = sg.PopupGetFile('Document Browser', 'Document file to open', no_window=True,
file_types = (
("PDF Files", "*.pdf"),
("XPS Files", "*.*xps"),
("Epub Files", "*.epub"),
("Fiction Books", "*.fb2"),
("Comic Books", "*.cbz"),
("HTML", "*.htm*")
# add more document types here
)
)
fname = sg.popup_get_file('Document Browser', 'Document file to open',
no_window=True,
file_types=(
("PDF Files", "*.pdf"),
("XPS Files", "*.*xps"),
("Epub Files", "*.epub"),
("Fiction Books", "*.fb2"),
("Comic Books", "*.cbz"),
("HTML", "*.htm*")
# add more document types here
)
)
else:
fname = sys.argv[1]
if not fname:
sg.Popup("Cancelling:", "No filename supplied")
sg.popup("Cancelling:", "No filename supplied")
raise SystemExit("Cancelled: no filename supplied")
doc = fitz.open(fname)
@ -64,15 +63,16 @@ page_count = len(doc)
# used for response time statistics only
fitz_img_time = 0.0
tk_img_time = 0.0
img_count = 1
tk_img_time = 0.0
img_count = 1
# allocate storage for page display lists
dlist_tab = [None] * page_count
title = "PyMuPDF display of '%s', pages: %i" % (fname, page_count)
def get_page(pno, zoom = False, max_size = None, first = False):
def get_page(pno, zoom=False, max_size=None, first=False):
"""Return a PNG image for a document page number.
"""
dlist = dlist_tab[pno] # get display list of page number
@ -91,7 +91,7 @@ def get_page(pno, zoom = False, max_size = None, first = False):
mat_0 = fitz.Matrix(zoom_0, zoom_0)
if not zoom: # show total page
pix = dlist.getPixmap(matrix = mat_0, alpha=False)
pix = dlist.getPixmap(matrix=mat_0, alpha=False)
else:
mp = r.tl + (r.br - r.tl) * 0.5 # page rect center
w2 = r.width / 2
@ -125,22 +125,15 @@ max_size = (max_width, max_height)
root.destroy()
del root
window = sg.Window(title, return_keyboard_events = True,
location = (0,0), use_default_focus = False, no_titlebar=False)
cur_page = 0
data, clip_pos = get_page(cur_page,
zoom = False,
max_size = max_size,
first = True)
data, clip_pos = get_page(cur_page, zoom=False, max_size=max_size, first=True)
image_elem = sg.Image(data = data)
image_elem = sg.Image(data=data)
goto = sg.InputText(str(cur_page + 1), size=(5, 1), do_not_clear=True,
key = "PageNumber")
goto = sg.InputText(str(cur_page + 1), size=(5, 1), key="-PageNumber-")
layout = [
[
layout = [[
sg.ReadButton('Next'),
sg.ReadButton('Prev'),
sg.Text('Page:'),
@ -152,17 +145,18 @@ layout = [
[image_elem],
]
window.Layout(layout)
window = sg.Window(title, layout, return_keyboard_events=True,
location=(0, 0), use_default_focus=False, no_titlebar=False)
# now define the buttons / events we want to handle
enter_buttons = [chr(13), "Return:13"]
quit_buttons = ["Escape:27", chr(27)]
next_buttons = ["Next", "Next:34", "MouseWheel:Down"]
prev_buttons = ["Prev", "Prior:33", "MouseWheel:Up"]
Up = "Up:38"
Left = "Left:37"
Up = "Up:38"
Left = "Left:37"
Right = "Right:39"
Down = "Down:40"
Down = "Down:40"
zoom_buttons = ["Zoom", Up, Down, Left, Right]
# all the buttons we will handle
@ -173,8 +167,8 @@ old_page = 0
old_zoom = False
while True:
event, value = window.Read()
if event is None and (value is None or value['PageNumber'] is None):
event, value = window.read()
if event is None and (value is None or value['-PageNumber-'] is None):
break
if event in quit_buttons:
break
@ -184,7 +178,7 @@ while True:
if event in enter_buttons:
try:
cur_page = int(value['PageNumber']) - 1 # check if valid
cur_page = int(value['-PageNumber-']) - 1 # check if valid
while cur_page < 0:
cur_page += page_count
except:
@ -216,21 +210,22 @@ while True:
zoom = zoom_pressed = old_zoom = False
t0 = time.perf_counter()
data, clip_pos = get_page(cur_page, zoom = zoom, max_size = max_size,
first = False)
data, clip_pos = get_page(cur_page, zoom=zoom, max_size=max_size,
first=False)
t1 = time.perf_counter()
image_elem.Update(data = data)
image_elem.update(data=data)
t2 = time.perf_counter()
fitz_img_time += t1 - t0
tk_img_time += t2 - t1
img_count += 1
tk_img_time += t2 - t1
img_count += 1
old_page = cur_page
old_zoom = zoom_pressed or zoom
# update page number field
if event in my_keys:
goto.Update(str(cur_page + 1))
goto.update(str(cur_page + 1))
window.close()
# print some response time statistics
if img_count > 0:

View file

@ -1,5 +1,4 @@
import PySimpleGUI as sg
# import imwatchingyou # Not needed because using the one inside PySimpleGUI.py code itself
"""
Demo program that shows you how to integrate the PySimpleGUI Debugger
@ -20,36 +19,38 @@ import PySimpleGUI as sg
"""
layout = [
[sg.T('A typical PSG application')],
[sg.In(key='_IN_')],
[sg.T(' ', key='_OUT_', size=(45,1))],
[sg.CBox('Checkbox 1'), sg.CBox('Checkbox 2')],
[sg.Radio('a',1, key='_R1_'), sg.Radio('b',1, key='_R2_'), sg.Radio('c',1, key='_R3_')],
[sg.Combo(['c1', 'c2', 'c3'], size=(6,3), key='_COMBO_')],
[sg.Output(size=(50,6))],
[sg.Ok(), sg.Exit(), sg.Button('Enable'), sg.Button('Popout'), sg.Button('Debugger'), sg.Debug(key='Debug')],
]
[sg.Text('A typical PSG application')],
[sg.Input(key='-IN-')],
[sg.Text(' ', key='-OUT-', size=(45, 1))],
[sg.CBox('Checkbox 1'), sg.CBox('Checkbox 2')],
[sg.Radio('a', 1, key='-R1-'), sg.Radio('b', 1, key='-R2-'),
sg.Radio('c', 1, key='-R3-')],
[sg.Combo(['c1', 'c2', 'c3'], size=(6, 3), key='-COMBO-')],
[sg.Output(size=(50, 6))],
[sg.Ok(), sg.Exit(), sg.Button('Enable'), sg.Button('Popout'),
sg.Button('Debugger'), sg.Debug(key='Debug')],
]
window = sg.Window('This is your Application Window', layout, debugger_enabled=False)
window = sg.Window('This is your Application Window',
layout, debugger_enabled=False)
counter = 0
timeout = 100
# Note that you can launch the debugger windows right away, without waiting for user input
sg.show_debugger_popout_window()
while True: # Your Event Loop
event, values = window.Read(timeout=timeout)
event, values = window.read(timeout=100)
if event in (None, 'Exit'):
break
elif event == 'Enable':
window.EnableDebugger()
window.enable_debugger()
elif event == 'Popout':
sg.show_debugger_popout_window() # replaces old popout with a new one, possibly with new variables`
# replaces old popout with a new one, possibly with new variables`
sg.show_debugger_popout_window()
elif event == 'Debugger':
sg.show_debugger_window()
counter += 1
# to prove window is operating, show the input in another area in the window.
window.Element('_OUT_').Update(values['_IN_'])
window['-OUT-'].update(values['-IN-'])
window.Close()
window.close()

View file

@ -20,29 +20,29 @@ import PySimpleGUI as sg
"""
layout = [
[sg.T('A typical PSG application')],
[sg.In(key='_IN_')],
[sg.T(' ', key='_OUT_', size=(45,1))],
[sg.CBox('Checkbox 1'), sg.CBox('Checkbox 2')],
[sg.Radio('a',1, key='_R1_'), sg.Radio('b',1, key='_R2_'), sg.Radio('c',1, key='_R3_')],
[sg.Combo(['c1', 'c2', 'c3'], size=(6,3), key='_COMBO_')],
[sg.Output(size=(50,6))],
[sg.Ok(), sg.Exit(), sg.Button('Enable'), sg.Debug(key='Debug')],
]
window = sg.Window('This is your Application Window', layout, debugger_enabled=False)
[sg.Text('A typical PSG application')],
[sg.Input(key='-IN-')],
[sg.Text(' ', key='-OUT-', size=(45, 1))],
[sg.CBox('Checkbox 1'), sg.CBox('Checkbox 2')],
[sg.Radio('a', 1, key='-R1-'), sg.Radio('b', 1, key='-R2-'),
sg.Radio('c', 1, key='-R3-')],
[sg.Combo(['c1', 'c2', 'c3'], size=(6, 3), key='-COMBO-')],
[sg.Output(size=(50, 6))],
[sg.Ok(), sg.Exit(), sg.Button('Enable'), sg.Debug(key='Debug')],
]
window = sg.Window('This is your Application Window',
layout, debugger_enabled=False)
counter = 0
timeout = 100
while True: # Your Event Loop
event, values = window.Read(timeout=timeout)
event, values = window.read(timeout=100)
if event in (None, 'Exit'):
break
elif event == 'Enable':
window.EnableDebugger()
window.enable_debugger()
counter += 1
# to prove window is operating, show the input in another area in the window.
window.Element('_OUT_').Update(values['_IN_'])
window['-OUT-'].update(values['-IN-'])
window.Close()
window.close()

View file

@ -20,11 +20,15 @@ import imwatchingyou # STEP 1
"""
layout = [
[sg.T('A typical PSG application')],
[sg.In(key='_IN_')],
[sg.T(' ', key='_OUT_', size=(30, 1))],
[sg.Radio('a', 1, key='_R1_'), sg.Radio('b', 1, key='_R2_'), sg.Radio('c', 1, key='_R3_')],
[sg.Combo(['c1', 'c2', 'c3'], size=(6, 3), key='_COMBO_')],
[sg.Text('A typical PSG application')],
[sg.Input(key='-IN-')],
[sg.Text(' ', key='-OUT-', size=(30, 1))],
[
sg.Rad('a', 1, key='-R1-'),
sg.Rad('b', 1, key='-R2-'),
sg.Rad('c', 1, key='-R3-')
],
[sg.Combo(['c1', 'c2', 'c3'], size=(6, 3), key='-COMBO-')],
[sg.Output(size=(50, 6))],
[sg.Ok(), sg.Exit(), sg.Button('Debug'), sg.Button('Popout')],
]
@ -32,10 +36,9 @@ layout = [
window = sg.Window('This is your Application Window', layout)
counter = 0
timeout = 100
while True: # Your Event Loop
event, values = window.Read(timeout=timeout)
event, values = window.read(timeout=100)
if event in (None, 'Exit'):
break
elif event == 'Ok':
@ -46,9 +49,9 @@ while True: # Your Event Loop
imwatchingyou.show_debugger_popout_window() # STEP 2
counter += 1
# to prove window is operating, show the input in another area in the window.
window.Element('_OUT_').Update(values['_IN_'])
window['-OUT-'].update(values['-IN-'])
# don't worry about the "state" of things, just call this function "frequently"
imwatchingyou.refresh_debugger() # STEP 3 - refresh debugger
window.Close()
window.close()

View file

@ -1,9 +1,4 @@
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Demo - Running 2 windows with both being active at the same time
Three important things to note about this design patter:
@ -15,45 +10,44 @@ else:
# Window 1 layout
layout = [
[sg.Text('This is the FIRST WINDOW'), sg.Text(' ', key='_OUTPUT_')],
[sg.Text('This is the FIRST WINDOW'), sg.Text(' ', key='-OUTPUT-')],
[sg.Text('')],
[sg.Button('Launch 2nd Window'),sg.Button('Popup'), sg.Button('Exit')]
[sg.Button('Launch 2nd Window'), sg.Button('Popup'), sg.Button('Exit')]
]
window = sg.Window('Window Title', location=(800,600)).Layout(layout)
window = sg.Window('Window Title', layout, location=(800,600))
win2_active = False
i=0
while True: # Event Loop
event, values = window.Read(timeout=100)
event, values = window.read(timeout=100)
if event != sg.TIMEOUT_KEY:
print(i, event, values)
if event is None or event == 'Exit':
if event in (None, 'Exit'):
break
elif event == 'Popup':
sg.Popup('This is a BLOCKING popup','all windows remain inactive while popup active')
sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active')
i+=1
if event == 'Launch 2nd Window' and not win2_active: # only run if not already showing a window2
win2_active = True
# window 2 layout - note - must be "new" every time a window is created
layout2 = [
[sg.Text('The second window'), sg.Text('', key='_OUTPUT_')],
[sg.Input(do_not_clear=True, key='_IN_')],
[sg.Text('The second window'), sg.Text('', key='-OUTPUT-')],
[sg.Input('', key='-IN-')],
[sg.Button('Show'), sg.Button('Exit')]
]
window2 = sg.Window('Second Window').Layout(layout2)
window2 = sg.Window('Second Window', layout2)
# Read window 2's events. Must use timeout of 0
if win2_active:
# print("reading 2")
event, values = window2.Read(timeout=100)
event, values = window2.read(timeout=100)
# print("win2 ", event)
if event != sg.TIMEOUT_KEY:
print("win2 ", event)
if event == 'Exit' or event is None:
# print("Closing window 2", event)
win2_active = False
window2.Close()
window2.close()
if event == 'Show':
sg.Popup('You entered ', values['_IN_'])
sg.popup('You entered ', values['-IN-'])
window.Close()
window.close()

View file

@ -1,35 +1,39 @@
import PySimpleGUI as sg
"""
PySimpleGUI The Complete Course
Lesson 7 - Multiple Windows
1-lvl nested window
"""
import PySimpleGUI as sg
# Design pattern 1 - First window does not remain active
layout = [[ sg.Text('Window 1'),],
[sg.Input(do_not_clear=True)],
[sg.Text('', size=(20,1), key='_OUTPUT_')],
[sg.Input()],
[sg.Text('', size=(20,1), key='-OUTPUT-')],
[sg.Button('Launch 2')]]
win1 = sg.Window('Window 1').Layout(layout)
win2_active=False
while True:
ev1, vals1 = win1.Read(timeout=100)
if ev1 is None:
break
win1.FindElement('_OUTPUT_').Update(vals1[0])
window1 = sg.Window('Window 1', layout)
window2_active=False
if ev1 == 'Launch 2' and not win2_active:
win2_active = True
win1.Hide()
while True:
event1, values1 = window1.read(timeout=100)
if event1 is None:
break
window1['-OUTPUT-'].update(values1[0])
if event1 == 'Launch 2' and not window2_active:
window2_active = True
window1.hide()
layout2 = [[sg.Text('Window 2')],
[sg.Button('Exit')]]
win2 = sg.Window('Window 2').Layout(layout2)
window2 = sg.Window('Window 2', layout2)
while True:
ev2, vals2 = win2.Read()
ev2, vals2 = window2.read()
if ev2 is None or ev2 == 'Exit':
win2.Close()
win2_active = False
win1.UnHide()
window2.close()
window2_active = False
window1.un_hide()
break
window1.close()

View file

@ -1,34 +1,37 @@
"""
PySimpleGUI The Complete Course
Lesson 7 - Multiple Windows
"""
import PySimpleGUI as sg
"""
PySimpleGUI The Complete Course
Lesson 7
Multiple Independent Windows
"""
# Design pattern 2 - First window remains active
layout = [[ sg.Text('Window 1'),],
[sg.Input(do_not_clear=True)],
[sg.Text('', size=(20,1), key='_OUTPUT_')],
[sg.Input('')],
[sg.Text('', size=(20,1), key='-OUTPUT-')],
[sg.Button('Launch 2'), sg.Button('Exit')]]
win1 = sg.Window('Window 1').Layout(layout)
window1 = sg.Window('Window 1', layout)
win2_active = False
window2_active = False
while True:
ev1, vals1 = win1.Read(timeout=100)
win1.FindElement('_OUTPUT_').Update(vals1[0])
if ev1 is None or ev1 == 'Exit':
event1, values1 = window1.read(timeout=100)
window1['-OUTPUT-'].update(values1[0])
if event1 is None or event1 == 'Exit':
break
if not win2_active and ev1 == 'Launch 2':
win2_active = True
if not window2_active and event1 == 'Launch 2':
window2_active = True
layout2 = [[sg.Text('Window 2')],
[sg.Button('Exit')]]
win2 = sg.Window('Window 2').Layout(layout2)
window2 = sg.Window('Window 2', layout2)
if win2_active:
ev2, vals2 = win2.Read(timeout=100)
if window2_active:
ev2, vals2 = window2.read(timeout=100)
if ev2 is None or ev2 == 'Exit':
win2_active = False
win2.Close()
window2_active = False
window2.close()
window1.close()

View file

@ -1,48 +1,54 @@
import PySimpleGUI as sg
'''
Example of wizard-like PySimpleGUI windows
'''
layout = [[sg.Text('Window 1'), ],
[sg.Input(do_not_clear=True)],
[sg.Text('',size=(20,1), key='_OUTPUT_')],
[sg.Input('')],
[sg.Text('',size=(20,1), key='-OUTPUT-')],
[sg.Button('Next >'), sg.Button('Exit')]]
win1 = sg.Window('Window 1').Layout(layout)
window = sg.Window('Window 1', layout)
win3_active = win2_active = False
window3_active = window2_active = False
while True:
if not win2_active:
ev1, vals1 = win1.Read()
if ev1 is None or ev1 == 'Exit':
if not window2_active:
event1, values1 = window.read()
if event1 is None or event1 == 'Exit':
break
win1.FindElement('_OUTPUT_').Update(vals1[0])
window['-OUTPUT-'].update(values1[0])
if not win2_active and ev1 == 'Next >':
win2_active = True
win1.Hide()
if not window2_active and event1 == 'Next >':
window2_active = True
window.hide()
layout2 = [[sg.Text('Window 2')],
[sg.Button('< Prev'), sg.Button('Next >')]]
win2 = sg.Window('Window 2').Layout(layout2)
window2 = sg.Window('Window 2', layout2)
if win2_active:
ev2, vals2 = win2.Read()
if ev2 in (None, 'Exit', '< Prev'):
win2_active = False
win2.Close()
win1.UnHide()
elif ev2 == 'Next >':
win3_active = True
win2_active = False
win2.Hide()
if window2_active:
event2 = window2.read()[0]
if event2 in (None, 'Exit', '< Prev'):
window2_active = False
window2.close()
window.un_hide()
elif event2 == 'Next >':
window3_active = True
window2_active = False
window2.hide()
layout3 = [[sg.Text('Window 3')],
[sg.Button('< Prev'), sg.Button('Exit')]]
win3 = sg.Window('Window 3').Layout(layout3)
window3 = sg.Window('Window 3', layout3)
if win3_active:
ev3, vals3 = win3.Read()
if window3_active:
ev3, vals3 = window3.read()
if ev3 == '< Prev':
win3.Close()
win3_active = False
win2_active = True
win2.UnHide()
window3.close()
window3_active = False
window2_active = True
window2.un_hide()
elif ev3 in (None, 'Exit'):
break
window.close()

View file

@ -1,24 +1,21 @@
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
layout = [
[sg.Text('Your typed chars appear here:'), sg.Text('', size=(20,1), key='-OUTPUT-')],
[sg.Input(do_not_clear=True, key='-IN-')],
[sg.Button('Show'), sg.Button('Exit')]
]
layout = [
[sg.Text('Your typed chars appear here:'),
sg.Text(size=(20, 1), key='-OUTPUT-')],
[sg.Input('', key='-IN-')],
[sg.Button('Show'), sg.Button('Exit')]
]
window = sg.Window('Window Title').Layout(layout)
window = sg.Window('Window Title', layout)
while True: # Event Loop
event, values = window.Read()
while True:
event, values = window.read()
print(event, values)
if event is None or event == 'Exit':
if event in (None, 'Exit'):
break
if event == 'Show':
# change the "output" element to be the value of "input" element
window.FindElement('-OUTPUT-').Update(values['-IN-'])
# change the "output" element to be the value of "input" element
window['-OUTPUT-'].update(values['-IN-'])
window.Close()
window.close()

View file

@ -1,15 +1,15 @@
import PySimpleGUI as sg
"""
When creating a new PySimpleGUI program from scratch, start here.
These are the accepted design patterns that cover the two primary use cases
1. A "One Shot" window
2. A persistent window that stays open after button clicks (uses an event loop)
3. A persistent window that need to perform Update of an element before the window.read
3. A persistent window that need to perform update of an element before the window.read
"""
# ---------------------------------#
# DESIGN PATTERN 1 - Simple Window #
# ---------------------------------#
import PySimpleGUI as sg
layout = [[ sg.Text('My Oneshot') ],
[ sg.Button('OK') ]]
@ -22,7 +22,6 @@ window.close()
# -------------------------------------#
# DESIGN PATTERN 2 - Persistent Window #
# -------------------------------------#
import PySimpleGUI as sg
layout = [[ sg.Text('My layout') ],
[ sg.Button('OK'), sg.Button('Cancel') ]]
@ -38,14 +37,13 @@ window.close()
# ------------------------------------------------------------------#
# DESIGN PATTERN 3 - Persistent Window with "early update" required #
# ------------------------------------------------------------------#
import PySimpleGUI as sg
layout = [[ sg.Text('My layout', key='-TEXT-KEY-') ],
[ sg.Button('OK'), sg.Button('Cancel') ]]
window = sg.Window('Design Pattern 3', layout, finalize=True)
window['-TEXT-KEY-'].Update('NEW Text') # Change the text field. Finalize allows us to do this
window['-TEXT-KEY-'].update('NEW Text') # Change the text field. Finalize allows us to do this
while True: # Event Loop
event, values = window.read()

View file

@ -1,10 +1,6 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import subprocess
import os
@ -20,34 +16,36 @@ import os
ROOT_PATH = './'
def Launcher():
# def print(line):
# window.FindElement('output').Update(line)
sg.change_look_and_feel('Dark')
sg.ChangeLookAndFeel('Dark')
namesonly = [f for f in os.listdir(ROOT_PATH) if f.endswith('.py') ]
namesonly = [f for f in os.listdir(ROOT_PATH) if f.endswith('.py')]
if len(namesonly) == 0:
namesonly = ['test 1', 'test 2', 'test 3']
sg.SetOptions(element_padding=(0,0), button_element_size=(12,1), auto_size_buttons=False)
sg.set_options(element_padding=(0, 0),
button_element_size=(12, 1), auto_size_buttons=False)
layout = [[sg.Combo(values=namesonly, size=(35,30), key='demofile'),
sg.Button('Run', button_color=('white', '#00168B')),
sg.Button('Program 1'),
sg.Button('Program 2'),
sg.Button('Program 3', button_color=('white', '#35008B')),
sg.Button('EXIT', button_color=('white','firebrick3'))],
[sg.T('', text_color='white', size=(50,1), key='output')]]
window = sg.Window('Floating Toolbar', no_titlebar=True, grab_anywhere=True, keep_on_top=True).Layout(layout)
layout = [[sg.Combo(values=namesonly, size=(35, 30), key='demofile'),
sg.Button('Run', button_color=('white', '#00168B')),
sg.Button('Program 1'),
sg.Button('Program 2'),
sg.Button('Program 3', button_color=('white', '#35008B')),
sg.Button('EXIT', button_color=('white', 'firebrick3'))],
[sg.Text('', text_color='white', size=(50, 1), key='output')]]
window = sg.Window('Floating Toolbar',
layout,
no_titlebar=True,
grab_anywhere=True,
keep_on_top=True)
# ---===--- Loop taking in user input and executing appropriate program --- #
while True:
(event, values) = window.Read()
event, values = window.read()
if event == 'EXIT' or event is None:
break # exit button clicked
if event == 'Program 1':
@ -56,11 +54,14 @@ def Launcher():
print('Run your program 2 here!')
elif event == 'Run':
file = values['demofile']
print('Launching %s'%file)
print('Launching %s' % file)
ExecuteCommandSubprocess('python', os.path.join(ROOT_PATH, file))
else:
print(event)
window.close()
def ExecuteCommandSubprocess(command, *args, wait=False):
try:
if sys.platform == 'linux':
@ -69,10 +70,16 @@ def ExecuteCommandSubprocess(command, *args, wait=False):
# for arg in args:
# arg_string += ' ' + str(arg)
print('python3 ' + arg_string)
sp = subprocess.Popen(['python3 ', arg_string ], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sp = subprocess.Popen(['python3 ', arg_string],
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
else:
arg_string = ' '.join([str(arg) for arg in args])
sp = subprocess.Popen([command, arg_string], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
sp = subprocess.Popen([command, arg_string],
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE)
# sp = subprocess.Popen([command, list(args)], shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if wait:
@ -81,10 +88,9 @@ def ExecuteCommandSubprocess(command, *args, wait=False):
print(out.decode("utf-8"))
if err:
print(err.decode("utf-8"))
except: pass
except:
pass
if __name__ == '__main__':
Launcher()

View file

@ -1,9 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import psutil
"""
@ -32,14 +28,17 @@ class DashGraph(object):
self.color = color
def graph_percentage_abs(self, value):
self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, value), color=self.color)
self.graph_elem.draw_line(
(self.graph_current_item, 0),
(self.graph_current_item, value),
color=self.color)
if self.graph_current_item >= GRAPH_WIDTH:
self.graph_elem.Move(-1,0)
self.graph_elem.move(-1,0)
else:
self.graph_current_item += 1
def text_display(self, text):
self.text_elem.Update(text)
self.text_elem.update(text)
def main():
# A couple of "Uber Elements" that combine several elements and enable bulk edits
@ -47,7 +46,7 @@ def main():
return(sg.Text(text, font=('Helvetica 8'), **kwargs))
def GraphColumn(name, key):
col = sg.Column([[Txt(name, key=key+'_TXT_'), ],
col = sg.Col([[Txt(name, key=key+'_TXT_'), ],
[sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black',
key=key+'_GRAPH_')]], pad=(2, 2))
return col
@ -55,10 +54,11 @@ def main():
num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0,0), margins=(1,1), border_width=0)
sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0,0), margins=(1,1), border_width=0)
# ---------------- Create Layout ----------------
# the clever Red X graphic
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
layout = [[ sg.Button('', image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'),
sg.Text(' CPU Core Usage')] ]
@ -70,7 +70,7 @@ def main():
layout.append(row)
# ---------------- Create Window ----------------
window = sg.Window('PSG System Dashboard',
window = sg.Window('PSG System Dashboard', layout,
keep_on_top=True,
auto_size_buttons=False,
grab_anywhere=True,
@ -79,32 +79,31 @@ def main():
return_keyboard_events=True,
alpha_channel=TRANSPARENCY,
use_default_focus=False,
).Layout(layout).Finalize()
finalize=True)
# setup graphs & initial values
graphs = []
for i in range(num_cores):
graphs.append(DashGraph(window.FindElement('_CPU_'+str(i)+'_GRAPH_'),
window.FindElement('_CPU_'+str(i) + '_TXT_'),
graphs.append(DashGraph(window['_CPU_'+str(i)+'_GRAPH_'],
window['_CPU_'+str(i) + '_TXT_'],
0, colors[i%6]))
# ---------------- main loop ----------------
while (True):
while True :
# --------- Read and update window once every Polling Frequency --------
event, values = window.Read(timeout=POLL_FREQUENCY)
event, values = window.read(timeout=POLL_FREQUENCY)
if event in (None, 'Exit'): # Be nice and give an exit
break
# read CPU for each core
stats = psutil.cpu_percent(percpu=True)
# Update each graph
# update each graph
for i in range(num_cores):
graphs[i].graph_percentage_abs(stats[i])
graphs[i].text_display('{} CPU {:2.0f}'.format(i, stats[i]))
window.Close()
window.close()
if __name__ == "__main__":
# the clever Red X graphic
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
main()
sys.exit(69)

View file

@ -1,20 +1,15 @@
#!/usr/bin/env python
import sys
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import time
import random
import psutil
from threading import Thread
STEP_SIZE=3
STEP_SIZE = 3
SAMPLES = 300
SAMPLE_MAX = 500
CANVAS_SIZE = (300,200)
CANVAS_SIZE = (300, 200)
g_interval = .25
@ -22,6 +17,7 @@ g_cpu_percent = 0
g_procs = None
g_exit = False
def CPU_thread(args):
global g_interval, g_cpu_percent, g_procs, g_exit
@ -32,48 +28,63 @@ def CPU_thread(args):
except:
pass
def main():
global g_exit, g_response_time
# start ping measurement thread
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0,0))
sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0))
layout = [ [sg.Quit( button_color=('white','black')), sg.T('', pad=((100,0),0), font='Any 15', key='output')],
[sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],]
layout = [
[sg.Quit(button_color=('white', 'black')),
sg.Text('', pad=((100, 0), 0), font='Any 15', key='output')],
[sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, SAMPLE_MAX),
background_color='black', key='graph')]
]
window = sg.Window('CPU Graph', grab_anywhere=True, keep_on_top=True, background_color='black', no_titlebar=True, use_default_focus=False).Layout(layout)
window = sg.Window('CPU Graph', layout,
grab_anywhere=True, keep_on_top=True,
background_color='black', no_titlebar=True,
use_default_focus=False)
graph = window.FindElement('graph')
output = window.FindElement('output')
graph = window['graph']
output = window['output']
# start cpu measurement thread
thread = Thread(target=CPU_thread,args=(None,))
thread = Thread(target=CPU_thread, args=(None,))
thread.start()
last_cpu = i = 0
prev_x, prev_y = 0, 0
while True: # the Event Loop
time.sleep(.5)
event, values = window.Read(timeout=0)
if event == 'Quit' or event is None: # always give ths user a way out
event, values = window.read(timeout=0)
if event in ('Quit', None): # always give ths user a way out
break
# do CPU measurement and graph it
current_cpu = int(g_cpu_percent*10)
if current_cpu == last_cpu:
continue
output.Update(current_cpu/10) # show current cpu usage at top
# show current cpu usage at top
output.update(current_cpu/10)
if current_cpu > SAMPLE_MAX:
current_cpu = SAMPLE_MAX
new_x, new_y = i, current_cpu
if i >= SAMPLES:
graph.Move(-STEP_SIZE,0) # shift graph over if full of data
# shift graph over if full of data
graph.move(-STEP_SIZE, 0)
prev_x = prev_x - STEP_SIZE
graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
prev_x, prev_y = new_x, new_y
i += STEP_SIZE if i < SAMPLES else 0
last_cpu = current_cpu
g_exit = True
window.Close()
window.close()
if __name__ == '__main__':
main()

View file

@ -1,10 +1,5 @@
#!/usr/bin/env python
import sys
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import psutil
import time
from threading import Thread
@ -29,6 +24,7 @@ g_cpu_percent = 0
g_procs = None
g_exit = False
def CPU_thread(args):
global g_interval, g_cpu_percent, g_procs, g_exit
@ -44,30 +40,30 @@ def main():
global g_interval, g_procs, g_exit
# ---------------- Create Form ----------------
sg.ChangeLookAndFeel('Black')
layout = [[sg.Text('', size=(8,1), font=('Helvetica', 20),text_color=sg.YELLOWS[0],
justification='center', key='text')],
[sg.Text('', size=(30, 8), font=('Courier New', 12),text_color='white', justification='left', key='processes')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15,0), 0), size=(9,1)),
sg.Spin([x+1 for x in range(10)], 3, key='spin')],]
sg.change_look_and_feel('Black')
layout = [
[sg.Text('', size=(8, 1), font=('Helvetica', 20),
text_color=sg.YELLOWS[0], justification='center', key='text')],
[sg.Text('', size=(30, 8), font=('Courier New', 12),
text_color='white', justification='left', key='processes')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0), size=(9, 1)),
sg.Spin([x+1 for x in range(10)], 3, key='spin')]
]
window = sg.Window('CPU Utilization',
no_titlebar=True,
keep_on_top=True,
alpha_channel=.8,
grab_anywhere=True).Layout(layout)
window = sg.Window('CPU Utilization', layout
no_titlebar=True, keep_on_top=True, alpha_channel=.8, grab_anywhere=True)
# start cpu measurement thread
thread = Thread(target=CPU_thread,args=(None,))
thread = Thread(target=CPU_thread, args=(None,))
thread.start()
timeout_value = 1 # make first read really quick
g_interval = 1
# ---------------- main loop ----------------
while (True):
while True:
# --------- Read and update window --------
event, values = window.Read(timeout=timeout_value, timeout_key='Timeout')
event, values = window.read(timeout=timeout_value, timeout_key='Timeout')
# --------- Do Button Operations --------
if event is None or event == 'Exit':
if event in (None, 'Exit'):
break
timeout_value = int(values['spin']) * 1000
@ -77,11 +73,12 @@ def main():
if g_procs:
# --------- Create list of top % CPU porocesses --------
try:
top = {proc.name() : proc.cpu_percent() for proc in g_procs}
except: pass
top = {proc.name(): proc.cpu_percent() for proc in g_procs}
except:
pass
top_sorted = sorted(top.items(), key=operator.itemgetter(1), reverse=True)
top_sorted = sorted(
top.items(), key=operator.itemgetter(1), reverse=True)
if top_sorted:
top_sorted.pop(0)
display_string = ''
@ -89,11 +86,14 @@ def main():
display_string += '{:2.2f} {}\n'.format(cpu/10, proc)
# --------- Display timer and proceses in window --------
window.FindElement('text').Update('CPU {}'.format(cpu_percent))
window.FindElement('processes').Update(display_string)
window['text'].update('CPU ' + str(cpu_percent))
window['processes'].update(display_string)
g_exit = True
thread.join()
window.close()
if __name__ == "__main__":
main()
main()

View file

@ -1,45 +1,41 @@
#!/usr/bin/env python
import sys
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import psutil
# Yet another usage of CPU data
# ---------------- Create Form ----------------
sg.ChangeLookAndFeel('Black')
sg.change_look_and_feel('Black')
layout = [[sg.Text('CPU Utilization')],
[sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='_text_')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0), size=(9,1)),
sg.Spin([x + 1 for x in range(10)], 3, key='_spin_')]]
[sg.Text('', size=(8, 2), font=('Helvetica', 20),
justification='center', key='-text-')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0), size=(9, 1)),
sg.Spin([x + 1 for x in range(10)], 3, key='-spin-')]]
# Layout the rows of the Window
window = sg.Window('CPU Meter',
layout,
no_titlebar=True,
keep_on_top=True,
grab_anywhere=True).Layout(layout).Finalize()
grab_anywhere=True, finalize=True)
# ---------------- main loop ----------------
interval = 10 # For the first one, make it quick
while (True):
while True:
# --------- Read and update window --------
event, values = window.Read(timeout=interval)
event, values = window.read(timeout=interval)
# --------- Do Button Operations --------
if event is None or event == 'Exit':
if event in (None, 'Exit'):
break
interval = int(values['_spin_'])*1000
interval = int(values['-spin-'])*1000
cpu_percent = psutil.cpu_percent(interval=1)
# --------- Display timer in window --------
window.FindElement('_text_').Update(f'CPU {cpu_percent:02.0f}%')
window['-text-'].update(f'CPU {cpu_percent:02.0f}%')
# Broke out of main loop. Close the window.
window.CloseNonBlocking()
window.CloseNonBlocking()

View file

@ -1,66 +1,67 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
sg.PopupError('Sorry, at the moment this program only runs on Python 3')
sys.exit()
import PySimpleGUI as sg
import email
import imaplib
from datetime import datetime
import calendar
'''
Usage of Notification in PSG
'''
IMAP_SERVER_GMAIL = 'imap.gmail.com' # gmail server address
IMAP_SERVER_HOTMAIL = 'imap-mail.outlook.com' # hotmail server address
################# Change these to match your email setup ################
LOGIN_EMAIL = 'you@mail.com'
LOGIN_PASSWORD = 'your email password'
IMAP_SERVER = IMAP_SERVER_GMAIL # change to match your email service
# change to match your email service
IMAP_SERVER = IMAP_SERVER_GMAIL
MAX_EMAILS = 10
def gui():
sg.ChangeLookAndFeel('Topanga')
sg.SetOptions(border_width=0, margins=(0, 0), element_padding=(4, 0))
layout = [[sg.T('Email New Mail Notification' + 48 * ' '),
sg.Button('', image_data=refresh, button_color=('#282923', '#282923'), key='_refresh_',
tooltip='Refreshes Email'),
sg.Button('', image_data=red_x, button_color=('#282923', '#282923'), key='_quit_',
tooltip='Closes window')],
[sg.T('', key='_status_', size=(25, 1))], ]
sg.change_look_and_feel('Topanga')
sg.set_options(border_width=0, margins=(0, 0), element_padding=(4, 0))
color = ('#282923', '#282923')
layout = [[sg.Text('Email New Mail Notification' + 48 * ' '),
sg.Button('', image_data=refresh,
button_color=color,
key='-refresh-',
tooltip='refreshes Email'),
sg.Button('', image_data=red_x,
button_color=color,
key='-quit-',
tooltip='Closes window')],
[sg.Text('', key='-status-', size=(25, 1))], ]
for i in range(MAX_EMAILS):
layout.append([sg.T('', size=(20, 1), key='{}date'.format(i), font='Sans 8'),
sg.T('', size=(45, 1), font='Sans 8', key='{}from'.format(i))])
layout.append([sg.Text('', size=(20, 1), key='{}date'.format(i), font='Sans 8'),
sg.Text('', size=(45, 1), font='Sans 8', key='{}from'.format(i))])
window = sg.Window('',
layout,
no_titlebar=True,
grab_anywhere=True,
keep_on_top=True,
alpha_channel=0,
).Layout(layout).Finalize()
finalize=True)
# move the window to the upper right corner of the screen
w, h = window.GetScreenDimensions()
window.Move(w - 410, 0)
window.SetAlpha(.9)
window.Refresh()
status_elem = window.FindElement('_status_')
# The Event Loop
w, h = window.get_screen_dimensions()
window.move(w - 410, 0)
window.set_alpha(.9)
window.refresh()
status_elem = window['-status-']
while True:
status_elem.Update('Reading...')
window.Refresh()
status_elem.update('Reading...')
window.refresh()
read_mail(window)
status_elem.Update('')
event, values = window.Read(timeout=30 * 1000) # return every 30 seconds
if event == '_quit_':
status_elem.update('')
# return every 30 seconds
event, values = window.read(timeout=30 * 1000)
if event == '-quit-':
break
@ -78,31 +79,35 @@ def read_mail(window):
n = 0
now = datetime.now()
# get messages from today
search_string = '(SENTON {}-{}-{})'.format(now.day, calendar.month_abbr[now.month], now.year)
search_string = '(SENTON {}-{}-{})'.format(now.day,
calendar.month_abbr[now.month], now.year)
(retcode, messages) = mail.search(None, search_string)
if retcode == 'OK':
msg_list = messages[0].split() # message numbers are separated by spaces, turn into list
# message numbers are separated by spaces, turn into list
msg_list = messages[0].split()
msg_list.sort(reverse=True) # sort messages descending
for n, message in enumerate(msg_list):
if n >= MAX_EMAILS:
break
from_elem = window.FindElement('{}from'.format(n))
date_elem = window.FindElement('{}date'.format(n))
from_elem.Update('') # erase them so you know they're changing
date_elem.Update('')
window.Refresh()
from_elem = window['{}from'.format(n)]
date_elem = window['{}date'.format(n)]
from_elem.update('') # erase them so you know they're changing
date_elem.update('')
window.refresh()
typ, data = mail.fetch(message, '(RFC822)')
for response_part in data:
if isinstance(response_part, tuple):
original = email.message_from_bytes(response_part[1])
date_str = original['Date'][:22]
from_elem.Update(original['From'])
date_elem.Update(date_str)
window.Refresh() # make the window changes show up right away
from_elem.update(original['From'])
date_elem.update(date_str)
window.refresh() # make the window changes show up right away
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
refresh = 'iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAACb0lEQVR4XpVTXUiTbxT/vePdFuF0BTFW9ufVvMlu+iACka6CQY1gQVdtEmTMpSKzzJT/RTdCRHhT4F0Us8LGVqlo1lZaFslWQWBkN+tDkpSpbfNz797T8zy6DbUbf/Dbec7vfOycMwa0DBJjM7Ko72mBtz+KplCS6Ronf3NNxNZBt2qv4dJzL0uKwGRqU/6zHDqyd1dBk32/xMnfXOMxkVPXXYlVSLjykk4fKIb/4zgUSxEO7zRBKd4Bjm/jU9ys8f2fJoCFhRiWl6pw6+Qw0BymhlfT5Lg/xmycHA++ktL+nsRqrUOrdpBpH6hhKC7yhObti0CgKUTu0KTgcd8X4j4aB2bYvj7UPqkQrO/1cU25ESV3eJJO8LzLIQ11/CYXn5Grf4KqGF19E3Ts9iixe2QPm0dtt5PtP6NcHxF5ZVfDhIbeqMQ6E0hcI4ec327jah513T4YDM5TR/dh8vc0hkfHUxI2gwuPKyDLb2wV5cIdePuZZGwWmQxSSyqICFBVyKgJJkFaQW4Hna4THQ4X/gUiD2+QXEwjNZsASJvTgWgMqoY95WWw7raAJdjheeTEeniCTqgZu2IxswnSmGI3gEZjMiQpAMocTC2nJcm4hU9gRjp9E+6Ajb07wKFpHqRVOzKqedFUhOX4HyRnEwSjMQCB8/4IqnxU2DYiaGnsIe7n2UlK61MWe0dbW18Ijdfk/wuy7IXeEEvEvmM+kcRM4XYYSkohW62ChtIS/NKbWGwO8z9+Anp9TNSsQU2wEtVdEZy5o7Gfi7Z5ewj/vxbkPs51kYhVP4zAw3I3IN+ohSVFcfZeEs67Gid/c03E1uEv5QpTFzvZK5EAAAAASUVORK5CYII='
gui()

View file

@ -14,30 +14,38 @@ import time
"""
def time_as_int():
return int(round(time.time() * 100))
# ---------------- Create Form ----------------
sg.ChangeLookAndFeel('Black')
sg.change_look_and_feel('Black')
layout = [[sg.Text('')],
[sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
[sg.Button('Pause', key='-RUN-PAUSE-', button_color=('white', '#001480')),
sg.Button('Reset', button_color=('white', '#007339'), key='-RESET-'),
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
[sg.Text('', size=(8, 2), font=('Helvetica', 20),
justification='center', key='text')],
[sg.Button('Pause', key='-RUN-PAUSE-', button_color=('white', '#001480')),
sg.Button('Reset', button_color=('white', '#007339'), key='-RESET-'),
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
window = sg.Window('Running Timer', layout, no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True, element_padding=(0,0))
window = sg.Window('Running Timer', layout,
no_titlebar=True,
auto_size_buttons=False,
keep_on_top=True,
grab_anywhere=True,
element_padding=(0, 0))
# ---------------- main loop ----------------
current_time, paused_time, paused = 0, 0, False
start_time = time_as_int()
while (True):
while True:
# --------- Read and update window --------
if not paused:
event, values = window.Read(timeout=10)
event, values = window.read(timeout=10)
current_time = time_as_int() - start_time
else:
event, values = window.Read()
event, values = window.read()
# --------- Do Button Operations --------
if event in (None, 'Exit'): # ALWAYS give a way out of program
break
@ -50,10 +58,11 @@ while (True):
paused_time = time_as_int()
else:
start_time = start_time + time_as_int() - paused_time
window['-RUN-PAUSE-'].Update('Run' if paused else 'Pause') # Change button's text
# Change button's text
window['-RUN-PAUSE-'].update('Run' if paused else 'Pause')
# --------- Display timer in window --------
window['text'].Update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60,
(current_time // 100) % 60,
current_time % 100))
window.close()
window['text'].update('{:02d}:{:02d}.{:02d}'.format((current_time // 100) // 60,
(current_time // 100) % 60,
current_time % 100))
window.close()

View file

@ -1,9 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import psutil
"""
@ -20,6 +16,7 @@ GRAPH_WIDTH = 120 # each individual graph size in pixels
GRAPH_HEIGHT = 40
ALPHA = .7
class DashGraph(object):
def __init__(self, graph_elem, starting_count, color):
self.graph_current_item = 0
@ -33,106 +30,118 @@ class DashGraph(object):
self.prev_value = current_value
self.max_sent = max(self.max_sent, delta)
percent_sent = 100 * delta / self.max_sent
self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, percent_sent), color=self.color)
self.graph_elem.draw_line((self.graph_current_item, 0),
(self.graph_current_item, percent_sent),
color=self.color)
if self.graph_current_item >= GRAPH_WIDTH:
self.graph_elem.Move(-1,0)
self.graph_elem.move(-1, 0)
else:
self.graph_current_item += 1
return delta
def graph_percentage_abs(self, value):
self.graph_elem.DrawLine((self.graph_current_item, 0), (self.graph_current_item, value), color=self.color)
self.graph_elem.draw_line((self.graph_current_item, 0),
(self.graph_current_item, value),
color=self.color)
if self.graph_current_item >= GRAPH_WIDTH:
self.graph_elem.Move(-1,0)
self.graph_elem.move(-1, 0)
else:
self.graph_current_item += 1
def human_size(bytes, units=[' bytes','KB','MB','GB','TB', 'PB', 'EB']):
def human_size(bytes, units=[' bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']):
""" Returns a human readable string reprentation of bytes"""
return str(bytes) + units[0] if bytes < 1024 else human_size(bytes>>10, units[1:])
return str(bytes) + units[0] if bytes < 1024 else human_size(bytes >> 10, units[1:])
def main():
# Make the layout less cluttered and allow bulk-changes to text formatting
def Txt(text, **kwargs):
return(sg.Text(text, font=('Helvetica 8'), **kwargs))
# Update a Text Element
def Txt_Update(window, key, value):
window.FindElement(key).Update(value)
# ---------------- Create Window ----------------
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0,0), margins=(1,1), border_width=0)
sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0), margins=(1, 1), border_width=0)
def GraphColumn(name, key):
col = sg.Column([[Txt(name, key=key+'TXT_'), ],
[sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black',
key=key+'GRAPH_')]], pad=(2, 2))
return col
layout = [
[sg.Text(name, font=('Helvetica 8'), key=key+'TXT_')],
[sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT),
(0, 0),
(GRAPH_WIDTH, 100),
background_color='black',
key=key+'GRAPH_')]]
return sg.Col(layout, pad=(2, 2))
layout = [[sg.Text('System Status Dashboard'+' '*18), sg.Button('', image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window')],
[GraphColumn('Net Out', '_NET_OUT_'),
GraphColumn('Net In', '_NET_IN_')],
[GraphColumn('Disk Read', '_DISK_READ_'),
GraphColumn('Disk Write', '_DISK_WRITE_')],
[GraphColumn('CPU Usage', '_CPU_'),
GraphColumn('Memory Usage', '_MEM_')],]
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
layout = [
[sg.Text('System Status Dashboard'+' '*18),
sg.Button('',
image_data=red_x,
button_color=('black', 'black'),
key='Exit',
tooltip='Closes window')],
[GraphColumn('Net Out', '_NET_OUT_'),
GraphColumn('Net In', '_NET_IN_')],
[GraphColumn('Disk Read', '_DISK_READ_'),
GraphColumn('Disk Write', '_DISK_WRITE_')],
[GraphColumn('CPU Usage', '_CPU_'),
GraphColumn('Memory Usage', '_MEM_')], ]
window = sg.Window('PSG System Dashboard',
keep_on_top=True,
auto_size_buttons=False,
grab_anywhere=True,
no_titlebar=True,
default_button_element_size=(12, 1),
return_keyboard_events=True,
alpha_channel=ALPHA,
use_default_focus=False,
).Layout(layout).Finalize()
window = sg.Window('PSG System Dashboard', layout,
keep_on_top=True, auto_size_buttons=False,
grab_anywhere=True, no_titlebar=True,
default_button_element_size=(12, 1),
return_keyboard_events=True, alpha_channel=ALPHA,
use_default_focus=False, finalize=True)
# setup graphs & initial values
netio = psutil.net_io_counters()
net_graph_in = DashGraph(window.FindElement('_NET_IN_GRAPH_'), netio.bytes_recv, '#23a0a0')
net_graph_out = DashGraph(window.FindElement('_NET_OUT_GRAPH_'), netio.bytes_sent, '#56d856')
net_in = window['_NET_IN_GRAPH_']
net_graph_in = DashGraph(net_in,
netio.bytes_recv, '#23a0a0')
net_out = window['_NET_OUT_GRAPH_']
net_graph_out = DashGraph(net_out,
netio.bytes_sent, '#56d856')
diskio = psutil.disk_io_counters()
disk_graph_write = DashGraph(window.FindElement('_DISK_WRITE_GRAPH_'), diskio.write_bytes, '#be45be')
disk_graph_read = DashGraph(window.FindElement('_DISK_READ_GRAPH_'), diskio.read_bytes, '#5681d8')
disk_graph_write = DashGraph(
window['_DISK_WRITE_GRAPH_'], diskio.write_bytes, '#be45be')
disk_graph_read = DashGraph(
window['_DISK_READ_GRAPH_'], diskio.read_bytes, '#5681d8')
cpu_usage_graph = DashGraph(window.FindElement('_CPU_GRAPH_'), 0, '#d34545')
mem_usage_graph = DashGraph(window.FindElement('_MEM_GRAPH_'), 0, '#BE7C29')
cpu_usage_graph = DashGraph(window['_CPU_GRAPH_'], 0, '#d34545')
mem_usage_graph = DashGraph(window['_MEM_GRAPH_'], 0, '#BE7C29')
print(psutil.cpu_percent(percpu=True))
# ---------------- main loop ----------------
while (True):
while True :
# --------- Read and update window once a second--------
event, values = window.Read(timeout=1000)
if event in (None, 'Exit'): # Be nice and give an exit, expecially since there is no titlebar
event, values = window.read(timeout=1000)
# Be nice and give an exit, expecially since there is no titlebar
if event in (None, 'Exit'):
break
# ----- Network Graphs -----
netio = psutil.net_io_counters()
write_bytes = net_graph_out.graph_value(netio.bytes_sent)
read_bytes = net_graph_in.graph_value(netio.bytes_recv)
Txt_Update(window, '_NET_OUT_TXT_', 'Net out {}'.format(human_size(write_bytes)))
Txt_Update(window, '_NET_IN_TXT_', 'Net In {}'.format(human_size(read_bytes)))
window['_NET_OUT_TXT_'].update(
'Net out {}'.format(human_size(write_bytes)))
window['_NET_IN_TXT_'].update(
'Net In {}'.format(human_size(read_bytes)))
# ----- Disk Graphs -----
diskio = psutil.disk_io_counters()
write_bytes = disk_graph_write.graph_value(diskio.write_bytes)
read_bytes = disk_graph_read.graph_value(diskio.read_bytes)
Txt_Update(window, '_DISK_WRITE_TXT_', 'Disk Write {}'.format(human_size(write_bytes)))
Txt_Update(window, '_DISK_READ_TXT_', 'Disk Read {}'.format(human_size(read_bytes)))
window['_DISK_WRITE_TXT_'].update(
'Disk Write {}'.format(human_size(write_bytes)))
window['_DISK_READ_TXT_'].update(
'Disk Read {}'.format(human_size(read_bytes)))
# ----- CPU Graph -----
cpu = psutil.cpu_percent(0)
cpu_usage_graph.graph_percentage_abs(cpu)
Txt_Update(window, '_CPU_TXT_', '{0:2.0f}% CPU Used'.format(cpu))
window['_CPU_TXT_'].update('{0:2.0f}% CPU Used'.format(cpu))
# ----- Memory Graph -----
mem_used = psutil.virtual_memory().percent
mem_usage_graph.graph_percentage_abs(mem_used)
Txt_Update(window, '_MEM_TXT_', '{}% Memory Used'.format(mem_used))
window['_MEM_TXT_'].update('{}% Memory Used'.format(mem_used))
if __name__ == "__main__":
# the clever Red X graphic
red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw=="
main()
sys.exit(69)

View file

@ -1,45 +1,66 @@
#!/usr/bin/env python
import sys
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
sg.ChangeLookAndFeel('Dark')
sg.SetOptions(element_padding=(0, 0))
'''
Usage of Disable elements
'''
sg.change_look_and_feel('Dark')
sg.set_options(element_padding=(0, 0))
layout = [
[sg.T('Notes:', pad=((3, 0), 0)), sg.In(size=(44, 1), background_color='white', text_color='black', key='notes')],
[sg.T('Output:', pad=((3, 0), 0)), sg.T('', size=(44, 1), text_color='white', key='output')],
[sg.CBox('Checkbox:', default=True, pad=((3, 0), 0), disabled=True, key='cbox'), sg.Listbox((1,2,3,4),size=(8,3),disabled=True, key='listbox'),
sg.Radio('Radio 1', default=True, group_id='1', disabled=True, key='radio1'), sg.Radio('Radio 2', default=False, group_id='1', disabled=True, key='radio2')],
[sg.Spin((1,2,3,4),1,disabled=True, key='spin'), sg.OptionMenu((1,2,3,4),disabled=True, key='option'), sg.Combo(values=(1,2,3,4),disabled=True,key='combo')],
[sg.Multiline('Multiline', size=(20,3),disabled=True, key='multi')],
[sg.Slider((1,10), size=(20,20), orientation='h', disabled=True, key='slider')],
[sg.Button('Enable', button_color=('white', 'black')),
sg.Button('Disable', button_color=('white', 'black')),
sg.Button('Reset', button_color=('white', '#9B0023'), key='reset'),
sg.Button('Values', button_color=('white', 'springgreen4')),
sg.Button('Exit', disabled=True, button_color=('white', '#00406B'), key='exit')]]
[ sg.Text('Notes:', pad=((3, 0), 0)),
sg.Input(size=(44, 1), background_color='white', text_color='black', key='notes')],
window = sg.Window("Disable Elements Demo", default_element_size=(12, 1), text_justification='r', auto_size_text=False,
auto_size_buttons=False, keep_on_top=True, grab_anywhere=False,
default_button_element_size=(12, 1)).Layout(layout).Finalize()
[ sg.Text('Output:', pad=((3, 0), 0)),
sg.Text('', size=(44, 1), text_color='white', key='output')],
[sg.CBox('Checkbox:', default=True, pad=((3, 0), 0), disabled=True, key='cbox'),
sg.Listbox((1, 2, 3, 4), size=(8, 3), disabled=True, key='listbox'),
sg.Radio('Radio 1', default=True, group_id='1', disabled=True, key='radio1'),
sg.Radio('Radio 2', default=False, group_id='1', disabled=True, key='radio2')],
[sg.Spin((1, 2, 3, 4), 1, disabled=True, key='spin'),
sg.OptionMenu((1, 2, 3, 4), disabled=True, key='option'),
sg.Combo(values=(1, 2, 3, 4), disabled=True, key='combo')],
[sg.ML('Multiline', size=(20, 3), disabled=True, key='multi')],
[sg.Slider((1, 10), size=(20, 20), orientation='h', disabled=True, key='slider')],
[sg.Button('Enable', button_color=('white', 'black')),
sg.Button('Disable', button_color=('white', 'black')),
sg.Button('Reset', button_color=('white', '#9B0023'), key='reset'),
sg.Button('Values', button_color=('white', 'springgreen4')),
sg.Button('Exit', disabled=True, button_color=('white', '#00406B'), key='exit')]]
window = sg.Window("Disable Elements Demo", layout,
default_element_size=(12, 1),
text_justification='r',
auto_size_text=False,
auto_size_buttons=False,
keep_on_top=True,
grab_anywhere=False,
default_button_element_size=(12, 1),
finalize=True)
key_list = 'cbox', 'listbox', 'radio1', 'radio2', 'spin', 'option', 'combo', 'reset', 'notes', 'multi', 'slider', 'exit'
for key in key_list: window.FindElement(key).Update(disabled=True) # don't do this kind of for-loop
# don't do this kind of for-loop
for key in key_list:
window[key].update(disabled=True)
while True:
event, values = window.Read()
event, values = window.read()
if event in (None, 'exit'):
break
elif event == 'Disable':
for key in key_list: window.FindElement(key).Update(disabled=True)
for key in key_list:
window[key].update(disabled=True)
elif event == 'Enable':
for key in key_list: window.FindElement(key).Update(disabled=False)
for key in key_list:
window[key].update(disabled=False)
elif event == 'Values':
sg.Popup(values, keep_on_top=True)
sg.popup(values, keep_on_top=True)
sys.exit(0)
window.close()

View file

@ -1,29 +1,30 @@
#!/usr/bin/env python
import sys
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import hashlib
import os
'''
Find dups with PySimpleGUI
'''
# ====____====____==== FUNCTION DeDuplicate_folder(path) ====____====____==== #
# Function to de-duplicate the folder passed in #
# --------------------------------------------------------------------------- #
def FindDuplicatesFilesInFolder(path):
shatab = []
total = 0
small_count, dup_count, error_count = 0,0,0
total, small_count, dup_count, error_count = [0]*4
pngdir = path
if not os.path.exists(path):
sg.Popup('Duplicate Finder', '** Folder doesn\'t exist***', path)
sg.popup('Duplicate Finder', '** Folder doesn\'t exist***', path)
return
pngfiles = os.listdir(pngdir)
total_files = len(pngfiles)
for idx, f in enumerate(pngfiles):
if not sg.OneLineProgressMeter('Counting Duplicates', idx + 1, total_files, 'Counting Duplicate Files'):
if not sg.one_line_progress_meter('Counting Duplicates',
idx + 1,
total_files,
'Counting Duplicate Files'):
break
total += 1
fname = os.path.join(pngdir, f)
@ -42,8 +43,10 @@ def FindDuplicatesFilesInFolder(path):
continue
shatab.append(f_sha)
msg = '{} Files processed\n {} Duplicates found'.format(total_files, dup_count)
sg.Popup('Duplicate Finder Ended', msg)
msg = '{} Files processed\n {} Duplicates found'.format(
total_files, dup_count)
sg.popup('Duplicate Finder Ended', msg)
# ====____====____==== Pseudo-MAIN program ====____====____==== #
# This is our main-alike piece of code #
@ -54,9 +57,10 @@ def FindDuplicatesFilesInFolder(path):
if __name__ == '__main__':
source_folder = None
source_folder = sg.PopupGetFolder('Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in')
source_folder = sg.popup_get_folder(
'Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in')
if source_folder is not None:
FindDuplicatesFilesInFolder(source_folder)
else:
sg.PopupCancel('Cancelling', '*** Cancelling ***')
sg.popup_cancel('Cancelling', '*** Cancelling ***')
exit(0)

View file

@ -4,72 +4,79 @@ from shutil import copyfile
import shutil
import os
def Launcher():
sg.ChangeLookAndFeel('LightGreen')
'''
Make a "Windows os" executable with PyInstaller
'''
layout = [[sg.T('PyInstaller EXE Creator', font='Any 15')],
[sg.T('Source Python File'), sg.In(key='_sourcefile_', size=(45,1)), sg.FileBrowse(file_types=(("Python Files", "*.py"),))],
[sg.T('Icon File'), sg.In(key='_iconfile_', size=(45,1)), sg.FileBrowse(file_types=(("Icon Files", "*.ico"),))],
[sg.Frame('Output', font='Any 15',layout= [[sg.Output(size=(65, 15), font='Courier 10')]])],
[sg.ReadFormButton('Make EXE',bind_return_key=True),
sg.SimpleButton('Quit', button_color=('white','firebrick3')),]]
def Launcher():
sg.change_look_and_feel('LightGreen')
layout = [[sg.Text('PyInstaller EXE Creator', font='Any 15')],
[sg.Text('Source Python File'), sg.Input(key='-sourcefile-', size=(45, 1)),
sg.FileBrowse(file_types=(("Python Files", "*.py"),))],
[sg.Text('Icon File'), sg.Input(key='-iconfile-', size=(45, 1)),
sg.FileBrowse(file_types=(("Icon Files", "*.ico"),))],
[sg.Frame('Output', font='Any 15', layout=[
[sg.Output(size=(65, 15), font='Courier 10')]])],
[sg.ReadFormButton('Make EXE', bind_return_key=True),
sg.SimpleButton('Quit', button_color=('white', 'firebrick3')), ]]
window = sg.Window('PySimpleGUI EXE Maker',
layout,
auto_size_text=False,
auto_size_buttons=False,
default_element_size=(20,1,),
default_element_size=(20, 1,),
text_justification='right')
window.Layout(layout)
# ---===--- Loop taking in user input --- #
while True:
(button, values) = window.Read()
if button in ('Quit', None):
break # exit button clicked
source_file = values['_sourcefile_']
icon_file = values['_iconfile_']
event, values = window.read()
if event in ('Exit', 'Quit', None):
break
source_file = values['-sourcefile-']
icon_file = values['-iconfile-']
icon_option = '-i "{}"'.format(icon_file) if icon_file else ''
source_path, source_filename = os.path.split(source_file)
workpath_option = '--workpath "{}"'.format(source_path)
dispath_option = '--distpath "{}"'.format(source_path)
specpath_option = '--specpath "{}"'.format(source_path)
folder_to_remove = os.path.join(source_path,source_filename[:-3])
file_to_remove = os.path.join(source_path, source_filename[:-3]+'.spec')
command_line = 'pyinstaller -wF "{}" {} {} {} {}'.format(source_file, icon_option, workpath_option, dispath_option, specpath_option)
folder_to_remove = os.path.join(source_path, source_filename[:-3])
file_to_remove = os.path.join(
source_path, source_filename[:-3]+'.spec')
command_line = 'pyinstaller -wF "{}" {} {} {} {}'.format(
source_file, icon_option, workpath_option, dispath_option, specpath_option)
if button == 'Make EXE':
if event == 'Make EXE':
try:
print(command_line)
print('Making EXE... this will take a while.. the program has NOT locked up...')
window.Refresh()
print(
'Making EXE...the program has NOT locked up...')
window.refresh()
# print('Running command {}'.format(command_line))
runCommand(command_line)
shutil.rmtree(folder_to_remove)
os.remove(file_to_remove)
print('**** DONE ****')
except:
sg.PopupError('Something went wrong')
sg.popup_error('Something went wrong')
def runCommand(cmd, timeout=None):
""" run shell command
"""
run shell command
@param cmd: command to execute
@param timeout: timeout for command execution
@param cmd: command to execute
@param timeout: timeout for command execution
@return: (return code from command, command output)
"""
@return: (return code from command, command output)
"""
p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
output = ''
out, err = p.communicate()
p.wait(timeout)
return (out, err)
if __name__ == '__main__':
Launcher()

View file

@ -1,6 +1,4 @@
import PySimpleGUI as sg
# import PySimpleGUIQt as sg
# import PySimpleGUIWx as sg
'''
Event Callback Simulation
@ -15,17 +13,28 @@ import PySimpleGUI as sg
# The callback functions
# These callbacks all display a message in a non-blocking way and immediately return
def button1(event, values):
sg.popup_quick_message('Button 1 callback', background_color='red', text_color='white')
sg.popup_quick_message('Button 1 callback',
background_color='red',
text_color='white')
def button2(event, values):
sg.popup_quick_message('Button 2 callback', background_color='green', text_color='white')
sg.popup_quick_message('Button 2 callback',
background_color='green',
text_color='white')
def catch_all(event, values):
sg.popup_quick_message(f'An unplanned event = "{event}" happend', background_color='blue', text_color='white', auto_close_duration=6)
sg.popup_quick_message(f'An unplanned event = "{event}" happend',
background_color='blue',
text_color='white', auto_close_duration=6)
# Lookup dictionary that maps event to function to call. In this case, only 2 event have defined callbacks
func_dict = {'1':button1, '2':button2}
func_dict = {'1': button1, '2': button2}
# Layout the design of the GUI
layout = [[sg.Text('Please click a button')],
@ -50,4 +59,4 @@ while True:
window.close()
# All done!
sg.popup_auto_close('Done... this window auto closes')
sg.popup_auto_close('Done... this window auto closes')

View file

@ -1,66 +1,77 @@
#!/usr/bin/env python
import sys
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
def Everything():
sg.ChangeLookAndFeel('TanBlue')
'''
Example of GUI
'''
def main():
sg.change_look_and_feel('TanBlue')
column1 = [
[sg.Text('Column 1', background_color=sg.DEFAULT_BACKGROUND_COLOR, justification='center', size=(10, 1))],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1', key='spin1')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 2', key='spin2')],
[sg.Text('Column 1', background_color=sg.DEFAULT_BACKGROUND_COLOR,
justification='center', size=(10, 1))],
[sg.Spin(values=('Spin Box 1', '2', '3'),
initial_value='Spin Box 1', key='spin1')],
[sg.Spin(values=('Spin Box 1', '2', '3'),
initial_value='Spin Box 2', key='spin2')],
[sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3', key='spin3')]]
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', key='in1', do_not_clear=True)],
[sg.Checkbox('Checkbox', key='cb1'), sg.Checkbox('My second checkbox!', key='cb2', default=True)],
[sg.InputText('This is my text', key='in1')],
[sg.CBox('Checkbox', key='cb1'), sg.CBox(
'My second checkbox!', key='cb2', default=True)],
[sg.Radio('My first Radio! ', "RADIO1", key='rad1', default=True),
sg.Radio('My second Radio!', "RADIO1", key='rad2')],
[sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3),
key='multi1', do_not_clear=True),
sg.Multiline(default_text='A second multi-line', size=(35, 3), key='multi2', do_not_clear=True)],
[sg.InputCombo(('Combobox 1', 'Combobox 2'), key='combo', size=(20, 1)),
[sg.MLine(default_text='This is the default Text should you decide not to type anything', size=(35, 3),
key='multi1'),
sg.MLine(default_text='A second multi-line', size=(35, 3), key='multi2')],
[sg.Combo(('Combobox 1', 'Combobox 2'), key='combo', size=(20, 1)),
sg.Slider(range=(1, 100), orientation='h', size=(34, 20), key='slide1', default_value=85)],
[sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'), key='optionmenu')],
[sg.OptionMenu(('Menu Option 1', 'Menu Option 2',
'Menu Option 3'), key='optionmenu')],
[sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3), key='listbox'),
sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25, key='slide2', ),
sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75, key='slide3', ),
sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10, key='slide4'),
sg.Column(column1, background_color='gray34')],
sg.Slider(range=(1, 100),
orientation='v',
size=(5, 20),
default_value=25, key='slide2', ),
sg.Slider(range=(1, 100),
orientation='v',
size=(5, 20),
default_value=75, key='slide3', ),
sg.Slider(range=(1, 100),
orientation='v',
size=(5, 20),
default_value=10, key='slide4'),
sg.Col(column1, background_color='gray34')],
[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', key='folder', do_not_clear=True), sg.FolderBrowse()],
[sg.Text('Your Folder', size=(15, 1), justification='right'),
sg.InputText('Default Folder', key='folder'), sg.FolderBrowse()],
[sg.Button('Exit'),
sg.Text(' ' * 40), sg.Button('SaveSettings'), sg.Button('LoadSettings')]
]
window = sg.Window('Form Fill Demonstration', default_element_size=(40, 1), grab_anywhere=False)
# button, values = window.LayoutAndRead(layout, non_blocking=True)
window.Layout(layout)
window = sg.Window('Form Fill Demonstration', layout, default_element_size=(40, 1), grab_anywhere=False)
while True:
event, values = window.Read()
event, values = window.read()
if event == 'SaveSettings':
filename = sg.PopupGetFile('Save Settings', save_as=True, no_window=True)
filename = sg.popup_get_file('Save Settings', save_as=True, no_window=True)
window.SaveToDisk(filename)
# save(values)
elif event == 'LoadSettings':
filename = sg.PopupGetFile('Load Settings', no_window=True)
filename = sg.popup_get_file('Load Settings', no_window=True)
window.LoadFromDisk(filename)
# load(form)
elif event in ('Exit', None):
break
# window.CloseNonBlocking()
window.close()
if __name__ == '__main__':
Everything()
main()

View file

@ -1,28 +1,34 @@
import PySimpleGUI as sg
import sys
button_names = ('close', 'cookbook', 'cpu', 'github', 'pysimplegui', 'run', 'storage', 'timer')
house64='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'
cpu64='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'
timer64='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'
'''
Example of borderless floating toolbar.
'''
button_names = ('close', 'cookbook', 'cpu', 'github',
'pysimplegui', 'run', 'storage', 'timer')
house64 = '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'
cpu64 = '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'
timer64 = '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'
close64 = 'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAEQ0lEQVR42r2XW2wbRRSG/1177TgkdkyoS4shaaWogVIKRAXUVn4BgRBEIRBSkSK1lAakPhTxABJSK6BEtAoXCUHEWwWi4oEXUAVvRUASSBuJliAh5QJp6hrspoGQi69r73LO7Npu6kvsBGek0ezOrvf79szsmbG0D2iwAN8DaMQaFA0YHQFaLwCX6TQuHQAuNtjR2PawD05LZeFzKeC7b/txPoLxU8Aj1BVkAf1wqw/uejeU9RsASaqYQGp+Dv8EAvjgdD9OAg9S14gQOPKED1XNWyv7+lT0VArxiVH0fCUEOqjr3JoKcImN/pYW2EOnQyUJTESBJkdpgGkV8Cj/owDDdx59A8Mf92FT+GpR+KSlBrt6ehE6+hL0pLp6AYbvfusE5FontFgUZ989UVAiDU+X0OsvQ0/EVy4g4MeOQ3a6Mn38wKHet3MkrofzZJMsFlzpeRVaeLF8ASPsb8Javy7nDXRVxdA7x7FpIZQXnrlP0yDJMoKvHVpZBKq23Qv3M8/nzQt6PIah93qhRxaLwvPNhbLmgGP7Drg694mHlVqKwcsWEBItD8DVvleM6WrhRQXUwBSsnpthvclDY++BZLdnflS9YxecrZ2QFGVZePDIYcq5yWuGK47k39NIzlCdDkHxNuYXiJzrz/xIrr4BFpdbfAFyTS1CSi1uf7IDrqeeheyoLihxubsD2sI8UuEFaItUKfen5mahRcLZl7nft7xAvjIQs+GFP2cLCmjRCL5p3oDN6nzR56xIYDl4ORJlCwyqDnT7Z5aFL5G4w4vN8dnVCwymatA9daVkeCkSJQv8qDtxcDKYF86AwKEuSDYbvB+doq/DlnMPJ6uvmzfmSJQk0E9D+OLVcEG4f38bwgNnxLmz9Wl4+z6HZLXm3JuYHMfE7i0ri8Ck3Y3Hx4L0lvYl8Et7H0Xk7NJ7Xe1d8H74GX2/2YyZmv8XY3euo4SUXJkAFyvtEbdc+CsDn2r3Ifrrz3nHvW7Pftzy/kmxdhSCly2Qlmj66Xf88dB2qP6LRme+jauuo67rIDyvHMN4i1esmvlK6QIUTrEISbKxDnDlPkk2BK6VIDhXXaddP6Vk0H6A9wSUn0WKFn2lCgiYbDEmFVXJYjWOuU1LcHudgAASSLS0FnD4dV4TksYxNEOqsMDwgAAxELToSFZFfGaiVWzGNV6MWM4Uyc5OE8wQCr2AqwmxIuoJowX3k5CjZSd6vvxhqcBj921Fc2g8C2Mwzf5sax7zNZZjSdkcCg6/EEgacAYzlLZvRk1kW7rm39iELwZHsgLPATN311rqb7trG+65dT2FXTEg4o1NoDinZKOYQ8ICFo4ADwMJpEwBDrnKIU+YMqZQ0pAbC4QwODwCf0Rd/BQ4IATagM46oI+CeiNPPVS40EDF6M/pJ78Ap+n0PL8Cp7sGs9asgQSFDLxBmKJ6STKBVSbcZsa10gKcJHi/Hv0PWqbBbaFH/AEAAAAASUVORK5CYII='
def main():
btn_css = {
'button_color': ('white', 'black'),
'pad': (0, 0),
}
toolbar_buttons = [[sg.Button('', image_data=close64,button_color=('white', 'black'), pad=(0,0), key='-CLOSE-'),
sg.Button('', image_data=timer64, button_color=('white', 'black'), pad=(0, 0), key='-TIMER-'),
sg.Button('', image_data=house64, button_color=('white', 'black'), pad=(0, 0), key='-HOUSE-'),
sg.Button('', image_data=cpu64, button_color=('white', 'black'), pad=(0,0), key='-CPU-'),]]
toolbar_buttons = [[sg.Button(image_data=close64, **btn_css, key='-CLOSE-'),
sg.Button(image_data=timer64, **btn_css, key='-TIMER-'),
sg.Button(image_data=house64, **btn_css, key='-HOUSE-'),
sg.Button(image_data=cpu64, **btn_css, key='-CPU-'), ]]
# layout = toolbar_buttons
layout = [[sg.Column( toolbar_buttons, background_color='black')]]
layout = [[sg.Col(toolbar_buttons, background_color='black')]]
window = sg.Window('Toolbar', layout, no_titlebar=True, grab_anywhere=True, background_color='black', margins=(0,0))
window = sg.Window('Toolbar', layout, no_titlebar=True,
grab_anywhere=True, background_color='black', margins=(0, 0))
# ---===--- Loop taking in user input --- #
while True:
@ -31,14 +37,16 @@ def main():
if button == '-CLOSE-' or button is None:
break # exit button clicked
elif button == '-TIMER-':
print('Timer Button') # add your call to launch a timer program
# add your call to launch a timer program
print('Timer Button')
elif button == '-CPU-':
print('CPU Button') # add your call to launch a CPU measuring utility
# add your call to launch a CPU measuring utility
print('CPU Button')
elif button == '-HOUSE-':
print('Home Button')
window.close()
if __name__ == '__main__':
main()

View file

@ -1,10 +1,6 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
from tkinter import font
import tkinter
root = tkinter.Tk()
@ -12,38 +8,38 @@ fonts = list(font.families())
fonts.sort()
root.destroy()
sg.ChangeLookAndFeel('Black')
'''
Showing fonts in PSG / tk
'''
layout = [[ sg.Text('My Text Element',
size=(20,1),
auto_size_text=False,
click_submits=True,
relief=sg.RELIEF_GROOVE,
font = 'Courier` 25',
text_color='#FF0000',
background_color='white',
justification='center',
pad=(5,3),
key='_text_',
tooltip='This is a text element',
) ],
[sg.Listbox(fonts, size=(30,20), change_submits=True, key='_list_')],
[sg.Input(key='_in_')],
[ sg.Button('Read', bind_return_key=True), sg.Exit()]]
sg.change_look_and_feel('Black')
window = sg.Window('My new window',
# grab_anywhere=True,
# force_toplevel=True,
).Layout(layout)
layout = [[sg.Text('My Text Element',
size=(20, 1),
click_submits=True,
relief=sg.RELIEF_GROOVE,
font='Courier` 25',
text_color='#FF0000',
background_color='white',
justification='center',
pad=(5, 3),
key='-text-',
tooltip='This is a text element',
)],
[sg.Listbox(fonts, size=(30, 20), change_submits=True, key='-list-')],
[sg.Input(key='-in-')],
[sg.Button('Read', bind_return_key=True), sg.Exit()]]
window = sg.Window('My new window', layout)
while True: # Event Loop
event, values = window.Read()
if event is None or event == 'Exit':
event, values = window.read()
if event in (None, 'Exit'):
break
text_elem = window.FindElement('_text_')
text_elem = window['-text-']
print(event, values)
if values['_in_'] != '':
text_elem.Update(font=values['_in_'])
if values['-in-'] != '':
text_elem.update(font=values['-in-'])
else:
text_elem.Update(font=(values['_list_'][0], 25))
text_elem.update(font=(values['-list-'][0], 25))
window.close()

View file

@ -1,30 +1,34 @@
import PySimpleGUI as sg
# Testing async form, see if can have a slider
# that adjusts the size of text displayed
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
fontSize = 12
layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin'),
sg.Slider(range=(6,172), orientation='h', size=(10,20), change_submits=True, key='slider', font=('Helvetica 20')), sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
layout = [
[sg.Spin([sz for sz in range(6, 172)],
font=('Helvetica 20'),
initial_value=fontSize,
change_submits=True, key='spin'),
sg.Slider(range=(6, 172), orientation='h', size=(10, 20), change_submits=True, key='slider',
font=('Helvetica 20')),
sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]
]
sz = fontSize
window = sg.Window("Font size selector", grab_anywhere=False)
window.Layout(layout)
window = sg.Window("Font size selector", layout, grab_anywhere=False)
while True:
event, values= window.Read()
event, values = window.read()
if event is None or event == 'Quit':
break
sz_spin = int(values['spin'])
sz_slider = int(values['slider'])
sz = sz_spin if sz_spin != fontSize else sz_slider
if sz != fontSize:
fontSize = sz
font = "Helvetica " + str(fontSize)
window.FindElement('text').Update(font=font)
window.FindElement('slider').Update(sz)
window.FindElement('spin').Update(sz)
window['text'].update(font=font)
window['slider'].update(sz)
window['spin'].update(sz)
print("Done.")
window.close()

View file

@ -1,34 +1,37 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
layout = [[sg.Text('This is my sample text',size=(20,1), key='_text_') ],
[sg.CB('Bold', key='_bold_', change_submits=True),
sg.CB('Italics', key='_italics_', change_submits=True),
sg.CB('Underline', key='_underline_', change_submits=True)],
[sg.Slider((6,50), default_value=12, size=(14,20), orientation='h', key='_slider_', change_submits=True),
'''
App that shows "how fonts work in PySimpleGUI".
'''
layout = [[sg.Text('This is my sample text', size=(20, 1), key='-text-')],
[sg.CB('Bold', key='-bold-', change_submits=True),
sg.CB('Italics', key='-italics-', change_submits=True),
sg.CB('Underline', key='-underline-', change_submits=True)],
[sg.Slider((6, 50), default_value=12, size=(14, 20),
orientation='h', key='-slider-', change_submits=True),
sg.Text('Font size')],
[sg.Text('Font string = '), sg.Text('', size=(25,1), key='_fontstring_')],
[ sg.Button('Exit')]]
[sg.Text('Font string = '), sg.Text('', size=(25, 1), key='-fontstring-')],
[sg.Button('Exit')]]
window = sg.Window('Font string builder').Layout(layout)
window = sg.Window('Font string builder', layout)
text_elem = window.FindElement('_text_')
text_elem = window['-text-']
while True: # Event Loop
event, values = window.Read()
event, values = window.read()
if event in (None, 'Exit'):
break
font_string = 'Helvitica '
font_string += str(values['_slider_'])
if values['_bold_']:
font_string += str(values['-slider-'])
if values['-bold-']:
font_string += ' bold'
if values['_italics_']:
if values['-italics-']:
font_string += ' italic'
if values['_underline_']:
if values['-underline-']:
font_string += ' underline'
text_elem.Update(font=font_string)
window.FindElement('_fontstring_').Update('"'+font_string+'"')
text_elem.update(font=int(font_string.split(' ')[1].split('.')[0]))
window['-fontstring-'].update('"'+font_string+'"')
print(event, values)
window.close()

View file

@ -1,53 +1,58 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
# Example of colors in PSG
def main():
# ------- Make a new Window ------- #
window = sg.Window('GoodColors', auto_size_text=True, default_element_size=(30,2))
window.AddRow(sg.Text('Having trouble picking good colors? Try one of the colors defined by PySimpleGUI'))
window = sg.Window('GoodColors', default_element_size=(30, 2))
window.AddRow(sg.Text('Having trouble picking good colors? Try this'))
window.AddRow(sg.Text('Here come the good colors as defined by PySimpleGUI'))
#===== Show some nice BLUE colors with yellow text ===== ===== ===== ===== ===== ===== =====#
text_color = sg.YELLOWS[0]
buttons = (sg.Button('BLUES[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.BLUES))
window.AddRow(sg.T('Button Colors Using PySimpleGUI.BLUES'))
buttons = (sg.Button('BLUES[{}]\n{}'.format(j, c), button_color=(
text_color, c), size=(10, 2)) for j, c in enumerate(sg.BLUES))
window.AddRow(sg.Text('Button Colors Using PySimpleGUI.BLUES'))
window.AddRow(*buttons)
window.AddRow(sg.Text('_' * 100, size=(65, 1)))
#===== Show some nice PURPLE colors with yellow text ===== ===== ===== ===== ===== ===== =====#
buttons = (sg.Button('PURPLES[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.PURPLES))
window.AddRow(sg.T('Button Colors Using PySimpleGUI.PURPLES'))
buttons = (sg.Button('PURPLES[{}]\n{}'.format(j, c), button_color=(
text_color, c), size=(10, 2)) for j, c in enumerate(sg.PURPLES))
window.AddRow(sg.Text('Button Colors Using PySimpleGUI.PURPLES'))
window.AddRow(*buttons)
window.AddRow(sg.Text('_' * 100, size=(65, 1)))
#===== Show some nice GREEN colors with yellow text ===== ===== ===== ===== ===== ===== =====#
buttons = (sg.Button('GREENS[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.GREENS))
window.AddRow(sg.T('Button Colors Using PySimpleGUI.GREENS'))
buttons = (sg.Button('GREENS[{}]\n{}'.format(j, c), button_color=(
text_color, c), size=(10, 2)) for j, c in enumerate(sg.GREENS))
window.AddRow(sg.Text('Button Colors Using PySimpleGUI.GREENS'))
window.AddRow(*buttons)
window.AddRow(sg.Text('_' * 100, size=(65, 1)))
#===== Show some nice TAN colors with yellow text ===== ===== ===== ===== ===== ===== =====#
text_color = sg.GREENS[0] # let's use GREEN text on the tan
buttons = (sg.Button('TANS[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.TANS))
window.AddRow(sg.T('Button Colors Using PySimpleGUI.TANS'))
buttons = (sg.Button('TANS[{}]\n{}'.format(j, c), button_color=(
text_color, c), size=(10, 2)) for j, c in enumerate(sg.TANS))
window.AddRow(sg.Text('Button Colors Using PySimpleGUI.TANS'))
window.AddRow(*buttons)
window.AddRow(sg.Text('_' * 100, size=(65, 1)))
#===== Show some nice YELLOWS colors with black text ===== ===== ===== ===== ===== ===== =====#
text_color = 'black' # let's use black text on the tan
buttons = (sg.Button('YELLOWS[{}]\n{}'.format(j, c), button_color=(text_color, c), size=(10,2)) for j, c in enumerate(sg.YELLOWS))
window.AddRow(sg.T('Button Colors Using PySimpleGUI.YELLOWS'))
buttons = (sg.Button('YELLOWS[{}]\n{}'.format(j, c), button_color=(
text_color, c), size=(10, 2)) for j, c in enumerate(sg.YELLOWS))
window.AddRow(sg.Text('Button Colors Using PySimpleGUI.YELLOWS'))
window.AddRow(*buttons)
window.AddRow(sg.Text('_' * 100, size=(65, 1)))
#===== Add a click me button for fun and SHOW the window ===== ===== ===== ===== ===== ===== =====#
window.AddRow(sg.Button('Click ME!'))
event, values = window.Read() # show it!
event, values = window.read()
window.close()
if __name__ == '__main__':

View file

@ -0,0 +1,48 @@
#!/usr/bin/env python
import PySimpleGUI as sg
'''
Example of colors in PySimpleGUI
'''
def main():
s10 = (10, 2)
window = sg.Window('GoodColors', [
[sg.Text('Having trouble picking good colors? Try this')],
[sg.Text('Here come the good colors as defined by PySimpleGUI')],
[sg.Text('Button Colors Using PySimpleGUI.BLUES')],
[*[sg.Button('BLUES[{}]\n{}'.format(j, c), button_color=(sg.YELLOWS[0], c), size=s10)
for j, c in enumerate(sg.BLUES)]],
[sg.Text('_' * 100, size=(65, 1))],
[sg.Text('Button Colors Using PySimpleGUI.PURPLES')],
[*[sg.Button('PURPLES[{}]\n{}'.format(j, c), button_color=(sg.YELLOWS[0], c), size=s10)
for j, c in enumerate(sg.PURPLES)]],
[sg.Text('_' * 100, size=(65, 1))],
[sg.Text('Button Colors Using PySimpleGUI.GREENS')],
[*[sg.Button('GREENS[{}]\n{}'.format(j, c), button_color=(sg.YELLOWS[0], c), size=s10)
for j, c in enumerate(sg.GREENS)]],
[sg.Text('_' * 100, size=(65, 1))],
[sg.Text('Button Colors Using PySimpleGUI.TANS')],
[*[sg.Button('TANS[{}]\n{}'.format(j, c), button_color=(sg.GREENS[0], c), size=s10)
for j, c in enumerate(sg.TANS)]],
[sg.Text('_' * 100, size=(65, 1))],
[sg.Text('Button Colors Using PySimpleGUI.YELLOWS')],
[*[sg.Button('YELLOWS[{}]\n{}'.format(j, c), button_color=('black', c), size=s10)
for j, c in enumerate(sg.YELLOWS)]],
[sg.Text('_' * 100, size=(65, 1))],
[sg.Button('Click ME!')]
], default_element_size=(30, 2))
event, values = window.read()
window.close()
if __name__ == '__main__':
main()

View file

@ -1,9 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
from gtts import gTTS
from pygame import mixer
import time
@ -19,16 +15,16 @@ import os
'''
layout = [[sg.Text('What would you like me to say?')],
[sg.Multiline(size=(60,10), enter_submits=True)],
[sg.MLine(size=(60,10), enter_submits=True)],
[sg.Button('Speak', bind_return_key=True), sg.Exit()]]
window = sg.Window('Google Text to Speech').Layout(layout)
window = sg.Window('Google Text to Speech', layout)
i = 0
mixer.init()
while True:
event, values = window.Read()
if event is None or event == 'Exit':
event, values = window.read()
if event in (None, 'Exit'):
break
# Get the text and convert to mp3 file
tts = gTTS(text=values[0], lang='en',slow=False)
@ -42,6 +38,8 @@ while True:
mixer.stop()
i += 1
window.close()
# try to remove the temp files. You'll likely be left with 1 to clean up
try:
os.remove('speech0.mp3')

View file

@ -10,21 +10,24 @@ import socket
Note this exact same demo runs with PySimpleGUIWeb by changing the import statement
"""
class Ball():
def __init__(self, x, y, r, graph_elem, *args, **kwargs):
mass = 10
self.body = pymunk.Body(mass,
pymunk.moment_for_circle(mass, 0, r, (0, 0))) # Create a Body with mass and moment
# Create a Body with mass and moment
self.body = pymunk.Body(
mass, pymunk.moment_for_circle(mass, 0, r, (0, 0)))
self.body.position = x, y
self.shape = pymunk.Circle(self.body, r, offset=(0, 0)) # Create a box shape and attach to body
# Create a box shape and attach to body
self.shape = pymunk.Circle(self.body, r, offset=(0, 0))
self.shape.elasticity = 0.99999
self.shape.friction = 0.8
self.gui_circle_figure = None
self.graph_elem = graph_elem
def move(self):
self.graph_elem.RelocateFigure(self.gui_circle_figure, self.body.position[0], ball.body.position[1])
self.graph_elem.RelocateFigure(
self.gui_circle_figure, self.body.position[0], ball.body.position[1])
class Playfield():
@ -37,9 +40,8 @@ class Playfield():
self.arena_balls = [] # type: [] Ball
self.graph_elem = graph_elem # type: sg.Graph
def add_wall(self, pt_from, pt_to):
body = pymunk.Body(body_type=pymunk.Body.STATIC)
body = pymunk.Body(body_type=pymunk.Body.STATIC)
ground_shape = pymunk.Segment(body, pt_from, pt_to, 0.0)
ground_shape.friction = 0.8
ground_shape.elasticity = .99
@ -50,26 +52,35 @@ class Playfield():
x = random.randint(0, 600)
y = random.randint(0, 400)
r = random.randint(1, 10)
self.add_ball(x,y,r)
self.add_ball(x, y, r)
def add_ball(self, x, y, r, fill_color='black', line_color='red'):
ball = Ball(x, y, r, self.graph_elem)
self.arena_balls.append(ball)
area.space.add(ball.body, ball.shape)
ball.gui_circle_figure = self.graph_elem.DrawCircle((x, y), r, fill_color=fill_color, line_color=line_color)
ball.gui_circle_figure = self.graph_elem.draw_circle(
(x, y), r, fill_color=fill_color, line_color=line_color)
return ball
def shoot_a_ball(self, x, y, r, vector=(-10, 0), fill_color='black', line_color='red'):
ball = self.add_ball(x,y,r, fill_color=fill_color, line_color=line_color )
ball = self.add_ball(
x, y, r, fill_color=fill_color, line_color=line_color)
# ball.shape.surface_velocity=10
ball.body.apply_impulse_at_local_point(100*pymunk.Vec2d(vector))
# ------------------- Build and show the GUI Window -------------------
graph_elem = sg.Graph((600, 400), (0, 400), (600, 0), enable_events=True, key='_GRAPH_', background_color='lightblue')
layout = [[sg.Text('Ball Test'), sg.T('My IP {}'.format(socket.gethostbyname(socket.gethostname())))],
# ------------------- Build and show the GUI Window -------------------
graph_elem = sg.Graph((600, 400), (0, 400), (600, 0),
enable_events=True,
key='-GRAPH-',
background_color='lightblue')
hostname = socket.gethostbyname(socket.gethostname())
layout = [[sg.Text('Ball Test'), sg.Text('My IP {}'.format(hostname))],
[graph_elem],
[sg.B('Kick'), sg.B('Player 1 Shoot', size=(15,2)),sg.B('Player 2 Shoot', size=(15,2)), sg.Button('Exit')]]
[sg.Button('Kick'), sg.Button('Player 1 Shoot', size=(15, 2)),
sg.Button('Player 2 Shoot', size=(15, 2)), sg.Button('Exit')]
]
window = sg.Window('Window Title', layout, disable_close=True)
@ -78,20 +89,23 @@ area = Playfield(graph_elem)
# ------------------- GUI Event Loop -------------------
while True: # Event Loop
event, values = window.Read(timeout=10)
event, values = window.read(timeout=10)
# print(event, values)
if event in (None, 'Exit'):
break
area.space.step(0.01)
if event == 'Player 2 Shoot':
area.shoot_a_ball(555, 200, 5, (-10,0), fill_color='green', line_color='green')
area.shoot_a_ball(555, 200, 5, (-10, 0),
fill_color='green', line_color='green')
elif event == 'Player 1 Shoot':
area.shoot_a_ball(10, 200, 5, (10,0))
area.shoot_a_ball(10, 200, 5, (10, 0))
for ball in area.arena_balls:
if event == 'Kick':
ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(1,200)
pos = ball.body.position[0], ball.body.position[1]-random.randint(1, 200)
ball.body.position = pos
ball.move()
window.Close()
window.close()

View file

@ -19,20 +19,22 @@ layout = [[sg.Graph(
key="-GRAPH-",
change_submits=True, # mouse click events
drag_submits=True),],
[sg.Text("", key="info", size=(60, 1))]]
[sg.Text(key='info', size=(60, 1))]]
window = sg.Window("draw rect on image", layout, finalize=True)
# get the graph element for ease of use later
graph = window["-GRAPH-"] # type: sg.Graph
graph.DrawImage(image_file, location=(0,0)) if image_file else None
graph.draw_image(image_file, location=(0,0)) if image_file else None
dragging = False
start_point = end_point = prior_rect = None
while True:
event, values = window.Read()
event, values = window.read()
if event is None:
break # exit
if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse
x, y = values["-GRAPH-"]
if not dragging:
@ -41,13 +43,15 @@ while True:
else:
end_point = (x, y)
if prior_rect:
graph.DeleteFigure(prior_rect)
graph.delete_figure(prior_rect)
if None not in (start_point, end_point):
prior_rect = graph.DrawRectangle(start_point, end_point, line_color='red')
prior_rect = graph.draw_rectangle(start_point, end_point, line_color='red')
elif event.endswith('+UP'): # The drawing has ended because mouse up
info = window.Element("info")
info.Update(value=f"grabbed rectangle from {start_point} to {end_point}")
info = window["info"]
info.update(value=f"grabbed rectangle from {start_point} to {end_point}")
start_point, end_point = None, None # enable grabbing a new rect
dragging = False
else:
print("unhandled event", event, values)

View file

@ -1,31 +1,31 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0,0), graph_top_right=(400, 400), background_color='red', key='graph')],
[sg.T('Change circle color to:'), sg.Button('Red'), sg.Button('Blue'), sg.Button('Move')]]
# Usage of Graph element.
window = sg.Window('Graph test').Layout(layout).Finalize()
layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0, 0), graph_top_right=(400, 400), background_color='red', key='graph')],
[sg.Text('Change circle color to:'), sg.Button('Red'), sg.Button('Blue'), sg.Button('Move')]]
graph = window.FindElement('graph')
circle =graph .DrawCircle((75,75), 25, fill_color='black',line_color='white')
point = graph.DrawPoint((75,75), 10, color='green')
oval = graph.DrawOval((25,300), (100,280), fill_color='purple', line_color='purple' )
rectangle = graph.DrawRectangle((25,300), (100,280), line_color='purple' )
line = graph.DrawLine((0,0), (100,100))
arc = graph.DrawArc((0,0), (400,400), 160, 10, style='arc' ,arc_color='blue')
window = sg.Window('Graph test', layout, finalize=True)
graph = window['graph']
circle = graph.draw_circle((75, 75), 25, fill_color='black', line_color='white')
point = graph.draw_point((75, 75), 10, color='green')
oval = graph.draw_oval((25, 300), (100, 280), fill_color='purple', line_color='purple')
rectangle = graph.draw_rectangle((25, 300), (100, 280), line_color='purple')
line = graph.draw_line((0, 0), (100, 100))
arc = graph.draw_arc((0, 0), (400, 400), 160, 10, style='arc', arc_color='blue')
while True:
event, values = window.Read()
event, values = window.read()
if event is None:
break
if event in ('Blue', 'Red'):
graph.TKCanvas.itemconfig(circle, fill=event)
elif event == 'Move':
graph.MoveFigure(point, 10,10)
graph.MoveFigure(circle, 10,10)
graph.MoveFigure(oval, 10,10)
graph.MoveFigure(rectangle, 10,10)
graph.MoveFigure(arc, 10,10)
graph.MoveFigure(point, 10, 10)
graph.MoveFigure(circle, 10, 10)
graph.MoveFigure(oval, 10, 10)
graph.MoveFigure(rectangle, 10, 10)
graph.MoveFigure(arc, 10, 10)
window.close()

View file

@ -1,27 +1,25 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import ping
from threading import Thread
import time
STEP_SIZE=1
STEP_SIZE = 1
SAMPLES = 1000
CANVAS_SIZE = (1000,500)
CANVAS_SIZE = (1000, 500)
# globale used to communicate with thread.. yea yea... it's working fine
g_exit = False
g_response_time = None
def ping_thread(args):
global g_exit, g_response_time
while not g_exit:
g_response_time = ping.quiet_ping('google.com', timeout=1000)
def main():
global g_exit, g_response_time
@ -29,21 +27,27 @@ def main():
thread = Thread(target=ping_thread, args=(None,))
thread.start()
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0,0))
sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0))
layout = [ [sg.T('Ping times to Google.com', font='Any 12'), sg.Quit(pad=((100,0), 0), button_color=('white', 'black'))],
[sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,500),background_color='black', key='graph')],]
layout = [
[sg.Text('Ping times to Google.com', font='Any 12'),
sg.Quit(pad=((100, 0), 0), button_color=('white', 'black'))],
[sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 500),
background_color='black', key='graph')]
]
window = sg.Window('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False).Layout(layout)
graph = window.FindElement('graph')
window = sg.Window('Canvas test', layout,
grab_anywhere=True, background_color='black',
no_titlebar=False, use_default_focus=False)
graph = window['graph']
prev_response_time = None
i=0
prev_x, prev_y = 0, 0
i = 0
prev_x, prev_y = 0, 0
while True:
event, values = window.Read(timeout=200)
event, values = window.read(timeout=200)
if event == 'Quit' or event is None:
break
if g_response_time is None or prev_response_time == g_response_time:
@ -51,10 +55,10 @@ def main():
new_x, new_y = i, g_response_time[0]
prev_response_time = g_response_time
if i >= SAMPLES:
graph.Move(-STEP_SIZE,0)
graph.move(-STEP_SIZE, 0)
prev_x = prev_x - STEP_SIZE
graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
# window.FindElement('graph').DrawPoint((new_x, new_y), color='red')
graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
# window['graph'].draw_point((new_x, new_y), color='red')
prev_x, prev_y = new_x, new_y
i += STEP_SIZE if i < SAMPLES else 0
@ -62,6 +66,8 @@ def main():
g_exit = True
thread.join()
window.close()
if __name__ == '__main__':
main()

View file

@ -1,29 +0,0 @@
import PySimpleGUI as sg
import random
BAR_WIDTH = 50
BAR_SPACING = 75
EDGE_OFFSET = 3
GRAPH_SIZE = (500,500)
DATA_SIZE = (500,500)
graph = sg.Graph(GRAPH_SIZE, (0,0), DATA_SIZE)
layout = [[sg.Text('Bar graphs using PySimpleGUI')],
[graph],
[sg.Button('OK')]]
window = sg.Window('Window Title', layout)
while True:
event, values = window.Read()
graph.Erase()
if event is None:
break
for i in range(7):
graph_value = random.randint(0, 400)
graph.DrawRectangle(top_left=(i * BAR_SPACING + EDGE_OFFSET, graph_value),
bottom_right=(i * BAR_SPACING + EDGE_OFFSET + BAR_WIDTH, 0), fill_color='blue')
graph.DrawText(text=graph_value, location=(i*BAR_SPACING+EDGE_OFFSET+25, graph_value+10))
window.Close()

View file

@ -1,38 +1,42 @@
# import PySimpleGUIWeb as sg
# import PySimpleGUIQt as sg
import PySimpleGUI as sg
import math
# Yet another usage of Graph element.
SIZE_X = 200
SIZE_Y = 100
NUMBER_MARKER_FREQUENCY = 25
def draw_axis():
graph.draw_line((-SIZE_X,0), (SIZE_X, 0)) # axis lines
graph.draw_line((0,-SIZE_Y), (0,SIZE_Y))
graph.draw_line((-SIZE_X, 0), (SIZE_X, 0)) # axis lines
graph.draw_line((0, -SIZE_Y), (0, SIZE_Y))
for x in range(-SIZE_X, SIZE_X+1, NUMBER_MARKER_FREQUENCY):
graph.draw_line((x,-3), (x,3)) # tick marks
graph.draw_line((x, -3), (x, 3)) # tick marks
if x != 0:
graph.draw_text( str(x), (x,-10), color='green', font='Algerian 15') # numeric labels
# numeric labels
graph.draw_text(str(x), (x, -10), color='green')
for y in range(-SIZE_Y, SIZE_Y+1, NUMBER_MARKER_FREQUENCY):
graph.draw_line((-3,y), (3,y))
graph.draw_line((-3, y), (3, y))
if y != 0:
graph.draw_text( str(y), (-10,y), color='blue')
graph.draw_text(str(y), (-10, y), color='blue')
# Create the graph that will be put into the window
graph = sg.Graph(canvas_size=(400, 400),
graph_bottom_left=(-(SIZE_X+5), -(SIZE_Y+5)),
graph_top_right=(SIZE_X+5, SIZE_Y+5),
background_color='white',
key='graph')
graph_bottom_left=(-(SIZE_X+5), -(SIZE_Y+5)),
graph_top_right=(SIZE_X+5, SIZE_Y+5),
background_color='white',
key='graph')
# Window layout
layout = [[sg.Text('Example of Using Math with a Graph', justification='center', size=(50,1), relief=sg.RELIEF_SUNKEN)],
layout = [[sg.Text('Example of Using Math with a Graph', justification='center', size=(50, 1), relief=sg.RELIEF_SUNKEN)],
[graph],
[sg.Text('y = sin(x / x2 * x1)', font='Algerian 18')],
[sg.Text('x1'),sg.Slider((0,200), orientation='h', enable_events=True,key='_SLIDER_')],
[sg.Text('x2'),sg.Slider((1,200), orientation='h', enable_events=True,key='_SLIDER2_')]]
[sg.Text('y = sin(x / x2 * x1)', font='COURIER 18')],
[sg.Text('x1'), sg.Slider((0, 200), orientation='h',
enable_events=True, key='-SLIDER-')],
[sg.Text('x2'), sg.Slider((1, 200), orientation='h', enable_events=True, key='-SLIDER2-')]]
window = sg.Window('Graph of Sine Function', layout)
@ -43,9 +47,11 @@ while True:
graph.erase()
draw_axis()
prev_x = prev_y = None
for x in range(-SIZE_X,SIZE_X):
y = math.sin(x/int(values['_SLIDER2_']))*int(values['_SLIDER_'])
for x in range(-SIZE_X, SIZE_X):
y = math.sin(x/int(values['-SLIDER2-']))*int(values['-SLIDER-'])
if prev_x is not None:
graph.draw_line((prev_x, prev_y), (x,y), color='red')
graph.draw_line((prev_x, prev_y), (x, y), color='red')
prev_x, prev_y = x, y
window.close()

View file

@ -1,69 +1,76 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import random
import sys
STEP_SIZE=1
'''
Example of random line in Graph element.
'''
STEP_SIZE = 1
SAMPLES = 300
SAMPLE_MAX = 300
CANVAS_SIZE = (300,300)
CANVAS_SIZE = (300, 300)
def main():
global g_exit, g_response_time
layout = [[sg.T('Enter width, height of graph')],
[sg.In(size=(6, 1)), sg.In(size=(6, 1))],
layout = [[sg.Text('Enter width, height of graph')],
[sg.Input(size=(6, 1), key='w'), sg.Input(size=(6, 1), key='h')],
[sg.Ok(), sg.Cancel()]]
window = sg.Window('Enter graph size').Layout(layout)
b,v = window.Read()
if b is None or b == 'Cancel':
sys.exit(69)
w, h = int(v[0]), int(v[1])
CANVAS_SIZE = (w,h)
window = sg.Window('Enter graph size', layout)
event, values = window.read()
if event is None or event == 'Cancel':
return
CANVAS_SIZE = int(values['w']), int(values['h'])
window.close()
# start ping measurement thread
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0,0))
sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0))
layout = [ [sg.Button('Quit', button_color=('white','black'))],
[sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,SAMPLE_MAX),background_color='black', key='graph')],]
layout = [[sg.Button('Quit', button_color=('white', 'black'))],
[sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, SAMPLE_MAX)
background_color='black', key='graph')], ]
window = sg.Window('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False).Layout(layout).Finalize()
graph = window.FindElement('graph')
window = sg.Window('Canvas test', layout, grab_anywhere=True,
background_color='black', no_titlebar=False,
use_default_focus=False, finalize=True)
graph = window['graph']
prev_response_time = None
i=0
i = 0
prev_x, prev_y = 0, 0
graph_value = 250
while True:
# time.sleep(.2)
event, values = window.Read(timeout=0)
event, values = window.read(timeout=0)
if event == 'Quit' or event is None:
break
graph_offset = random.randint(-10, 10)
graph_value = graph_value + graph_offset
if graph_value > SAMPLE_MAX:
graph_value = SAMPLE_MAX
if graph_value < 0:
graph_value = 0
new_x, new_y = i, graph_value
prev_value = graph_value
if i >= SAMPLES:
graph.Move(-STEP_SIZE,0)
graph.move(-STEP_SIZE, 0)
prev_x = prev_x - STEP_SIZE
graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
# window.FindElement('graph').DrawPoint((new_x, new_y), color='red')
graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
prev_x, prev_y = new_x, new_y
i += STEP_SIZE if i < SAMPLES else 0
window.close()
if __name__ == '__main__':

View file

@ -1,21 +1,25 @@
import ping
from threading import Thread
import time
import PySimpleGUI as sg
from threading import Thread
import ping
import time
# Yet another usage of Graph element.
STEP_SIZE=1
STEP_SIZE = 1
SAMPLES = 6000
CANVAS_SIZE = (6000,500)
CANVAS_SIZE = (6000, 500)
# globale used to communicate with thread.. yea yea... it's working fine
g_exit = False
g_response_time = None
def ping_thread(args):
global g_exit, g_response_time
while not g_exit:
g_response_time = ping.quiet_ping('google.com', timeout=1000)
def main():
global g_exit, g_response_time
@ -23,21 +27,22 @@ def main():
thread = Thread(target=ping_thread, args=(None,))
thread.start()
sg.ChangeLookAndFeel('Black')
sg.SetOptions(element_padding=(0,0))
sg.change_look_and_feel('Black')
sg.set_options(element_padding=(0, 0))
layout = [ [sg.T('Ping times to Google.com', font='Any 12'), sg.Quit(pad=((100,0), 0), button_color=('white', 'black'))],
[sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,500),background_color='black', key='graph')],]
layout = [[sg.Text('Ping times to Google.com', font='Any 12'),
sg.Quit(pad=((100, 0), 0), button_color=('white', 'black'))],
[sg.Graph(CANVAS_SIZE, (0, 0), (SAMPLES, 500),
background_color='black', key='graph')]
]
form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False)
form.Layout(layout)
form.Finalize()
graph = form.FindElement('graph')
form = sg.FlexForm('Canvas test', layout, grab_anywhere=True, background_color='black',
no_titlebar=False, use_default_focus=False, finalize=True)
graph = form['graph']
prev_response_time = None
i=0
prev_x, prev_y = 0, 0
i = 0
prev_x, prev_y = 0, 0
while True:
time.sleep(.2)
@ -49,10 +54,10 @@ def main():
new_x, new_y = i, g_response_time[0]
prev_response_time = g_response_time
if i >= SAMPLES:
graph.Move(-STEP_SIZE,0)
graph.move(-STEP_SIZE, 0)
prev_x = prev_x - STEP_SIZE
graph.DrawLine((prev_x, prev_y), (new_x, new_y), color='white')
# form.FindElement('graph').DrawPoint((new_x, new_y), color='red')
graph.draw_line((prev_x, prev_y), (new_x, new_y), color='white')
# form['graph'].draw_point((new_x, new_y), color='red')
prev_x, prev_y = new_x, new_y
i += STEP_SIZE if i < SAMPLES else 0
@ -63,4 +68,4 @@ def main():
if __name__ == '__main__':
main()
exit(69)

View file

@ -1,26 +1,32 @@
import PySimpleGUIWeb as sg
# import PySimpleGUI as sg
import pymunk
import random
import socket
# Yet another usage of Graph element and physics from pymunk.
"""
Demo that shows integrating PySimpleGUI with the pymunk library. This combination
of PySimpleGUI and pymunk could be used to build games.
Note this exact same demo runs with PySimpleGUIWeb by changing the import statement
"""
class Ball():
def __init__(self, x, y, r, *args, **kwargs):
mass = 10
self.body = pymunk.Body(mass,
pymunk.moment_for_circle(mass, 0, r, (0, 0))) # Create a Body with mass and moment
# Create a Body with mass and moment
self.body = pymunk.Body(
mass, pymunk.moment_for_circle(mass, 0, r, (0, 0)))
self.body.position = x, y
self.shape = pymunk.Circle(self.body, r, offset=(0, 0)) # Create a box shape and attach to body
# Create a box shape and attach to body
self.shape = pymunk.Circle(self.body, r, offset=(0, 0))
self.shape.elasticity = 0.99999
self.shape.friction = 0.8
self.gui_circle_figure = None
class Playfield():
def __init__(self):
self.space = pymunk.Space()
@ -30,7 +36,7 @@ class Playfield():
self.add_wall((600, 0), (600, 400)) # right side
def add_wall(self, pt_from, pt_to):
body = pymunk.Body(body_type=pymunk.Body.STATIC)
body = pymunk.Body(body_type=pymunk.Body.STATIC)
ground_shape = pymunk.Segment(body, pt_from, pt_to, 0.0)
ground_shape.friction = 0.8
ground_shape.elasticity = .99
@ -45,25 +51,28 @@ class Playfield():
ball = Ball(x, y, r)
self.arena_balls.append(ball)
area.space.add(ball.body, ball.shape)
ball.gui_circle_figure = graph_elem.DrawCircle((x, y), r, fill_color='black', line_color='red')
ball.gui_circle_figure = graph_elem.draw_circle(
(x, y), r, fill_color='black', line_color='red')
# ------------------- Build and show the GUI Window -------------------
graph_elem = sg.Graph((600, 400), (0, 400), (600, 0), enable_events=True, key='_GRAPH_', background_color='lightblue')
graph_elem = sg.Graph((600, 400), (0, 400), (600, 0),
enable_events=True, key='-GRAPH-', background_color='lightblue')
layout = [[sg.Text('Ball Test'), sg.T('My IP {}'.format(socket.gethostbyname(socket.gethostname())))],
hostname = socket.gethostbyname(socket.gethostname())
layout = [[sg.Text('Ball Test'), sg.Text('My IP '+hostname)],
[graph_elem],
# [sg.Up(), sg.Down()],
[sg.B('Kick'), sg.Button('Exit')]]
[sg.Button('Kick'), sg.Button('Exit')]]
window = sg.Window('Window Title', layout, ).Finalize()
window = sg.Window('Window Title', layout, finalize=True)
area = Playfield()
area.add_balls()
# ------------------- GUI Event Loop -------------------
while True: # Event Loop
event, values = window.Read(timeout=0)
event, values = window.read(timeout=0)
# print(event, values)
if event in (None, 'Exit'):
break
@ -71,7 +80,9 @@ while True: # Event Loop
for ball in area.arena_balls:
if event == 'Kick':
ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(1,200)
graph_elem.RelocateFigure(ball.gui_circle_figure, ball.body.position[0], ball.body.position[1])
ball.body.position = ball.body.position[0], ball.body.position[1]-random.randint(
1, 200)
graph_elem.RelocateFigure(
ball.gui_circle_figure, ball.body.position[0], ball.body.position[1])
window.Close()
window.close()

View file

@ -1,15 +1,18 @@
import PySimpleGUI as sg
"""
Oh yes, the classic "Hello World". The problem is that you
Oh yes, the classic "Hello World". The problem is that you
can do it so many ways using PySimpleGUI
"""
sg.PopupNoButtons('Hello World') # the single line
sg.popup_no_buttons('Hello World') # the single line
sg.Window('Hello world', [[sg.Text('Hello World')]]).Read() # single line using a real window
# single line using a real window
sg.Window('Hello world', [[sg.Text('Hello World')]]).read()
# This is a "Traditional" PySimpleGUI window code. First make a layout, then a window, the read it
layout = [[sg.Text('Hello World')]]
window = sg.Window('Hello world', layout)
event, values = window.Read()
event, values = window.read()
window.close()

View file

@ -1,17 +1,15 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUIQt as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import subprocess
'''
Famouns howdoi command in PSG
'''
# Test this command in a dos window if you are having trouble.
HOW_DO_I_COMMAND = 'python -m howdoi.howdoi'
HOW_DO_I_COMMAND = 'python -m howdoi.howdoi'
# if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file
DEFAULT_ICON = 'E:\\TheRealMyDocs\\Icons\\QuestionMark.ico'
def HowDoI():
'''
@ -22,46 +20,59 @@ def HowDoI():
:return: never returns
'''
# ------- Make a new Window ------- #
sg.ChangeLookAndFeel('GreenTan') # give our form a spiffy set of colors
# give our form a spiffy set of colors
sg.change_look_and_feel('GreenTan')
layout = [
[sg.Text('Ask and your answer will appear here....', size=(40, 1))],
[sg.Output(size=(120, 30), font=('Helvetica 10'))],
[ sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'),
sg.Text('Num Answers',font='Helvetica 15'), sg.Checkbox('Display Full Text', key='full text', font='Helvetica 15'),
sg.T('Command History', font='Helvetica 15'), sg.T('', size=(40,3), text_color=sg.BLUES[0], key='history')],
[sg.Multiline(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]
]
layout = [
[sg.Text('Ask and your answer will appear here....', size=(40, 1))],
[sg.Output(size=(120, 30), font=('Helvetica 10'))],
[sg.Spin(values=(1, 2, 3, 4), initial_value=1, size=(2, 1), key='Num Answers', font='Helvetica 15'),
sg.Text('Num Answers', font='Helvetica 15'), sg.CBox(
'Display Full Text', key='full text', font='Helvetica 15'),
sg.Text('Command History', font='Helvetica 15'), sg.Text('', size=(40, 3), text_color=sg.BLUES[0], key='history')],
[sg.MLine(size=(85, 5), enter_submits=True, key='query', do_not_clear=False),
sg.Button('SEND', button_color=(
sg.YELLOWS[0], sg.BLUES[0]), bind_return_key=True),
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]
]
window = sg.Window('How Do I ??', default_element_size=(30, 2), icon=DEFAULT_ICON, font=('Helvetica',' 13'), default_button_element_size=(8,2), return_keyboard_events=True, no_titlebar=True, grab_anywhere=True)
window.Layout(layout)
window = sg.Window('How Do I ??', layout, default_element_size=(30, 2),
font=('Helvetica', ' 13'),
default_button_element_size=(8, 2),
return_keyboard_events=True, no_titlebar=True,
grab_anywhere=True)
# ---===--- Loop taking in user input and using it to query HowDoI --- #
command_history = []
history_offset = 0
while True:
event, values = window.Read()
event, values = window.read()
if event == 'SEND':
query = values['query'].rstrip()
# print(query)
QueryHowDoI(query, values['Num Answers'], values['full text']) # send the string to HowDoI
# send the string to HowDoI
QueryHowDoI(query, values['Num Answers'], values['full text'])
command_history.append(query)
history_offset = len(command_history)-1
window.FindElement('query').Update('') # manually clear input because keyboard events blocks clear
window.FindElement('history').Update('\n'.join(command_history[-3:]))
# manually clear input because keyboard events blocks clear
window['query'].update('')
window['history'].update('\n'.join(command_history[-3:]))
elif event == None or event == 'EXIT': # if exit button or closed using X
break
elif 'Up' in event and len(command_history): # scroll back in history
# scroll back in history
elif 'Up' in event and len(command_history):
command = command_history[history_offset]
history_offset -= 1 * (history_offset > 0) # decrement is not zero
window.FindElement('query').Update(command)
elif 'Down' in event and len(command_history): # scroll forward in history
history_offset += 1 * (history_offset < len(command_history)-1) # increment up to end of list
# decrement is not zero
history_offset -= 1 * (history_offset > 0)
window['query'].update(command)
# scroll forward in history
elif 'Down' in event and len(command_history):
# increment up to end of list
history_offset += 1 * (history_offset < len(command_history)-1)
command = command_history[history_offset]
window.FindElement('query').Update(command)
window['query'].update(command)
elif 'Escape' in event: # clear currently line
window.FindElement('query').Update('')
window['query'].update('')
window.close()
def QueryHowDoI(Query, num_answers, full_text):
@ -71,15 +82,15 @@ def QueryHowDoI(Query, num_answers, full_text):
:param Query: text english question to ask the HowDoI web engine
:return: nothing
'''
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(HOW_DO_I_COMMAND + ' \"' + Query + '\" -n ' +
str(num_answers)+full_text_option, stdout=subprocess.PIPE)
(output, err) = t.communicate()
print('{:^88}'.format(Query.rstrip()))
print('_'*60)
print(output.decode("utf-8") )
print(output.decode("utf-8"))
exit_code = t.wait()
if __name__ == '__main__':
HowDoI()

View file

@ -1,43 +0,0 @@
import PySimpleGUI as sg
'''
IP Address entry window with digit validation and auto advance
If not a digit or ., the ignored
. will advance the focus to the next entry
On the last input, once it's complete the focus moves to the OK button
Pressing spacebar with focus on OK generates an _OK_ event
'''
# create a short-cut element so don't have to type this in over and over
InIp = lambda key: sg.Input(do_not_clear=True, size=(3, 1), key=key, pad=(0, 2))
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_')],
[InIp(0), sg.T('.'), InIp(1), sg.T('.'), InIp(2), sg.T('.'), InIp(3)],
[sg.Button('Ok', key='_OK_', bind_return_key=True), sg.Button('Exit')]]
window = sg.Window('Window Title', return_keyboard_events=True).Layout(layout)
while True: # Event Loop
event, values = window.Read()
print(event)
if event is None or event == 'Exit':
break
elem = window.FindElementWithFocus()
if elem is not None:
key = elem.Key
value = values[key] # get value of input field that has focus
if event == '.' and key!= '_OK_': # if a ., then advance to next field
elem.Update(value[:-1])
value = value[:-1]
next_elem = window.Element(key+1)
next_elem.SetFocus()
elif event not in '0123456789':
elem.Update(value[:-1])
elif len(value) > 2 and key < 3: # if 2 digits typed in, move on to next input
next_elem = window.Element(key+1)
next_elem.SetFocus()
elif len(value)> 2 and key == 3:
window.Element('_OK_').SetFocus()
print('You entered IP Address {}.{}.{}.{}'.format(*values.values()))
window.Close()

View file

@ -1,12 +1,9 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import os
from PIL import Image, ImageTk
import io
"""
Simple Image Browser based on PySimpleGUI
--------------------------------------------
@ -19,13 +16,14 @@ There are some improvements compared to the PNG browser of the repository:
Dependecies
------------
Python v3
Python3
PIL
"""
# Get the folder containin:g the images from the user
folder = sg.PopupGetFolder('Image folder to open', default_path='')
folder = sg.popup_get_folder('Image folder to open', default_path='')
if not folder:
sg.PopupCancel('Cancelling')
sg.popup_cancel('Cancelling')
raise SystemExit()
# PIL supported image types
@ -35,60 +33,59 @@ img_types = (".png", ".jpg", "jpeg", ".tiff", ".bmp")
flist0 = os.listdir(folder)
# create sub list of image files (no sub folders, no wrong file types)
fnames = [f for f in flist0 if os.path.isfile(os.path.join(folder,f)) and f.lower().endswith(img_types)]
fnames = [f for f in flist0 if os.path.isfile(
os.path.join(folder, f)) and f.lower().endswith(img_types)]
num_files = len(fnames) # number of iamges found
if num_files == 0:
sg.Popup('No files in folder')
sg.popup('No files in folder')
raise SystemExit()
del flist0 # no longer needed
#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# use PIL to read data of one image
#------------------------------------------------------------------------------
def get_img_data(f, maxsize = (1200, 850), first = False):
# ------------------------------------------------------------------------------
def get_img_data(f, maxsize=(1200, 850), first=False):
"""Generate image data using PIL
"""
img = Image.open(f)
img.thumbnail(maxsize)
if first: # tkinter is inactive the first time
bio = io.BytesIO()
img.save(bio, format = "PNG")
img.save(bio, format="PNG")
del img
return bio.getvalue()
return ImageTk.PhotoImage(img)
#------------------------------------------------------------------------------
# ------------------------------------------------------------------------------
# create the form that also returns keyboard events
window = sg.Window('Image Browser', return_keyboard_events=True,
location=(0, 0), use_default_focus=False)
# make these 2 elements outside the layout as we want to "update" them later
# initialize to the first file in the list
filename = os.path.join(folder, fnames[0]) # name of first file in list
image_elem = sg.Image(data = get_img_data(filename, first = True))
image_elem = sg.Image(data=get_img_data(filename, first=True))
filename_display_elem = sg.Text(filename, size=(80, 3))
file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15,1))
file_num_display_elem = sg.Text('File 1 of {}'.format(num_files), size=(15, 1))
# define layout, show and read the form
col = [[filename_display_elem],
[image_elem]]
[image_elem]]
col_files = [[sg.Listbox(values = fnames, change_submits=True, size=(60, 30), key='listbox')],
[sg.Button('Next', size=(8,2)), sg.Button('Prev',
size=(8,2)), file_num_display_elem]]
col_files = [[sg.Listbox(values=fnames, change_submits=True, size=(60, 30), key='listbox')],
[sg.Button('Next', size=(8, 2)), sg.Button('Prev', size=(8, 2)), file_num_display_elem]]
layout = [[sg.Column(col_files), sg.Column(col)]]
layout = [[sg.Col(col_files), sg.Col(col)]]
window.Layout(layout) # Shows form on screen
window = sg.Window('Image Browser', layout, return_keyboard_events=True,
location=(0, 0), use_default_focus=False)
# loop reading the user input and displaying image, filename
i=0
i = 0
while True:
# read the form
event, values = window.Read()
event, values = window.read()
print(event, values)
# perform button and keyboard operations
if event is None:
@ -111,10 +108,10 @@ while True:
filename = os.path.join(folder, fnames[i])
# update window with new image
image_elem.Update(data=get_img_data(filename))
image_elem.update(data=get_img_data(filename))
# update window with filename
filename_display_elem.Update(filename)
filename_display_elem.update(filename)
# update page display
file_num_display_elem.Update('File {} of {}'.format(i+1, num_files))
file_num_display_elem.update('File {} of {}'.format(i+1, num_files))
window.close()

View file

@ -1,32 +1,30 @@
import sys
import PySimpleGUI as sg
import re
QT = True
if QT:
import PySimpleGUIQt as sg
else:
import PySimpleGUI as sg
def autocomplete_popup_show(text_list ):
autocomplete_popup_layout = [[sg.Listbox(values=text_list,
size=(100,20*len(text_list)) if QT else (15, len(text_list)),
change_submits=True,
bind_return_key=True,
auto_size_text=True,
key='_FLOATING_LISTBOX_', enable_events=True)]]
'''
Exampel of Input element features.
'''
def autocomplete_popup_show(text_list):
autocomplete_popup_layout = [
[sg.Listbox(values=text_list,
size=(15, len(text_list)),
change_submits=True, bind_return_key=True,
key='-FLOATING-LISTBOX-', enable_events=True)
]
]
autocomplete_popup = sg.Window("Borderless Window",
autocomplete_popup_layout,
default_element_size=(12, 1),
auto_size_text=False,
auto_size_buttons=False,
no_titlebar=True,
grab_anywhere=True,
auto_size_text=False, keep_on_top=True,
no_titlebar=True, grab_anywhere=True,
return_keyboard_events=True,
keep_on_top=True,
auto_size_buttons=False,
background_color='black',
location=(1320,622),
default_button_element_size=(12, 1))
default_button_element_size=(12, 1),
location=(1320, 622), finalize=True)
window = autocomplete_popup.Layout(autocomplete_popup_layout).Finalize()
return window
@ -34,57 +32,69 @@ def predict_text(input, lista):
pattern = re.compile('.*' + input + '.*')
return [w for w in lista if re.match(pattern, w)]
choices = ['ABC' + str(i) for i in range(30)] # dummy data
layout = [ [sg.Text('Your typed chars appear here:')],
[sg.In(key='_INPUT_', size=(10,1), do_not_clear=True)],
[sg.Button('Show'), sg.Button('Exit')],]
layout = [[sg.Text('Your typed chars appear here:')],
[sg.Input(key='-INPUT-', size=(10, 1))],
[sg.Button('Show'), sg.Button('Exit')], ]
window = sg.Window('Window Title', return_keyboard_events=True).Layout(layout)
window = sg.Window('Window Title', layout, return_keyboard_events=True)
sel_item = -1
skip_event = False
while True: # Event Loop
event, values = window.Read(timeout=500)
if event is None or event == 'Exit':
event, values = window.read(timeout=500)
if event in (None, 'Exit'):
break
if event != sg.TIMEOUT_KEY:
# print(f'ev1 {event}')
in_val = values['_INPUT_']
# print(f'event1 {event}')
in_val = values['-INPUT-']
prediction_list = predict_text(str(in_val), choices)
if prediction_list:
try:
fwindow.Close()
except: pass
fwindow.close()
except:
pass
fwindow = autocomplete_popup_show(prediction_list)
list_elem = fwindow.Element('_FLOATING_LISTBOX_')
list_elem = fwindow['-FLOATING-LISTBOX-']
if event == '_COMBO_':
sg.Popup('Chose', values['_COMBO_'])
sg.popup('Chose', values['_COMBO_'])
if event.startswith('Down') or event.startswith('special 16777237'):
sel_item = sel_item + (sel_item<len(prediction_list))
list_elem.Update(set_to_index=sel_item)
sel_item = sel_item + (sel_item < len(prediction_list))
list_elem.update(set_to_index=sel_item)
skip_event = True
elif event.startswith('Up') or event.startswith('special 16777235'):
sel_item = sel_item - (sel_item>0)
list_elem.Update(set_to_index=sel_item)
sel_item = sel_item - (sel_item > 0)
list_elem.update(set_to_index=sel_item)
skip_event = True
if event == '\r' or event.startswith('special 16777220'):
chosen = vals2['_FLOATING_LISTBOX_']
window.Element('_INPUT_').Update(vals2['_FLOATING_LISTBOX_'][0], select=True)
fwindow.Close()
chosen = values2['-FLOATING-LISTBOX-']
window['-INPUT-'].update(values2['-FLOATING-LISTBOX-']
[0], select=True)
fwindow.close()
sel_item = -1
if event.startswith('Escape') or event.startswith('special 16777216'):
window.Element('_INPUT_').Update('')
window['-INPUT-'].update('')
try:
ev2, vals2 = fwindow.Read(timeout=10)
if ev2 == '_FLOATING_LISTBOX_' and skip_event and QT:
skip_event = False
elif ev2 != sg.TIMEOUT_KEY and ev2 is not None:
# print(f'ev2 {ev2}')
fwindow.Close()
window.Element('_INPUT_').Update(vals2['_FLOATING_LISTBOX_'][0], select=True)
event2, values2 = fwindow.read(timeout=10)
# if event2 == '-FLOATING-LISTBOX-' and skip_event and QT:
# skip_event = False
if event2 != sg.TIMEOUT_KEY and event2 is not None:
# print(f'event2 {event2}')
fwindow.close()
window['-INPUT-'].update(values2['-FLOATING-LISTBOX-']
[0], select=True)
sel_item = -1
fwindow = None
except: pass
window.Close()
except:
pass
window.close()

View file

@ -1,8 +1,4 @@
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
"""
Simple field validation
@ -11,15 +7,18 @@ else:
"""
layout = [[sg.Text('Enter digits:')],
[sg.Input(do_not_clear=True, enable_events=True, key='_INPUT_')],
[sg.Button('Ok', key='_OK_'),sg.Button('Exit')]]
[sg.Input('', enable_events=True, key='-INPUT-')],
[sg.Button('Ok', key='-OK-'), sg.Button('Exit')]]
window = sg.Window('Window Title').Layout(layout)
window = sg.Window('Window Title', layout)
while True: # Event Loop
event, values = window.Read()
if event in (None, 'Exit'):
event, values = window.read()
if event in (None, 'Exit'):
break
if len(values['_INPUT_']) and values['_INPUT_'][-1] not in ('0123456789'): # if last char entered not a digit
window.Element('_INPUT_').Update(values['_INPUT_'][:-1]) # delete last char from input
window.Close()
# if last char entered not a digit
if len(values['-INPUT-']) and values['-INPUT-'][-1] not in ('0123456789'):
# delete last char from input
window['-INPUT-'].update(values['-INPUT-'][:-1])
window.close()

View file

@ -9,19 +9,19 @@ import PySimpleGUI as sg
"""
layout = [[sg.Column([[sg.Text('My Window')],[sg.Input(key='_IN_'), sg.B('My button', key='_OUT_')]], key='_COL_')],
[sg.Button('Invisible'), sg.B('Visible'), sg.Button('Exit')]]
layout = [[sg.Col([[sg.Text('My Window')], [sg.Input(key='-IN-'), sg.Button('My button', key='-OUT-')]], key='-COL-')],
[sg.Button('Invisible'), sg.Button('Visible'), sg.Button('Exit')]]
window = sg.Window('Window Title', layout)
while True: # Event Loop
event, values = window.Read()
event, values = window.read()
print(event, values)
if event in (None, 'Exit'):
break
if event == 'Invisible':
window.Elem('_COL_').Update(visible=False)
window['-COL-'].update(visible=False)
elif event == 'Visible':
window.Elem('_COL_').Update(visible=True)
window['-COL-'].update(visible=True)
window.Close()
window.close()

View file

@ -1,29 +1,28 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
# Recipe for getting keys, one at a time as they are released
# If want to use the space bar, then be sure and disable the "default focus"
layout = [[sg.Text("Press a key or scroll mouse")],
[sg.Text("", size=(18,1), key='text')],
[sg.Text("", size=(18, 1), key='text')],
[sg.Button("OK", key='OK')]]
window = sg.Window("Keyboard Test", return_keyboard_events=True, use_default_focus=False).Layout(layout)
window = sg.Window("Keyboard Test", layout,
return_keyboard_events=True, use_default_focus=False)
# ---===--- Loop taking in user input --- #
while True:
event, values = window.Read()
text_elem = window.FindElement('text')
event, values = window.read()
text_elem = window['text']
if event in ("OK", None):
print(event, "exiting")
break
if len(event) == 1:
text_elem.Update(value='%s - %s' % (event, ord(event)))
text_elem.update(value='%s - %s' % (event, ord(event)))
if event is not None:
text_elem.Update(event)
text_elem.update(event)
window.close()

View file

@ -1,6 +1,4 @@
import PySimpleGUI as sg
# import PySimpleGUIQt as sg
"""
tkinter and Qt do not "activate" buttons by pressing the ENTER key with the button highlighted / in focus
This demo will enable the application to click on a button if the button has focus (is highlighted) and the
@ -18,29 +16,32 @@ import PySimpleGUI as sg
"""
QT_ENTER_KEY1 = 'special 16777220'
QT_ENTER_KEY2 = 'special 16777221'
QT_ENTER_KEY1 = 'special 16777220'
QT_ENTER_KEY2 = 'special 16777221'
layout = [ [sg.T('Test of Enter Key use')],
[sg.In(key='_IN_')],
[sg.Button('Button 1', key='_1_')],
[sg.Button('Button 2', key='_2_')],
[sg.Button('Button 3', key='_3_')], ]
layout = [[sg.Text('Test of Enter Key use')],
[sg.Input(key='-IN-')],
[sg.Button('Button 1', key='-1-')],
[sg.Button('Button 2', key='-2-')],
[sg.Button('Button 3', key='-3-')], ]
window = sg.Window('My new window', layout,
return_keyboard_events=True)
while True: # Event Loop
event, values = window.Read()
event, values = window.read()
if event is None:
break
if event in ('\r', QT_ENTER_KEY1, QT_ENTER_KEY2): # Check for ENTER key
elem = window.FindElementWithFocus() # go find element with Focus
# go find element with Focus
elem = window.find_element_with_focus()
if elem is not None and elem.Type == sg.ELEM_TYPE_BUTTON: # if it's a button element, click it
elem.Click()
# check for buttons that have been clicked
elif event == '_1_':
elif event == '-1-':
print('Button 1 clicked')
elif event == '_2_':
elif event == '-2-':
print('Button 2 clicked')
elif event == '_3_':
print('Button 3 clicked')
elif event == '-3-':
print('Button 3 clicked')
window.close()

View file

@ -1,17 +1,14 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
layout = [[sg.Text("Hold down a key")],
[sg.Button("OK")]]
window = sg.Window("Realtime Keyboard Test", return_keyboard_events=True, use_default_focus=False).Layout(layout)
window = sg.Window("Realtime Keyboard Test", layout, return_keyboard_events=True,
use_default_focus=False)
while True:
event, values = window.Read(timeout=0)
event, values = window.read(timeout=0)
if event == "OK":
print(event, values, "exiting")
@ -23,3 +20,5 @@ while True:
print(event)
elif event is None:
break
window.close()

View file

@ -1,35 +1,34 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
# Demonstrates a number of PySimpleGUI features including:
# Default element size
# auto_size_buttons
# Button
# Dictionary return values
# Update of elements in form (Text, Input)
# do_not_clear of Input elements
# update of elements in form (Text, Input)
layout = [[sg.Text('Enter Your Passcode')],
[sg.Input(size=(10, 1), do_not_clear=True, key='input')],
[sg.Input('', size=(10, 1), key='input')],
[sg.Button('1'), sg.Button('2'), sg.Button('3')],
[sg.Button('4'), sg.Button('5'), sg.Button('6')],
[sg.Button('7'), sg.Button('8'), sg.Button('9')],
[sg.Button('Submit'), sg.Button('0'), sg.Button('Clear')],
[sg.Text('', size=(15, 1), font=('Helvetica', 18), text_color='red', key='out')],
[sg.Text('', size=(15, 1), font=('Helvetica', 18),
text_color='red', key='out')],
]
window = sg.Window('Keypad', default_button_element_size=(5, 2), auto_size_buttons=False, grab_anywhere=False).Layout(layout)
window = sg.Window('Keypad', layout,
default_button_element_size=(5, 2),
auto_size_buttons=False,
grab_anywhere=False)
# Loop forever reading the form's values, updating the Input field
keys_entered = ''
while True:
event, values = window.Read() # read the form
event, values = window.read() # read the form
if event is None: # if the X button clicked, just exit
break
if event == 'Clear': # clear keys if clear button
@ -39,6 +38,8 @@ while True:
keys_entered += event # add the new digit
elif event == 'Submit':
keys_entered = values['input']
window.FindElement('out').Update(keys_entered) # output the final string
window['out'].update(keys_entered) # output the final string
window.FindElement('input').Update(keys_entered) # change the form to reflect current key string
# change the form to reflect current key string
window['input'].update(keys_entered)
window.close()

File diff suppressed because one or more lines are too long

View file

@ -1,10 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import time
import random
@ -23,9 +18,9 @@ def LEDIndicator(key=None, radius=30):
pad=(0, 0), key=key)
def SetLED(window, key, color):
graph = window.FindElement(key)
graph.Erase()
graph.DrawCircle((0, 0), 12, fill_color=color, line_color=color)
graph = window[key]
graph.erase()
graph.draw_circle((0, 0), 12, fill_color=color, line_color=color)
layout = [[sg.Text('My LED Status Indicators', size=(20,1))],
@ -35,11 +30,11 @@ layout = [[sg.Text('My LED Status Indicators', size=(20,1))],
[sg.Text('Server 1'), LEDIndicator('_server1_')],
[sg.Button('Exit')]]
window = sg.Window('My new window', default_element_size=(12, 1), auto_size_text=False).Layout(layout).Finalize()
window = sg.Window('My new window', layout, default_element_size=(12, 1), auto_size_text=False, finalize=True)
i = 0
while True: # Event Loop
event, value = window.Read(timeout=400)
event, value = window.read(timeout=400)
if event == 'Exit' or event is None:
break
if value is None:
@ -49,3 +44,4 @@ while True: # Event Loop
SetLED(window, '_ram_', 'green' if random.randint(1, 10) > 5 else 'red')
SetLED(window, '_temp_', 'green' if random.randint(1, 10) > 5 else 'red')
SetLED(window, '_server1_', 'green' if random.randint(1, 10) > 5 else 'red')
window.close()

View file

@ -34,10 +34,11 @@ def layout0():
window = sg.Window('Generated Layouts', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
Construct #1 - List comprehension to generate a Column of Buttons
@ -46,15 +47,17 @@ def layout0():
"""
def layout1():
layout = [[sg.Button(i)] for i in range(4)] # a List of lists of buttons. Notice the ] after Button
# a List of lists of buttons. Notice the ] after Button
layout = [[sg.Button(i)] for i in range(4)]
window = sg.Window('Generated Layouts', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -70,15 +73,17 @@ def layout1():
See next Construct on how to not use a \ that also results in a VISUALLY similar to a norma layout
"""
def layout2():
layout = [[sg.Button(i) for i in range(4)]] + [[sg.OK()]] # if want to split, can't add newline after + to do it
# if want to split, can't add newline after + to do it
layout = [[sg.Button(i) for i in range(4)]] + [[sg.OK()]]
window = sg.Window('Generated Layouts', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -94,18 +99,21 @@ def layout2():
use this way because it modifies the layout list directly.
"""
def layout3():
# in terms of formatting, the layout to the RIGHT of the = sign looks like a 2-line GUI (ignore the layout +=
layout = [[sg.Button(i) for i in range(4)]]
layout += [[sg.OK()]] # this row is better than, but is the same as
layout.append([sg.Cancel()]) # .. this row in that they both add a new ROW with a button on it
layout = [[sg.Button(i) for i in range(4)]]
# this row is better than, but is the same as
layout += [[sg.OK()]]
# .. this row in that they both add a new ROW with a button on it
layout.append([sg.Cancel()])
window = sg.Window('Generated Layouts', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -115,15 +123,16 @@ def layout3():
items in one list are added to the items in another. That's true for all these contructs using +
"""
def layout4():
layout = [[sg.Text('Enter some info')] + [sg.Input()] + [sg.Exit()]]
layout = [[sg.Text('Enter some info')] + [sg.Input()] + [sg.Exit()]]
window = sg.Window('Generated Layouts', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -147,20 +156,24 @@ def layout4():
Works as long as the things you are adding together look like this [[ ]] (the famous double bracket layouts of PSG)
"""
def layout5():
questions = ('Managing your day-to-day life', 'Coping with problems in your life?', 'Concentrating?',
'Get along with people in your family?', 'Get along with people outside your family?',
'Get along well in social situations?', 'Feel close to another person',
'Feel like you had someone to turn to if you needed help?', 'Felt confident in yourself?')
layout = [[sg.T(qnum + 1, size=(2, 2)), sg.T(q, size=(30, 2))] + [sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, col)) for col in range(5)] for qnum, q in enumerate(questions)]
layout = [[sg.Text(qnum + 1, size=(2, 2)), sg.Text(q, size=(30, 2))] +
[sg.Radio('', group_id=qnum, size=(7, 2),
key=(qnum, col)) for col in range(5)]
for qnum, q in enumerate(questions)]
layout += [[sg.OK()]]
window = sg.Window('Computed Layout Questionnaire', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -181,20 +194,26 @@ def layout6():
'Feel like you had someone to turn to if you needed help?', 'Felt confident in yourself?')
layout = [[]]
for qnum, question in enumerate(questions): # loop through questions
row_layout = [sg.T(qnum + 1, size=(2, 2)), sg.T(question, size=(30, 2))] # rows start with # and question
for radio_num in range(5): # loop through 5 radio buttons and add to row
row_layout += [sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, radio_num))]
layout += [row_layout] # after row is completed layout, tack it onto the end of final layout
for qnum, question in enumerate(questions):
# rows start with # and question
row_layout = [sg.Text(qnum + 1, size=(2, 2)),
sg.Text(question, size=(30, 2))]
layout += [[sg.OK()]] # and finally, add a row to the bottom that has an OK button
# loop through 5 radio buttons and add to row
for radio_num in range(5):
row_layout += [sg.Radio('', group_id=qnum,
size=(7, 2), key=(qnum, radio_num))]
# after row is completed layout, tack it onto the end of final layout
layout += [row_layout]
# and finally, add a row to the bottom that has an OK button
layout += [[sg.OK()]]
window = sg.Window('Computed Layout Questionnaire', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -223,21 +242,24 @@ def layout6():
variable number of rows and a variable number of columns in each row.
"""
def layout7():
questions = ('Managing your day-to-day life', 'Coping with problems in your life?', 'Concentrating?',
'Get along with people in your family?', 'Get along with people outside your family?',
'Get along well in social situations?', 'Feel close to another person',
'Feel like you had someone to turn to if you needed help?', 'Felt confident in yourself?')
layout = [[*[sg.T(qnum + 1, size=(2, 2)), sg.T(q, size=(30, 2))], # These are the question # and the question text
*[sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, col)) for col in range(5)]] for qnum, q in enumerate(questions)] + [[sg.OK()]] # finally add an OK button at the very bottom by using the '+' operator
# These are the question # and the question text
layout = [[*[sg.Text(qnum + 1, size=(2, 2)), sg.Text(q, size=(30, 2))],
# finally add an OK button at the very bottom by using the '+' operator
*[sg.Radio('', group_id=qnum, size=(7, 2), key=(qnum, col)) for col in range(5)]] for qnum, q in enumerate(questions)] + [[sg.OK()]]
window = sg.Window('Questionnaire', layout)
event, values = window.Read()
event, values = window.read()
print(event, values)
window.Close()
window.close()
"""
@ -249,20 +271,25 @@ def layout7():
In this example we start with a "Header" Text element and build from there.
"""
def layout8():
# The questions and answers
q_and_a = [
['1. What is the thing that makes light in our solar system', ['A. The Moon', 'B. Jupiter', 'C. I dunno']],
['2. What is Pluto', ['A. The 9th planet', 'B. A dwarf-planet', 'C. The 8th planet', 'D. Goofies pet dog']],
['1. What is the thing that makes light in our solar system',
['A. The Moon', 'B. Jupiter', 'C. I dunno']],
['2. What is Pluto', ['A. The 9th planet', 'B. A dwarf-planet',
'C. The 8th planet', 'D. Goofies pet dog']],
['3. When did man step foot on the moon', ['A. 1969', 'B. 1960', 'C. 1970', 'D. 1869']], ]
layout = [[sg.Text('Astronomy Quiz #1', font='ANY 15', size=(30, 2))]] # make Header larger
# make Header larger
layout = [[sg.Text('Astronomy Quiz #1', font='ANY 15', size=(30, 2))]]
# "generate" the layout for the window based on the Question and Answer information
for qa in q_and_a:
q = qa[0]
a_list = qa[1]
layout += [[sg.Text(q)]] + [[sg.Radio(a, group_id=q)] for a in a_list] + [[sg.Text('_' * 50)]]
layout += [[sg.Text(q)]] + [[sg.Radio(a, group_id=q)]
for a in a_list] + [[sg.Text('_' * 50)]]
layout += [[sg.Button('Submit Answers', key='SUBMIT')]]
@ -279,11 +306,11 @@ def layout8():
# ------------------------- Call each of the Constructs -------------------------
layout0()
layout1()
layout2()
layout3()
layout4()
layout5()
layout6()
layout7()
layout8()
# layout1()
# layout2()
# layout3()
# layout4()
# layout5()
# layout6()
# layout7()
# layout8()

View file

@ -1,27 +1,29 @@
import PySimpleGUI as sg
names = ['Roberta', 'Kylie', 'Jenny', 'Helen',
'Andrea', 'Meredith','Deborah','Pauline',
'Belinda', 'Wendy']
'Andrea', 'Meredith', 'Deborah', 'Pauline',
'Belinda', 'Wendy']
layout = [ [sg.Text('Listbox with search')],
[sg.Input(do_not_clear=True, size=(20,1),enable_events=True, key='_INPUT_')],
[sg.Listbox(names, size=(20,4), enable_events=True, key='_LIST_')],
[sg.Button('Chrome'), sg.Button('Exit')]]
layout = [[sg.Text('Listbox with search')],
[sg.Input(size=(20, 1), enable_events=True, key='-INPUT-')],
[sg.Listbox(names, size=(20, 4), enable_events=True, key='-LIST-')],
[sg.Button('Chrome'), sg.Button('Exit')]]
window = sg.Window('Listbox with Search').Layout(layout)
window = sg.Window('Listbox with Search', layout)
# Event Loop
while True:
event, values = window.Read()
if event is None or event == 'Exit': # always check for closed window
event, values = window.read()
if event in (None, 'Exit'): # always check for closed window
break
if values['_INPUT_'] != '': # if a keystroke entered in search field
search = values['_INPUT_']
if values['-INPUT-'] != '': # if a keystroke entered in search field
search = values['-INPUT-']
new_values = [x for x in names if search in x] # do the filtering
window.Element('_LIST_').Update(new_values) # display in the listbox
window['-LIST-'].update(new_values) # display in the listbox
else:
window.Element('_LIST_').Update(names) # display original unfiltered list
if event == '_LIST_' and len(values['_LIST_']): # if a list item is chosen
sg.Popup('Selected ', values['_LIST_'])
# display original unfiltered list
window['-LIST-'].update(names)
# if a list item is chosen
if event == '-LIST-' and len(values['-LIST-']):
sg.popup('Selected ', values['-LIST-'])
window.Close()
window.close()

View file

@ -1,13 +1,8 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import os
import mido
import time
import sys
PLAYER_COMMAND_NONE = 0
PLAYER_COMMAND_EXIT = 1
@ -18,6 +13,8 @@ PLAYER_COMMAND_RESTART_SONG = 4
# ---------------------------------------------------------------------- #
# PlayerGUI CLASS #
# ---------------------------------------------------------------------- #
class PlayerGUI():
'''
Class implementing GUI for both initial screen but the player itself
@ -26,8 +23,10 @@ class PlayerGUI():
def __init__(self):
self.Window = None
self.TextElem = None
self.PortList = mido.get_output_names() # use to get the list of midi ports
self.PortList = self.PortList[::-1] # reverse the list so the last one is first
# use to get the list of midi ports
self.PortList = mido.get_output_names()
# reverse the list so the last one is first
self.PortList = self.PortList[::-1]
# ---------------------------------------------------------------------- #
# PlayerChooseSongGUI #
@ -37,20 +36,27 @@ class PlayerGUI():
# ---------------------- DEFINION OF CHOOSE WHAT TO PLAY GUI ----------------------------
layout = [[sg.Text('MIDI File Player', font=("Helvetica", 15), size=(20, 1), text_color='green')],
[sg.Text('File Selection', font=("Helvetica", 15), size=(20, 1))],
[sg.Text('Single File Playback', justification='right'), sg.InputText(size=(65, 1), key='midifile'), sg.FileBrowse(size=(10, 1), file_types=(("MIDI files", "*.mid"),))],
[sg.Text('Or Batch Play From This Folder', auto_size_text=False, justification='right'), sg.InputText(size=(65, 1), key='folder'), sg.FolderBrowse(size=(10, 1))],
helv = ("Helvetica", 15)
layout = [[sg.Text('MIDI File Player', font=helv15, size=(20, 1), text_color='green')],
[sg.Text('File Selection', font=helv15, size=(20, 1))],
[sg.Text('Single File Playback', justification='right'),
sg.InputText(size=(65, 1), key='midifile'),
sg.FileBrowse(size=(10, 1), file_types=(("MIDI files", "*.mid"),))],
[sg.Text('Or Batch Play From This Folder', auto_size_text=False, justification='right'),
sg.InputText(size=(65, 1), key='folder'),
sg.FolderBrowse(size=(10, 1))],
[sg.Text('_' * 250, auto_size_text=False, size=(100, 1))],
[sg.Text('Choose MIDI Output Device', size=(22, 1)),
sg.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), key='device')],
[sg.Text('_' * 250, auto_size_text=False, size=(100, 1))],
[sg.SimpleButton('PLAY', size=(12, 2), button_color=('red', 'white'), font=("Helvetica", 15), bind_return_key=True), sg.Text(' ' * 2, size=(4, 1)), sg.Cancel(size=(8, 2), font=("Helvetica", 15))]]
[sg.SimpleButton('PLAY', size=(12, 2), button_color=('red', 'white'), font=helv15, bind_return_key=True),
sg.Text(' ' * 2, size=(4, 1)),
sg.Cancel(size=(8, 2), font=helv15)]]
window = sg.Window('MIDI File Player', auto_size_text=False, default_element_size=(30, 1), font=("Helvetica", 12)).Layout(layout)
window = sg.Window('MIDI File Player', layout, auto_size_text=False,
default_element_size=(30, 1), font=helv)
self.Window = window
return window.Read()
return window.read()
def PlayerPlaybackGUIStart(self, NumFiles=1):
# ------- Make a new FlexForm ------- #
@ -60,37 +66,44 @@ class PlayerGUI():
image_next = './ButtonGraphics/Next.png'
image_exit = './ButtonGraphics/Exit.png'
self.TextElem = sg.T('Song loading....', size=(70, 5 + NumFiles), font=("Helvetica", 14), auto_size_text=False)
self.SliderElem = sg.Slider(range=(1, 100), size=(50, 8), orientation='h', text_color='#f0f0f0')
self.TextElem = sg.Text('Song loading....',
size=(70, 5 + NumFiles),
font=("Helvetica", 14), auto_size_text=False)
self.SliderElem = sg.Slider(range=(1, 100),
size=(50, 8),
orientation='h', text_color='#f0f0f0')
css = {
'image_size': (50, 50),
'image_subsample': 2,
'border_width': 0,
'button_color': sg.TRANSPARENT_BUTTON
}
layout = [
[sg.T('MIDI File Player', size=(30, 1), font=("Helvetica", 25))],
[self.TextElem],
[self.SliderElem],
[sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
image_filename=image_pause, image_size=(50,50), image_subsample=2, border_width=0, key='PAUSE'), sg.T(' '),
sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
image_filename=image_next, image_size=(50,50), image_subsample=2, border_width=0, key='NEXT'), sg.T(' '),
sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
image_filename=image_restart, image_size=(50,50), image_subsample=2, border_width=0, key='Restart Song'), sg.T(' '),
sg.Button('', button_color=sg.TRANSPARENT_BUTTON,
image_filename=image_exit, image_size=(50,50), image_subsample=2, border_width=0,key='EXIT')]
]
[sg.Text('MIDI File Player', size=(30, 1), font=("Helvetica", 25))],
[self.TextElem],
[self.SliderElem],
[sg.Button('', image_filename=image_pause, **css, key='PAUSE'), sg.Text(' '),
sg.Button('', image_filename=image_next, **css, key='NEXT'), sg.Text(' '),
sg.Button('', image_filename=image_restart, **css, key='Restart Song'), sg.Text(' '),
sg.Button('', image_filename=image_exit, **css, key='EXIT')]
]
window = sg.Window('MIDI File Player', default_element_size=(30, 1), font=("Helvetica", 25)).Layout(layout).Finalize()
window = sg.Window('MIDI File Player', layout, default_element_size=(
30, 1), font=("Helvetica", 25), finalize=True)
self.Window = window
# ------------------------------------------------------------------------- #
# PlayerPlaybackGUIUpdate #
# Refresh the GUI for the main playback interface (must call periodically #
# ------------------------------------------------------------------------- #
def PlayerPlaybackGUIUpdate(self, DisplayString):
window = self.Window
if 'window' not in locals() or window is None: # if the widnow has been destoyed don't mess with it
# if the widnow has been destoyed don't mess with it
if 'window' not in locals() or window is None:
return PLAYER_COMMAND_EXIT
self.TextElem.Update(DisplayString)
event, (values) = window.Read(timeout=0)
self.TextElem.update(DisplayString)
event, (values) = window.read(timeout=0)
if event is None:
return PLAYER_COMMAND_EXIT
if event == 'PAUSE':
@ -118,38 +131,42 @@ def main():
'''
return int(round(time.time() * 1000))
pback = PlayerGUI()
button, values = pback.PlayerChooseSongGUI()
if button != 'PLAY':
sg.PopupCancel('Cancelled...\nAutoclose in 2 sec...', auto_close=True, auto_close_duration=2)
sys.exit(69)
sg.popup_cancel('Cancelled...\nAutoclose in 2 sec...',
auto_close=True, auto_close_duration=2)
return
if values['device']:
midi_port = values['device'][0]
else:
sg.PopupCancel('No devices found\nAutoclose in 2 sec...', auto_close=True, auto_close_duration=2)
sg.popup_cancel('No devices found\nAutoclose in 2 sec...',
auto_close=True, auto_close_duration=2)
batch_folder = values['folder']
midi_filename = values['midifile']
# ------ Build list of files to play --------------------------------------------------------- #
if batch_folder:
filelist = os.listdir(batch_folder)
filelist = [batch_folder+'/'+f for f in filelist if f.endswith(('.mid', '.MID'))]
filelist = [batch_folder+'/' +
f for f in filelist if f.endswith(('.mid', '.MID'))]
filetitles = [os.path.basename(f) for f in filelist]
elif midi_filename: # an individual filename
filelist = [midi_filename,]
filetitles = [os.path.basename(midi_filename),]
filelist = [midi_filename, ]
filetitles = [os.path.basename(midi_filename), ]
else:
sg.PopupError('*** Error - No MIDI files specified ***')
sys.exit(666)
sg.popup_error('*** Error - No MIDI files specified ***')
return
# ------ LOOP THROUGH MULTIPLE FILES --------------------------------------------------------- #
pback.PlayerPlaybackGUIStart(NumFiles=len(filelist) if len(filelist) <=10 else 10)
pback.PlayerPlaybackGUIStart(NumFiles=len(filelist) if len(filelist) <= 10 else 10)
port = None
# Loop through the files in the filelist
for now_playing_number, current_midi_filename in enumerate(filelist):
display_string = 'Playing Local File...\n{} of {}\n{}'.format(now_playing_number+1, len(filelist), current_midi_filename)
display_string = 'Playing Local File...\n{} of {}\n{}'.format(
now_playing_number+1, len(filelist), current_midi_filename)
midi_title = filetitles[now_playing_number]
# --------------------------------- REFRESH THE GUI ----------------------------------------- #
pback.PlayerPlaybackGUIUpdate(display_string)
@ -164,16 +181,19 @@ def main():
try:
mid = mido.MidiFile(filename=midi_filename)
except:
print('****** Exception trying to play MidiFile filename = {}***************'.format(midi_filename))
sg.PopupError('Exception trying to play MIDI file:', midi_filename, 'Skipping file')
print(' Fail at playing Midi file = {}****'.format(midi_filename))
sg.popup_error('Exception trying to play MIDI file:',
midi_filename, 'Skipping file')
continue
# 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(filetitles[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):
while True :
start_playback_time = GetCurrentTime()
port.reset()
@ -181,12 +201,14 @@ def main():
#################### GUI - read values ##################
if not midi_msg_number % 4: # update the GUI every 4 MIDI messages
t = (GetCurrentTime() - start_playback_time)//1000
display_midi_len = '{:02d}:{:02d}'.format(*divmod(int(midi_length_in_seconds),60))
display_midi_len = '{:02d}:{:02d}'.format(
*divmod(int(midi_length_in_seconds), 60))
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)
# 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
if paused:
@ -219,9 +241,9 @@ def main():
if cancelled:
break
# ---------------------------------------------------------------------- #
# LAUNCH POINT -- program starts and ends here #
# ---------------------------------------------------------------------- #
if __name__ == '__main__':
main()

View file

@ -1,65 +1,75 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
def MachineLearningGUI():
sg.SetOptions(text_justification='right')
sg.set_options(text_justification='right')
flags = [[sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))],
[sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)],
[sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))],
[sg.Checkbox('Normalize', size=(12, 1), default=True), sg.Checkbox('Verbose', size=(20, 1))],
[sg.Checkbox('Cluster', size=(12, 1)), sg.Checkbox('Flush Output', size=(20, 1), default=True)],
[sg.Checkbox('Write Results', size=(12, 1)), sg.Checkbox('Keep Intermediate Data', size=(20, 1))],]
flags = [[sg.CB('Normalize', size=(12, 1), default=True), sg.CB('Verbose', size=(20, 1))],
[sg.CB('Cluster', size=(12, 1)), sg.CB(
'Flush Output', size=(20, 1), default=True)],
[sg.CB('Write Results', size=(12, 1)), sg.CB(
'Keep Intermediate Data', size=(20, 1))],
[sg.CB('Normalize', size=(12, 1), default=True),
sg.CB('Verbose', size=(20, 1))],
[sg.CB('Cluster', size=(12, 1)), sg.CB(
'Flush Output', size=(20, 1), default=True)],
[sg.CB('Write Results', size=(12, 1)), sg.CB('Keep Intermediate Data', size=(20, 1))], ]
loss_functions = [[sg.Radio('Cross-Entropy', 'loss', size=(12, 1)), sg.Radio('Logistic', 'loss', default=True, size=(12, 1))],
[sg.Radio('Hinge', 'loss', size=(12, 1)), sg.Radio('Huber', 'loss', size=(12, 1))],
[sg.Radio('Kullerback', 'loss', size=(12, 1)), sg.Radio('MAE(L1)', 'loss', size=(12, 1))],
[sg.Radio('MSE(L2)', 'loss', size=(12, 1)), sg.Radio('MB(L0)', 'loss', size=(12, 1))],]
loss_functions = [[sg.Rad('Cross-Entropy', 'loss', size=(12, 1)), sg.Rad('Logistic', 'loss', default=True, size=(12, 1))],
[sg.Rad('Hinge', 'loss', size=(12, 1)),
sg.Rad('Huber', 'loss', size=(12, 1))],
[sg.Rad('Kullerback', 'loss', size=(12, 1)),
sg.Rad('MAE(L1)', 'loss', size=(12, 1))],
[sg.Rad('MSE(L2)', 'loss', size=(12, 1)), sg.Rad('MB(L0)', 'loss', size=(12, 1))], ]
command_line_parms = [[sg.Text('Passes', size=(8, 1)), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1)),
sg.Text('Steps', size=(8, 1), pad=((7,3))), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1))],
[sg.Text('ooa', size=(8, 1)), sg.In(default_text='6', size=(8, 1)), sg.Text('nn', size=(8, 1)),
sg.In(default_text='10', size=(10, 1))],
[sg.Text('q', size=(8, 1)), sg.In(default_text='ff', size=(8, 1)), sg.Text('ngram', size=(8, 1)),
sg.In(default_text='5', size=(10, 1))],
[sg.Text('l', size=(8, 1)), sg.In(default_text='0.4', size=(8, 1)), sg.Text('Layers', size=(8, 1)),
sg.Drop(values=('BatchNorm', 'other'), auto_size_text=True)],]
sg.Text('Steps', size=(8, 1), pad=((7, 3))), sg.Spin(values=[i for i in range(1, 1000)], initial_value=20, size=(6, 1))],
[sg.Text('ooa', size=(8, 1)), sg.Input(default_text='6', size=(8, 1)), sg.Text('nn', size=(8, 1)),
sg.Input(default_text='10', size=(10, 1))],
[sg.Text('q', size=(8, 1)), sg.Input(default_text='ff', size=(8, 1)), sg.Text('ngram', size=(8, 1)),
sg.Input(default_text='5', size=(10, 1))],
[sg.Text('l', size=(8, 1)), sg.Input(default_text='0.4', size=(8, 1)), sg.Text('Layers', size=(8, 1)),
sg.Drop(values=('BatchNorm', 'other'))], ]
layout = [[sg.Frame('Command Line Parameteres', command_line_parms, title_color='green', font='Any 12')],
[sg.Frame('Flags', flags, font='Any 12', title_color='blue')],
[sg.Frame('Loss Functions', loss_functions, font='Any 12', title_color='red')],
[sg.Frame('Loss Functions', loss_functions,
font='Any 12', title_color='red')],
[sg.Submit(), sg.Cancel()]]
window = sg.Window('Machine Learning Front End', font=("Helvetica", 12)).Layout(layout)
button, values = window.Read()
sg.SetOptions(text_justification='left')
sg.set_options(text_justification='left')
window = sg.Window('Machine Learning Front End',
layout, font=("Helvetica", 12))
button, values = window.read()
window.close()
print(button, values)
def CustomMeter():
# layout the form
layout = [[sg.Text('A custom progress meter')],
[sg.ProgressBar(1000, orientation='h', size=(20,20), key='progress')],
[sg.ProgressBar(1000, orientation='h',
size=(20, 20), key='progress')],
[sg.Cancel()]]
# create the form`
window = sg.Window('Custom Progress Meter').Layout(layout)
progress_bar = window.FindElement('progress')
window = sg.Window('Custom Progress Meter', layout)
progress_bar = window['progress']
# loop that would normally do something useful
for i in range(1000):
# check to see if the cancel button was clicked and exit loop if clicked
event, values = window.Read(timeout=0, timeout_key='timeout')
event, values = window.read(timeout=0, timeout_key='timeout')
if event == 'Cancel' or event == None:
break
# update bar with loop value +1 so that bar eventually reaches the maximum
progress_bar.UpdateBar(i+1)
progress_bar.update_bar(i+1)
# done with loop... need to destroy the window as it's still open
window.CloseNonBlocking()
if __name__ == '__main__':
CustomMeter()
MachineLearningGUI()

View file

@ -1,11 +1,12 @@
#!/usr/bin/env python
from matplotlib.ticker import NullFormatter # useful for `logit` scale
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import PySimpleGUI as sg
import matplotlib
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
"""
Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
@ -21,12 +22,7 @@ Basic steps are:
"""
#------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.ticker import NullFormatter # useful for `logit` scale
# ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
# Fixing random state for reproducibility
np.random.seed(19680801)
@ -75,9 +71,9 @@ plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25,
fig = plt.gcf() # if using Pyplot then get the figure from the plot
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
#------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
# ------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
#------------------------------- Beginning of Matplotlib helper code -----------------------
# ------------------------------- Beginning of Matplotlib helper code -----------------------
def draw_figure(canvas, figure, loc=(0, 0)):
@ -85,7 +81,8 @@ def draw_figure(canvas, figure, loc=(0, 0)):
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
#------------------------------- Beginning of GUI CODE -------------------------------
# ------------------------------- Beginning of GUI CODE -------------------------------
# define the window layout
layout = [[sg.Text('Plot test', font='Any 18')],
@ -93,9 +90,12 @@ layout = [[sg.Text('Plot test', font='Any 18')],
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
layout, finalize=True)
# add the plot to the window
fig_canvas_agg = draw_figure(window['canvas'].TKCanvas, fig)
event, values = window.read()
window.close()

View file

@ -1,10 +1,11 @@
#!/usr/bin/env python
import PySimpleGUI as sg
from random import randint
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
from matplotlib.figure import Figure
# Yet another usage of MatPlotLib with animations.
def draw_figure(canvas, figure, loc=(0, 0)):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
@ -15,19 +16,23 @@ def main():
NUM_DATAPOINTS = 10000
# define the form layout
layout = [[sg.Text('Animated Matplotlib', size=(40, 1), justification='center', font='Helvetica 20')],
layout = [[sg.Text('Animated Matplotlib', size=(40, 1),
justification='center', font='Helvetica 20')],
[sg.Canvas(size=(640, 480), key='-CANVAS-')],
[sg.Text('Progress through the data')],
[sg.Slider(range=(0, NUM_DATAPOINTS), size=(60, 10), orientation='h', key='-SLIDER-')],
[sg.Slider(range=(0, NUM_DATAPOINTS), size=(60, 10),
orientation='h', key='-SLIDER-')],
[sg.Text('Number of data points to display on screen')],
[sg.Slider(range=(10, 500), default_value=40, size=(40, 10), orientation='h', key='-SLIDER-DATAPOINTS-')],
[sg.Slider(range=(10, 500), default_value=40, size=(40, 10),
orientation='h', key='-SLIDER-DATAPOINTS-')],
[sg.Button('Exit', size=(10, 1), pad=((280, 0), 3), font='Helvetica 14')]]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
layout, finalize=True)
canvas_elem = window.FindElement('-CANVAS-')
slider_elem = window.FindElement('-SLIDER-')
canvas_elem = window['-CANVAS-']
slider_elem = window['-SLIDER-']
canvas = canvas_elem.TKCanvas
# draw the initial plot in the window
@ -41,16 +46,18 @@ def main():
dpts = [randint(0, 10) for x in range(NUM_DATAPOINTS)]
for i in range(len(dpts)):
event, values = window.Read(timeout=10)
event, values = window.read(timeout=10)
if event in ('Exit', None):
exit(69)
slider_elem.Update(i) # slider shows "progress" through the data points
slider_elem.update(i) # slider shows "progress" through the data points
ax.cla() # clear the subplot
ax.grid() # draw the grid
data_points = int(values['-SLIDER-DATAPOINTS-']) # draw this many data points (on next line)
ax.plot(range(data_points), dpts[i:i+data_points], color='purple')
fig_agg.draw()
window.close()
if __name__ == '__main__':
main()

View file

@ -1,6 +1,4 @@
#!/usr/bin/env python
import PySimpleGUI as sg
import PySimpleGUI as sg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
@ -12,9 +10,6 @@ def draw_figure(canvas, figure):
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def main():
# define the form layout
layout = [[sg.Text('Animated Matplotlib', size=(40, 1), justification='center', font='Helvetica 20')],
@ -24,7 +19,7 @@ def main():
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
canvas_elem = window.FindElement('-CANVAS-')
canvas_elem = window['-CANVAS-']
canvas = canvas_elem.TKCanvas
# draw the intitial scatter plot
fig, ax = plt.subplots()
@ -32,7 +27,7 @@ def main():
fig_agg = draw_figure(canvas, fig)
while True:
event, values = window.Read(timeout=10)
event, values = window.read(timeout=10)
if event in ('Exit', None):
exit(69)
@ -45,6 +40,7 @@ def main():
ax.scatter(x, y, c=color, s=scale, label=color, alpha=0.3, edgecolors='none')
ax.legend()
fig_agg.draw()
window.close()
if __name__ == '__main__':

View file

@ -1,8 +1,8 @@
#!/usr/bin/env python
import PySimpleGUI as sg
import matplotlib
matplotlib.use('TkAgg')
import inspect
matplotlib.use('TkAgg')
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
@ -846,17 +846,17 @@ fig_dict = {'Pyplot Simple':PyplotSimple, 'Pyplot Formatstr':PyplotFormatstr,'Py
'Pyplot Scatter With Legend' :PyplotScatterWithLegend, 'Artist Customized Box Plots' : PyplotArtistBoxPlots,
'Artist Customized Box Plots 2' : ArtistBoxplot2, 'Pyplot Histogram' : PyplotHistogram}
sg.ChangeLookAndFeel('LightGreen')
sg.change_look_and_feel('LightGreen')
figure_w, figure_h = 650, 650
# define the form layout
listbox_values = list(fig_dict)
col_listbox = [[sg.Listbox(values=listbox_values, enable_events=True, size=(28, len(listbox_values)), key='-LISTBOX-')],
[sg.T(' ' * 12), sg.Exit(size=(5, 2))]]
[sg.Text(' ' * 12), sg.Exit(size=(5, 2))]]
layout = [[sg.Text('Matplotlib Plot Test', font=('current 18'))],
[sg.Column(col_listbox, pad=(5, (3, 330))), sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-') ,
sg.Multiline(size=(70, 35), pad=(5, (3, 90)), key='-MULTILINE-')],]
[sg.Col(col_listbox, pad=(5, (3, 330))), sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-') ,
sg.MLine(size=(70, 35), pad=(5, (3, 90)), key='-MULTILINE-')],]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, grab_anywhere=False, finalize=True)
@ -872,7 +872,7 @@ while True:
delete_figure_agg(figure_agg)
choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list)
func = fig_dict[choice] # get function to call from the dictionary
window['-MULTILINE-'].Update(inspect.getsource(func)) # show source code to function in multiline
window['-MULTILINE-'].update(inspect.getsource(func)) # show source code to function in multiline
fig = func() # call function to get the figure
figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
window.close()

View file

@ -1,12 +1,12 @@
#!/usr/bin/env python
#!/usr/bin/env python
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import numpy as np
import inspect
import PySimpleGUI as sg
import matplotlib
matplotlib.use('TkAgg')
import inspect
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
"""
Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window.
@ -20,11 +20,6 @@ Basic steps are:
"""
import numpy as np
import matplotlib.pyplot as plt
def PyplotSimple():
import numpy as np
import matplotlib.pyplot as plt
@ -38,6 +33,7 @@ def PyplotSimple():
fig = plt.gcf() # get the figure to show
return fig
def PyplotHistogram():
"""
=============================================================
@ -87,6 +83,7 @@ def PyplotHistogram():
fig.tight_layout()
return fig
def PyplotArtistBoxPlots():
"""
=========================================
@ -143,6 +140,7 @@ def PyplotArtistBoxPlots():
fig.subplots_adjust(hspace=0.4)
return fig
def ArtistBoxplot2():
# fake data
@ -189,6 +187,7 @@ def ArtistBoxplot2():
fig.subplots_adjust(hspace=0.4)
return fig
def PyplotScatterWithLegend():
import matplotlib.pyplot as plt
from numpy.random import rand
@ -205,6 +204,7 @@ def PyplotScatterWithLegend():
ax.grid(True)
return fig
def PyplotLineStyles():
"""
==========
@ -258,6 +258,7 @@ def PyplotLineStyles():
plt.tight_layout()
return plt.gcf()
def PyplotLinePolyCollection():
import matplotlib.pyplot as plt
from matplotlib import collections, colors, transforms
@ -361,6 +362,7 @@ def PyplotLinePolyCollection():
ax4.set_ylim(ax4.get_ylim()[::-1])
return fig
def PyplotGGPlotSytleSheet():
import numpy as np
import matplotlib.pyplot as plt
@ -405,6 +407,7 @@ def PyplotGGPlotSytleSheet():
fig = plt.gcf() # get the figure to show
return fig
def PyplotBoxPlot():
import numpy as np
import matplotlib.pyplot as plt
@ -423,6 +426,7 @@ def PyplotBoxPlot():
ax1.boxplot(data)
return fig1
def PyplotRadarChart():
import numpy as np
@ -609,6 +613,7 @@ def PyplotRadarChart():
size='large')
return fig
def DifferentScales():
import numpy as np
import matplotlib.pyplot as plt
@ -629,13 +634,15 @@ def DifferentScales():
ax2 = ax1.twinx() # instantiate a second axes that shares the same x-axis
color = 'tab:blue'
ax2.set_ylabel('sin', color=color) # we already handled the x-label with ax1
# we already handled the x-label with ax1
ax2.set_ylabel('sin', color=color)
ax2.plot(t, data2, color=color)
ax2.tick_params(axis='y', labelcolor=color)
fig.tight_layout() # otherwise the right y-label is slightly clipped
return fig
def ExploringNormalizations():
import matplotlib.pyplot as plt
import matplotlib.colors as mcolors
@ -662,6 +669,7 @@ def ExploringNormalizations():
fig.tight_layout()
return fig
def PyplotFormatstr():
def f(t):
@ -679,6 +687,7 @@ def PyplotFormatstr():
fig = plt.gcf() # get the figure to show
return fig
def UnicodeMinus():
import numpy as np
import matplotlib
@ -693,6 +702,7 @@ def UnicodeMinus():
ax.set_title('Using hyphen instead of Unicode minus')
return fig
def Subplot3d():
from mpl_toolkits.mplot3d.axes3d import Axes3D
from matplotlib import cm
@ -723,6 +733,7 @@ def Subplot3d():
ax.plot_wireframe(X, Y, Z, rstride=10, cstride=10)
return fig
def PyplotScales():
import numpy as np
import matplotlib.pyplot as plt
@ -823,12 +834,15 @@ def AxesGrid():
return plt.gcf()
# The magic function that makes it possible.... glues together tkinter and pyplot using Canvas Widget
def draw_figure(canvas, figure):
figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
figure_canvas_agg.draw()
figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
return figure_canvas_agg
def delete_figure_agg(figure_agg):
figure_agg.get_tk_widget().forget()
plt.close('all')
@ -842,48 +856,52 @@ def delete_figure_agg(figure_agg):
# print(inspect.getsource(PyplotSimple))
fig_dict = {'Pyplot Simple':PyplotSimple, 'Pyplot Formatstr':PyplotFormatstr,'PyPlot Three':Subplot3d,
'Unicode Minus': UnicodeMinus, 'Pyplot Scales' : PyplotScales, 'Axes Grid' : AxesGrid,
'Exploring Normalizations' : ExploringNormalizations, 'Different Scales' : DifferentScales,
'Pyplot Box Plot' : PyplotBoxPlot, 'Pyplot ggplot Style Sheet' : PyplotGGPlotSytleSheet,
'Pyplot Line Poly Collection' : PyplotLinePolyCollection, 'Pyplot Line Styles' : PyplotLineStyles,
'Pyplot Scatter With Legend' :PyplotScatterWithLegend, 'Artist Customized Box Plots' : PyplotArtistBoxPlots,
'Artist Customized Box Plots 2' : ArtistBoxplot2, 'Pyplot Histogram' : PyplotHistogram}
fig_dict = {'Pyplot Simple': PyplotSimple, 'Pyplot Formatstr': PyplotFormatstr, 'PyPlot Three': Subplot3d,
'Unicode Minus': UnicodeMinus, 'Pyplot Scales': PyplotScales, 'Axes Grid': AxesGrid,
'Exploring Normalizations': ExploringNormalizations, 'Different Scales': DifferentScales,
'Pyplot Box Plot': PyplotBoxPlot, 'Pyplot ggplot Style Sheet': PyplotGGPlotSytleSheet,
'Pyplot Line Poly Collection': PyplotLinePolyCollection, 'Pyplot Line Styles': PyplotLineStyles,
'Pyplot Scatter With Legend': PyplotScatterWithLegend, 'Artist Customized Box Plots': PyplotArtistBoxPlots,
'Artist Customized Box Plots 2': ArtistBoxplot2, 'Pyplot Histogram': PyplotHistogram}
sg.ChangeLookAndFeel('LightGreen')
sg.change_look_and_feel('LightGreen')
figure_w, figure_h = 650, 650
# define the form layout
listbox_values = list(fig_dict)
col_listbox = [[sg.Listbox(values=listbox_values, change_submits=True, size=(28, len(listbox_values)), key='-LISTBOX-')],
[sg.T(' ' * 12), sg.Exit(size=(5, 2))]]
[sg.Text(' ' * 12), sg.Exit(size=(5, 2))]]
col_multiline = sg.Column([[sg.Multiline(size=(70, 35), key='-MULTILINE-')]])
col_canvas = sg.Column([[ sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-')]])
col_instructions = sg.Column([[sg.Pane([col_canvas, col_multiline], size=(800,600))],
[sg.Text('Grab square above and slide upwards to view source code for graph')]])
col_multiline = sg.Col([[sg.MLine(size=(70, 35), key='-MULTILINE-')]])
col_canvas = sg.Col([[sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-')]])
col_instructions = sg.Col([[sg.Pane([col_canvas, col_multiline], size=(800, 600))],
[sg.Text('Grab square above and slide upwards to view source code for graph')]])
layout = [[sg.Text('Matplotlib Plot Test', font=('ANY 18'))],
[sg.Column(col_listbox), col_instructions],]
[sg.Col(col_listbox), col_instructions], ]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',layout, resizable=True, finalize=True)
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI',
layout, resizable=True, finalize=True)
canvas_elem = window.FindElement('-CANVAS-')
multiline_elem= window.FindElement('-MULTILINE-')
canvas_elem = window['-CANVAS-']
multiline_elem = window['-MULTILINE-']
figure_agg = None
while True:
event, values = window.Read()
event, values = window.read()
if event in (None, 'Exit'):
break
if figure_agg:
# ** IMPORTANT ** Clean up previous drawing before drawing again
delete_figure_agg(figure_agg)
choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list)
func = fig_dict[choice] # get function to call from the dictionary
window['-MULTILINE-'].Update(inspect.getsource(func)) # show source code to function in multiline
# get first listbox item chosen (returned as a list)
choice = values['-LISTBOX-'][0]
# get function to call from the dictionary
func = fig_dict[choice]
# show source code to function in multiline
window['-MULTILINE-'].update(inspect.getsource(func))
fig = func() # call function to get the figure
figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure
figure_agg = draw_figure(
window['-CANVAS-'].TKCanvas, fig) # draw the figure

View file

@ -1,15 +1,10 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasAgg
import matplotlib.backends.tkagg as tkagg
import matplotlib.pyplot as plt
import PySimpleGUI as sg
import tkinter as tk
"""
A graph of time to ping Google.com
Demonstrates Matploylib used in an animated way.
@ -646,12 +641,15 @@ def main():
global g_my_globals
# define the form layout
layout = [[ sg.Canvas(size=SIZE, background_color='white',key='canvas') , sg.Button('Exit', pad=(0, (210, 0)))]]
layout = [
[ sg.Canvas(size=SIZE, background_color='white',key='canvas'),
sg.Button('Exit', pad=(0, (210, 0)))]
]
# create the form and show it without the plot
window = sg.Window('Ping Graph', background_color='white', grab_anywhere=True).Layout(layout).Finalize()
window = sg.Window('Ping Graph', layout, background_color='white', grab_anywhere=True, finalize=True)
canvas_elem = window.FindElement('canvas')
canvas_elem = window['canvas']
canvas = canvas_elem.TKCanvas
fig = plt.figure(figsize=(3.1, 2.25), tight_layout={'pad':0})
@ -662,13 +660,14 @@ def main():
plt.tight_layout()
while True:
event, values = window.Read(timeout=0)
event, values = window.read(timeout=0)
if event in ('Exit', None):
exit(0)
break
run_a_ping_and_graph()
photo = draw(fig, canvas)
window.close()
if __name__ == '__main__':
main()

View file

@ -1,35 +1,37 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import matplotlib.pyplot as plt
import ping
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, FigureCanvasAgg
import matplotlib.backends.tkagg as tkagg
import matplotlib.pyplot as plt
import PySimpleGUI as sg
import tkinter as tk
import ping
#================================================================================
# ================================================================================
# 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
# graphs are global so that can be retained across multiple calls to this callback
global g_my_globals
#===================== Do the ping =====================#
response = ping.quiet_ping('google.com',timeout=1000)
response = ping.quiet_ping('google.com', timeout=1000)
if response[0] == 0:
ping_time = 1000
else:
@ -46,21 +48,26 @@ def run_a_ping_and_graph():
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
# clear before graphing
g_my_globals.axis_ping.clear()
# graph the ping values
g_my_globals.axis_ping.plot(x_array, y_array)
#================================================================================
# ================================================================================
# 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)
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
@ -73,30 +80,34 @@ def draw(fig, canvas):
tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2)
return photo
#================================================================================
# ================================================================================
# Function: MAIN
#================================================================================
# ================================================================================
def main():
global g_my_globals
# define the form layout
layout = [[sg.Text('Animated Ping', size=(40, 1), justification='center', font='Helvetica 20')],
layout = [[sg.Text('Animated Ping', size=(40, 1),
justification='center', font='Helvetica 20')],
[sg.Canvas(size=(640, 480), key='canvas')],
[sg.Button('Exit', size=(10, 2), pad=((280, 0), 3), font='Helvetica 14')]]
# create the form and show it without the plot
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
window = sg.Window(
'Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True)
canvas_elem = window.FindElement('canvas')
canvas_elem = window['canvas']
canvas = canvas_elem.TKCanvas
fig = plt.figure()
g_my_globals.axis_ping = fig.add_subplot(1,1,1)
g_my_globals.axis_ping = fig.add_subplot(1, 1, 1)
set_chart_labels()
plt.tight_layout()
while True:
event, values = window.Read(timeout=0)
event, values = window.read(timeout=0)
if event in ('Exit', None):
break

View file

@ -1,10 +1,5 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
# import PySimpleGUIQt as sg # portable to QT
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
#
# An Async Demonstration of a media player
@ -12,42 +7,39 @@ else:
# See how it looks here:
# https://user-images.githubusercontent.com/13696193/43159403-45c9726e-8f50-11e8-9da0-0d272e20c579.jpg
#
def MediaPlayerGUI():
background = '#F0F0F0'
# Set the backgrounds the same as the background on the buttons
sg.SetOptions(background_color=background, element_background_color=background)
# Images are located in a subfolder in the Demo Media Player.py folder
image_pause = './ButtonGraphics/Pause.png'
image_restart = './ButtonGraphics/Restart.png'
image_next = './ButtonGraphics/Next.png'
image_exit = './ButtonGraphics/Exit.png'
sg.set_options(background_color=background,
element_background_color=background)
# A text element that will be changed to display messages in the GUI
ImageButton = lambda image_filename, key:sg.Button('', button_color=(background,background), image_filename=image_filename, image_size=(50, 50), image_subsample=2, border_width=0, key=key)
def ImageButton(title, key):
return sg.Button(title, button_color=(background, background),
border_width=0, key=key)
# define layout of the rows
layout= [[sg.Text('Media File Player', font=("Helvetica", 25))],
[sg.Text('', size=(15, 2), font=("Helvetica", 14), key='output')],
[ImageButton(image_restart, key='Restart Song'), sg.Text(' ' * 2),
ImageButton(image_pause, key='Pause'),
sg.Text(' ' * 2),
ImageButton(image_next, key='Next'),
sg.Text(' ' * 2),
sg.Text(' ' * 2),ImageButton(image_exit, key='Exit')],
]
layout = [[sg.Text('Media File Player', font=("Helvetica", 25))],
[sg.Text('', size=(15, 2), font=("Helvetica", 14), key='output')],
[ImageButton('restart', key='Restart Song'), sg.Text(' ' * 2),
ImageButton('pause', key='Pause'), sg.Text(' ' * 2),
ImageButton('next', key='Next'), sg.Text(' ' * 2),
sg.Text(' ' * 2), ImageButton('exit', key='Exit')],
]
# Open a form, note that context manager can't be used generally speaking for async forms
window = sg.Window('Media File Player', auto_size_text=True, default_element_size=(20, 1),
font=("Helvetica", 25)).Layout(layout)
# Our event loop
while(True):
event, values = window.Read(timeout=100) # Poll every 100 ms
window = sg.Window('Media File Player', layout,
default_element_size=(20, 1),
font=("Helvetica", 25))
while True:
event, values = window.read(timeout=100)
if event == 'Exit' or event is None:
break
# If a button was pressed, display it on the GUI by updating the text element
if event != sg.TIMEOUT_KEY:
window.FindElement('output').Update(event)
window['output'].update(event)
window.close()
MediaPlayerGUI()

View file

@ -1,82 +1,73 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
# Usage of icons as base64 string and toolbar
house64 = 'data:image/png;base64,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'
timer64 = 'data:image/png;base64,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'
close64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAE30lEQVRIiZ2VXYgdRRqGn6+quvucM/85iRoTNevMBJFEWY0GFQTBC1HBlaz/jMpoFFfXBdmFvdiLvRIEFRHFGBXMjUQhF/6Bol6sSNaIruCNir/R/Dlx5iRzck736e6qby/6JDlx9CIWFN10Ue/7vW+9X7XcDn8bryWPL2vERkNQQPj9Q72K7F3s7Hxb9bZ98L0bj91jt1y23kxNTxIEGUQ/aTYR6WW9cud/Prx01zf7/7FP5EHXHG7Y6bVTpBPLMSegCWKEEMKvkihgjEWDP+FbEjxTa1bjv9l/CsIKF3ypHhUDSFGACCKC956iKKjV6/hfkCjgUNK0TW1oCA3h+EJk8UUBYFCsQaSyRajArUWLnEONcTrT68nTLtZaEKmmMTiUlsREGy9HO0dgcL1y6lgtZrAsEYFexhwxq2buYfru+1mcOo+828UYg4rgUH7OSkY3zbDq1lkaV1yFP9TqEyy18jiBCMF7DjYmOOu+hxifnCSKItZuvp/F6fPJ05TEwE+dHhN33MfpGy4iFAVjf7qF8etvBV9y1IilBApGIMt6TExOM372JKqKqhLFMdOz93Jk6jx+bHVoztzLyj9eiHqP2Gq7O3UlGAuq1RwYDlUwhoChMdSAz3ZxaEeD8T/fBggaAnGtxpqZWdKFBSbOPLMCCQGJItJPdrHw4lOYRgNsBM6dSCDGErIuodtGkhoyPEr68U5svcbI1ZsQY0CV2vAw9ZGRKjEiSBTR/fQjDm9/AddcjqoSul182kYHVDhJauRffUH7wD7ilatxzVOwI6PM7XiJLO2x4rob0CgGVTSEKigidD94j/ltW9Dg0b0/4BfmyQ8ewKUdWLZ6wCIB9SXFXJvQ+hLkc6QeEznHf199jY1rpjh1w0ZUFTGm7z18/tSj2Hffor5shKLdhhJCADMcw7IlKRIkAqkJRIa4LPl6d5c/PPJkBd5vpArcArD+ue101l1Md08bFxuIBUlOyOUggUIAVIl94Kv5wKqtz7L+7r/0bRHEmApcFbwnHhljw6tv0b3kEtK5gDWmj/GbfQAWZbdaztjyPOfP3oN6D8GDCO133uDAvx9CyxKsRX1JMjbBBa+8Rnbl5RSpR35RfXUGfVLnYGFBcTfdwLo77yLkPYy14CLa773JngfuoNy7QOh2WPnw09WVkufUm8s598G/s+eT9wmBJZ1m+sVTFNBc4Wi8vJ3v//kAJk7AOhbf3MGezTfjWwuYCcv8s1s58K+/okWOxDGdjz5g7+YZtKRSoL+igCp5FKVntGk48sTTzDWb1C+4mB833wgETD2CELBjEfNbtyAjo4xdcz27N11L6B5GGoZQhN+26KiSoII9LebnJx9BkggzNIQkyfEdItiRQGvbM7S2bQHJMGN1NO8ds2dQhBORYBCjAFEE1kFSw0QxuAiTJCAGce64vz4gviTkOTJcErIMMRbyDIxg7bHTFnc47clcmpdj43VkeBRJEkytgdTqSL2OiRMkSRDroH9t4EtCUaBZhmYpIUurZ9pFfVnuX+w62xfjeq3D3/6vbifXrT1XkzgWdREmipA4RlwMUYRY21cg/X+lJ5gSbIHGOVovCHmOCSX7DrbMx599icIhVI2cA5c5mC1gbGnITm4oqAOr0PoOXs9g51HAGiITyCDByXDp4KuiaoESmP8/YC0Y5GajmEsAAAAASUVORK5CYII='
psg64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABlbkiVhkyZikyFjmShjkyhlly1mli5nlylnmS5olyppnC5qmi5rmzBpmDBpmTFqmDFqmTFqmjNrmzFrnDNsmzJsnDJtnTFunjNvnzRsmTRtmzVunTVunjVvnzZwnjlxny5toDFvozJwoTNzpjVwoDRzpDRzqDd4rThyojp0ozl1pTt2pjt3pz11ozt4qDl4qTp6rTl6rzx4qD55qTx5qj97qz17rT58rD98rT9+rz5+sEB3pEF9rkB+r0F+sEF/sT2AtD6AtT6Btk+Aqk2CrEOBs0GBtEKCtEGCtUSBskWBs0SCtEWDtUaEtkWFt0aGt0KFuUCEukOGu0eFuEWHu0eJvEiGuUiHukiIuUiIukmJu0uKvEyKvFCAp1CCqlODrVKCrl2Kr1OEs1KGsFWGsFaIsVaPvFqKsl6NsmKNsWeTuG6YvHadvlySwV6UxF+YxW+bxW6dxnKewHGex3SdwHSfx3egwXGizHmgwHqkxnyjxHio0f/RMf7QMv/TMf/SMv3SNf7UOv7UO//UPP/UPf/UPv/VP//WPP/XPv/VQ//WQv7XQ//WRP/XRf/WR//YRv/YSP/YSf/YSv/ZS//aS//ZTf/aTP7aTf7aTv7bT//cT//bUP/cUP7cUv/cU/7cVf/eVf/fVv/eV/7dWP/eWP/eWf/fWv/fW//fYvzcaf/hW//gXP/gXv/gX//hYP/hYf/hY//iYP/jY//gZf/iZP7iZf/jZv/iZ//lZv/jaf/kav7ka//maf/ma//kbf/lbv7mbP/mbv/mb//id//mcP/ncv/nc//ld//ndv/meP/ocf/ocv/oc//odP/odf/odv/peP/pff/qfY+11ZSzz5G41qC81aW/1P/jgf/qiv/qjv7qoMnZ5szb587d6eDm2+fo1+7v3e/x3vXw1fHx3gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJblQd8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAABcQAAAXEAEYYRHbAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAABzUlEQVQoU2P4jwNAJZIEuLJA9M2u/iNgAaiEELOgIFPc//+r6puaalvAQmAJdg4pPj4h5oT/2+raWtqaGmAS/PxC/IJAGdbEB7saW5pb20AyQAkFNiFhUSEgkGZNfjizua29u70XJJHr8j+eV0RGVkRMTJb56u2mvt7eSR0gCT2gPsbMGzbi8hJyPDl3OidPnDRlwhagRHbG/zTXe5WSqqqqmpzXb/VMmz5jztSVIDtSWFLvl3Jrampq8ZY8WThj1tx586ZCXFV9t1xRR1tbR6Lw0f6ZC+YvWDAb6tz/xUom+rrGymWPD8xaunjZ0oUgMZBEsYqZqampWsnTY/PWLF+xZhFIHCRRpW5raWFhUPT/3IJ1a9euW/H//5oTYAlDezs7Kwvv//+XbN6wcev6//+3/z8FltDwcrC3N8/7v3rHtu07Nv3/vxVo0CWQhJGPm5ubdf7/TXt279699//JnTA70j38fH19wv//33b00OGj+w6fPXz5KMRVTiH+/gHuFf//7zl+5szZs2fO7YPo+H/FOSIyPMqz5v//g+dAMocvQCX+XwsMjYmNdgSy9p0/d/bgRZAYWOL//4LgoDAwY+++02AaJoEJcEj8/w8A4UqG4COjF7gAAAAASUVORK5CYII='
cpu64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAFi0lEQVRIiZ1WS2wbRRj+/5l92O6u7WycTW03xLEd6uBUjVO1hfbSByLQEwhxoIhbCwcuvApUiEOFhAQVEiAOvK4gqoojSEhtgUNApaJKG5qkdWpa1JfcZL3teu3sZmeGQ9ZVGhIJ8Z/+2Vn93//45psBWMMqlcoXxWLxEACAaZpju3btOkkIoZRSsnv37hOmaY4BABSLxUOVSuXzteJIq32klMqyLBuqqhoAAKqqGpTSpKIoSUQESZK6OnuKohiKohiUUpkxtvivWCvWBABEOp1+sr+//5V169ZtnJub+6FUKh3Rdf3hVqv1l6Zp5Ww2ezASifQ0Go3fhoaGjsZisYdardaM4zjTiEgAQHQC4j0HkQghAAC4oiiJRCKxBQBIs9m8oOt6iRASa7VaVwEAYrFYP+e85TjOpXg8PiyE4LZtn/F93wYAgogghOD3AYS+UFW1q1AovGoYxp4wGxIEgS2EEIQQCQCAcx7gkslCCB8AwLbt07Va7SPP8xqdWPdmIElSxDTNfZZlncrn828MDg6+VavVPvF9fy4Wi/X19fUdWJHMfSaEYJlMZgwRpVqtdtQwjD31ev2HIAgWpJGRkS8VRTEMw9g9OTm5v7u7+9GpqamXq9XqxwAAmzZt+oBzjpzzYC0QIQRDRJpIJLanUqmdw8PDX1mW9ZPv+5bkOM5FVVVTiURia1i24rruDQCAUqn09sDAwCHGGEdEadnwlgOJZT5BRMIYc5rN5iXP8+ax0y9N04qc84Vt27aduHjx4uuEED46Ovo95xxEOH1ExKWEhQh9DPe4JEl0fn7+14mJiecQUWo2m7MAgNQ0zb3d3d3bhoaGjrTb7Wld1x/p6uoa2bBhw4uyLGsAEFBKKSIi51xQSjFcIiICIQRDAhDXdWue502Vy+X3hRALqqr2SoODg2/KsmzE4/GNlNJ1nPOF9evXPxYEAbiue7lWq72rKIphmub+GzdufBeNRg1d14cZYx4hhBJClFQqNRbOQlBKo8lkcms+n48vLi5a0vj4+OOKoiTT6fQzjuNcJYRIQRCALMswOzv7LSEk0tPT85TjOBeCIKi12+1rtm3/ruv6FgDgAMB7e3vHgiAAQgh1HOfquXPnXr958+Zx3/dtshopltp7nyEiUtd1rxuG8URfX99B13Un2+32rKIo3ZzztRgMdOfOnT/mcrkX+vv79zcajVOapm3XNC3HGINoNNpnWdZJz/P+TiQSOzRNK6bT6WcjkUh/q9WaQUTIZrMHEFEjhECz2fzL9/2ZkZGRz0zT3JfNZp+WqtXq+5FIJJXL5V5kjLVDdgDnnMVisYFyufxVSFHgnO9gjDFElIvF4jth34ExxgCAIiIyxtq2bZ+5cuXK5wsLC3NSvV4/BQDCsqw/hBBBLpeTO+WF/KdhC0TIHAoAIggCjogYMnjpEBAi27Z96ezZsy90aCoVCoXXVFVNZbPZ/TMzMy9xzr1ljSdhYLHicN0DCkFYWKFnGMamUqn06fXr17/xPG9e0nV9Y6jnWqiAPCydrTm5laxY+pcCABdCcEqprmnag4qiWNLExMTBZWI3Ho/Hd2Qymb1CCBpm+V8AQJZluHPnzum5ubnx8+fPH+iI3apync/nX04mk9vDXihCiMX/K9drXTjJZDK5FRHJ3bt3/9R1/cH/e+Esb0FnkKK3t3ff5s2bv+7p6Rm7devWsXK5/GGhUDjsOM5kNBp9oFKpfKNp2kC9Xv9xdHT0eCaTed513fPhlYmd4CsBOiDQarVmu7q6KpZl/XLt2rVjQggvHo8PTE9PH242m1PpdPrRy5cvf3L79u2fo9GoyRi7U61W3wsDL5fv1V8VjLFF3/ct3/ctAADP86wgCBq+7zcAABljtud5FgCA7/uWLMvWai8KAIB/ACsf4Gh+DNwbAAAAAElFTkSuQmCC'
camera64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAF4ElEQVRIiaWVS2xcVxnHf+fc58ydh2fGnthO7Dixa6etQtQKaChKqUCVCqFSN92yQEKqVFGExKZSJcQCZcWSTReIFXQDCKkIVEAqURVQCImdtLVJmiaxM+PXjOc99965557DYkwSVJAqcY7O5nv99T/6f98n+Kznwo3ngDeBFWD+gd2whuDrvHF6+7+l2Z8ZIDW/zbjWxPe+WOb8Yp52pPnp1SZ/WO+ewZO/Ac7+XwC+awU/Olfl22cmqGTGaVOBjRCC36+2nvlfeYILN5ZJzR+fms3ML5dcImU+HaUMx8quev3zFXsqYzFKDUIILAHvbQ146+9NtkLFZlcxiFKAHSzxHd44/Y7gwo29Y3ln6s1nJzl/Mk87TsdFH8URgiQ1tKKURD90SAFZR5IauLIz5OpOzOV6yL1OzCglQXLeBsovLxepBh6rjQRlDAIwBsQjGA/LCkAghAEDw3jsXS5n+cJsnienBvzyozYf7g1tjfixDUKUAhfhOHRHGsTD4kYYHsCYMRMBYARGHBoPg402tLopC6UMXzuhOYiUqPWTeZtGJH/2bo23HUmSaowxaGMwevyEZSEtMEahVESaJqg0QZsUKS1s4eC5rjpSzo/OPj6TOTWbE6V8hsVSloOwZ9sME2rDIVgCXAfPd/F9Fy/j4Gd8wiim1WhCMmC+5DI3nWO2nCHrWvRCxVZzyGZzaH24uevebw7155Zm5BMnyuJYJce1nUFgozUyq/EyFkHgUCxmKRZy5PMBtitp7TdYCFyerBb50mOTHK8UOFrxCDzohrDVHLJR74iLG7v2pY0Dc+n6phnEmsJUTiCFtFEpaIHRAq0hVYYkSYnjhP3dFtlRh3MnJnjhzHGCwGV/YFjdUShtsKWk6Gd5ZiXLyekCxyo18c7lOmsb9/VEuyK1NMImScBYCAHSgEBgDMRRiBn0OLtU5htPz5FKh19ca3G5NqDWSYhVim9bLFZ8nl8IeHE5z4un5+jHWrx7dUfubO1ru1KQNumYwaE4xnI0mngQslTx+crKFLbj8Ku1Jr9b26G/t0vY65MmCbHrsD5RotOZRqA5f2qCc49N8sl2n96dgUm6obYZKTAWCDlWuACDQcUjVhYnWKoGfNCIeW9jj+7uPvNZw5mlaaZyLlutkGu1AbWtXf7sWzy3kOfUdIGVuYJYr4dWchBKySgBYxjfsbQFgB6xXA2YLVjsdSI+rnexdcJCtcBctcj0ZIGF6QnmygFJFPHPWodeOOJE2eXkVB5HGpF2htJmNAITfKpjPVswmXUpWJDEMckgwi5kiaXH7XaK3U1RGpTrI72Ubm+IVoqSC5XAxRGg+xH2vxmIwy9CCIQQZD0fNZ4GeCikUBi/yN2BxI00UkBqIFQWTjaL0+3iCYMyoAHPcRCJujlmoFMwGmM0JlVobeN4LvuDEX0Fk77FkbxFbAxtbSMeTClBqlMskbBQsCh6klYIrWGCLYSxBf+QKI1IYtJ4QNTt0Nnbp7G9Tb8/pNaO6UaaJ6ZzPDuXp9/cR+sUy/dxggLS8xjFEUnngK8ul5gtOjSHCfVmSNweKmHSS4d9YEBIkBJpW1jSJjEWdzsj1uo9vjyf5/svLIJWXLx1j/pGCCMNnsXCdMA3n57h1eeXsG2LD3ZD7tR6tG83Wkl78GubUdLHdXPC87AMOJ6Pm3HRlsv20HClFlINXE7NFPnhS4+zXmuz140YqRTfsThWDjh1tMREwWe1lXDl1gG3rtWS3t3GK+bGa3UbpUK9dZAVOV861RJexiOTy+BnPRLf4ZPU5i97isiyeGqmyOmjxf9cdkAtgvdrA/56q8WlP91M7l+99630xmsXAWxS/ZJZr/9cWdZygpQjy0JmfUzGIbFdhhIanuFuxWXtSMDxis/RskfgWnQjxeZBzN1GxM16T6/+7U5//f2PXx1d/+7bj64nWP7JCsa8heFhQ4jDpkg1Xs5jZrHK/Mo01fkKlaNF/KzLsBfR3O7QrHdU4/7B1u3VrR9E11+/9yjDfwGSndm1qwVxegAAAABJRU5ErkJggg=='
checkmark64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAD2ElEQVRIibWVe4hUVRzHP+feuTOz82gfrqwu5gM0zTQpS1yfoGQPyc3IjOwlYRElPcDICEP6Q6i/IvojCCIpTA0tSlSqJSvbTLZE0dbWxz4nXWdnxrk7M/feOY/+sHyEa7pt57/z45zP53x/B84R/B/jzeNLgeXADDHE4IeBV2Ihpo6LK1rzNqEhAW9oGw18UhelYeWUGHFL0tx5lqPZyBAI3mi9o8YRm16cWTlsVFLQVwjY2+4SSI2W+j8KXj+ybmwytO69xjo7Wyqzr8sldbaE60ksIdBlhTVo+KuHXppY5azftKzeNsbQkurntOuTKQQobYhFbCgPNsGaA5NDWm94ZlYV7fmAX3pcenIlTucDAqlJRENUxcJQLgwiwfMtYcpq4503JMJjq8M0d+XpyBRJnfUpBpJwyKYqFqbCcSCQg0gQyCeq4qHp90yr5Pd0kY6+ImnXJ1CaeDhEdSJCTSJKzLEHLXhu4oQEuWKZ79uzZAoX2hKPhOn+I6DtuEdfLriC4NE9L4CYhzEP8dH84Hz9kT0NBHLqvMlJmo5nyBQDylITj4RwM5rmw70orcEA0AL8Q/DgN8OBr/DltL8q64G1F52+obomwr6US7boE0hNhRPiVIdHx7H+EvA2sJ0tC3/+e8uFS27c/SS+7ElGrGkbnp5EfV0UArmGxt0Lzq/x5YzKWocz/T4FXyGEINvj0XE410QgJ7Fl4dqL4ecS3PVlJYgdllKzx04ZxqolY8h4mkm315JPl+z+nP8Bd++4hZ2LM/hyuokLCr7Eti28TJnOA5ndGLOUnYtLl+u2YMHnJ4BxY2bWsWj2SA72eoBBG4PnBvy2qwvpq81gVjhJp1Q7q9axLIFVMqSaz3ytfLWEpsbLwgFs6pc1o/R9+e7+eK9joSMWvjR4gSLA4FSGKLS7UyirUmRkbJFTG0VI6N17+oR0/bl8d/+A8HMJAG7bPB7BTmGL8TVz64mMiKGNQSuN0hqvq59CS59Kzq2zo8MrcH/s1V6qMIf9y5uvBL8gALj54xpgG5aYH589klB9BdoYjDY0XJ9k9HURPj2aRZ/ycL/tfouDK17+N/ilAoAbP6wAsRGLB8INI7BGJUAYLGEhLAtLCApfnDymc95NtD4eDMC8ZNiXzNKfSdLbt5K8N6o68nNMwoHqKCAwlkVwKI06ln2MtpWtVwMHBnjspHyNQO1Xe7pRbTmUEchCGbk/laKsdl0tfGBB51OKQM0hUD/ppk7kkTTy11NQku/TuUpdi+DKn/7wdyuAHzDcii0Uykwg/ezJoRMAVL9TCWwFjpJdvfpa4AB/Akx4zQw8GDagAAAAAElFTkSuQmCC'
cookbook64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAIAAAB1KUohAAAACXBIWXMAAAsSAAALEgHS3X78AAADMUlEQVQ4jY1UQUgCWxS9782M5hQzle3NTRGEQdBipCKKECoEg4JaJAqCmyBsYauEaNOqjQtXLSKINuFiKMiwIMtF1iLK2kWRZLUoDRxo5s37ixfSt4+/u7xzz51z7r3nwc7Ojt1uBwCEEPwtWKXL5eIvLy+HhoYIIYIgCIJAKa0Do5RyHPfy8nJycnJ1dcUjhJxOZygUOj09zefzFoulDp5SihCKRqPLy8vJZBI4jgOAo6Mjj8cDABjj/6WdTqdDoRAAfJeyFn8MQohhGADAY4xFUSyVSpIkAYBpmgih+soRQmxm2GazbW5u7u7ujoyMKIrCmP+ePMdxv9nhSqXi8/lmZmb29vay2Syrs1gs8EM/QogQQgipBWOMOzs7397eWlpabDYbAMiyHAwGu7u7mQTWzu/3R6PRxsZG+HERvNVqjcVix8fHfX19Nzc3T09PHo+HUjo1NVUulx8fHwFgbW0tEolQSguFwtbWVpU/rlQqs7Ozc3NzqqrmcjmXy9Xe3m61WgcGBubn5wGgo6NjYWEBAEql0t3dHQBUx8ljjNva2orFYnNzM8/zBwcHFoslGo329/cXCgUA6OnpwRh/fHwsLS3lcjm2qm9wQ0NDPB7f398fHBx8eHjIZrOqqhaLRUmSwuFwPB53OBw+ny+dTn9+ftYujed5AEilUhMTE9U9saTX66WUJhKJmv0dHh4Gg0FgF4YxJoQwANNjGIaiKLFYbHp62ul0Li4umqb5H5crSVIymQwEAolEwu12s6SiKNfX15OTkwDgcDguLi4ikUgVUv0zCIJgs9lUVWWlrP3q6qrf72dfAaCrq2tjY0OW5RowTynVNM1qteq6XqW9srJiGAZCSNd1hNDt7W04HGZm+NeFiaKYTCa3t7fHx8fdbjez+9fXV7UR87Cu66Zp1oI1TQsEAl6vN51Os9smhCCEfpbWmMw0TZbBpmm+v7+3traWy2VKKdP825I/M7Isi6IIAFxTU9P6+nomk+nt7X19fX1+fsYY1/ez0+k8Pz+/v7/nMMblcnl4eDifz5+dnWmaVgfGolQq2e32sbGx7wcok8mMjo7C396wVCpFKSWE/ANWXYLwO0+V8wAAAABJRU5ErkJggg=='
download64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAEl0lEQVRIia2WS2hdZRDHf/Odc+7NvbZpYky1Gk2rEbRa26pt8UWLitYHIqigCD426kIQxCfWhYu68U0RBBERXCq+WrXoorYIFWpbEY0lpk0NTWKtuUlzn+d834yLm5smqQspzurMcM785j+c+eYTTtUcESAzvhIAm/+azHacA4FodszAVNFTrUPm+Q6iecmUyJkEna5OiDCCXCtvJ2cnV+Ep+9R7/VIfQhmeryKeySywok+SSMMKMwqAihDXPIcPDDMURUQCgiPWjJCck6x87ZXXV3cXu3XTO5tkYOvAHbnIfZipTpghLdAMIEngi1cXvtlzwfrHpG0x5ismzsvo0E9D9z7z++M799s2EcSm67OUkAs5cpbzkkoMtPtAAzdXQ9zqjHkt1Ol5SHofx0KWYRUxrdiS3FlLtzz51wd7+v2OQl7qHnPtorUXS3ZxPRUKUT5x4mTDWu559LbCNS+9X9v025Duc4KoYdMAA7A4Mk92EMp/JFIZwR/rx9dL1teVdC2/Qe8yzQg+pS0JvLUzx3hjioPVQamGGlcu47KNq6qrPj+fsd+GeAEYA2SmRQiCNSJKP1Ad3IVaG0nnlWRxKqkkVlYxJxGZwhmFIo34U/fh0Hv4v6YYrY+ihYtkorDUNj+298GPvzv6ZRrkMzA/oyCXh9rEMOOHfiLfcx+5zhXkOnppswxEpJHVxdTjs0CycDHy9XcMlwc5a0E3EoTconOls/dyBsb6lYRLY4m/9T6blDgi8oHw3rPx83fesubl4oVPWFvXBUKoQzqB92Xitpite77n/k/epaN7AZO1CTIROtZ14fJC6ccS9ndGUhRLK0Eum1h2YGpH5eFfD47sjluzcFo+f+vp655F03alNhZhASMjloA1qtzedzab125kiw2QLhHaQ0zIFM2MztUdkBcqx1Lp+0o59NGRP49OVQs0Z3d6nEyMUMP8OGgVtAJaA19CagP4xn4e6DPuPhox1V9HTRFr/h9mRmWkwbJtGSsHK4xXq4cQGQDCDABM0ClEy6DlJiA9DLV90BgktirFzhrPXX0mT6Y9lAaqkAhRItRKGT3bjetTYd2aYM7JYcwm5wwaAP44hDyQYukokg5jliICZoFIoNjZ4Ol1HdhueOPgCLlFjt7twvo63HwztGuipml20lEBBlrGfBXzR5BsDGjOPBrAAkJKRKBwuuepNUXyP5/HN7tKXFGvcuMGY/3qhAO/NLCTJ7kFmIT0OPgjmAhiYKYIASFgGoCUyAILu+o8ckng0jSwsF1YuzxP0hYwm3tizwIIpKPQOIY4BXUYCiiYYWSIKYYHMoRAV1fKTddFxJKQOA/mmW9zFWRjoCmYw6R1lrcg2kxgAfCIeRxKMa+YBSw0Vc7fOScAZuAnMXWYE8yaIUFBDFSbS8sCgscsayZWD3jMAmhT7b8CnDPIeZw6RGTOLmwWFRALMA3BZvkamoBcwM3Zh7MA9Yb5I3v/YKoKTlr9sROKZVrlTGDWsylmkMTGxCQ4h0ObGaT1aRJzHsbtwJJmWSet0/9kIpB69gPbgersJA4oMm/pn6JlQI1/uWX87/YP06p9rkZQnAYAAAAASUVORK5CYII='
github64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAADAwMDQ0NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhyjGAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdUAAA3VAT3WWPEAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAABzSURBVChTbYxRFoAgDMPQ+98Z1zbIeJqPbU3RMRfDECqyGpjMg6ivT6NBbKTw5WySq0jKt/sHrXiJ8PwpAAVIgQGkwABSYAApMIAUGEAalFmK9UJ24dC1i7qdj6IO5F+xnxfLu0jS0c7kqxd3Dk+JY8/5AKFrLuM7mfCAAAAAAElFTkSuQmCC'
run64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAszD0iAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdUAAA3VAT3WWPEAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAABqSURBVChTpY5JDsAwCMTy/09TMGvFpVF9aAZPRHpkcXC7OIodPg0uCjPq+MwCrWRGKkiIvLyTqzw3aqoI73eqUNAoXBXlg4zudxF+NONfPIVvbSZPgww5oW0Vz8T4Lgbt/xbjia+rahR5AEYEg4vdzh2JAAAAAElFTkSuQmCC'
storage64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABwcHDQ0NDg4ODw8PFxcXGRkZGhoaGxsbHh4eIyMjJSUlJiYmJycnKCgoMTExMjIyNTU1NjY2Nzc3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAouNksgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdQAAA3UAe+RuhUAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAC5SURBVChTfZLbDsMgDEPpbb3TDv7/W7PYuAztYUeqhO2QAGowkXIMIeYkaSU4QsNBi4GcyhNINpTglmq4GWSphvy/ldkuLXZ4HmAxy3NmFJaA4guKGCwsjClfV05+fWdhYBtFw+amB292aygW3M7fsPTwjmadZkCvHEtWaAYTViBqVwgTA3tJVnB6D/xhaimItDhjMBvlhtFsaIafnEtOaAY/twAw/eslK70CbX8obUvgJNw9Jv0+Zh8D4s5+VAm/LwAAAABJRU5ErkJggg=='
def ShowMeTheButtons():
# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit' ]],
['&Edit', ['&Paste', ['Special', 'Normal',], 'Undo'],],
['&Toolbar', ['---', 'Command &1', 'Command &2', '---', 'Command &3', 'Command &4']],
['&Help', '&About...'],]
menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit']],
['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo'], ],
['&Toolbar', ['---', 'Command &1', 'Command &2',
'---', 'Command &3', 'Command &4']],
['&Help', '&About...'], ]
sg.SetOptions(auto_size_buttons=True, margins=(0,0), button_color=sg.COLOR_SYSTEM_DEFAULT)
sg.set_options(auto_size_buttons=True,
margins=(0, 0),
button_color=sg.COLOR_SYSTEM_DEFAULT)
toolbar_buttons = [[sg.Button('', image_data=close64[22:],button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0,0), key='-close-'),
sg.Button('', image_data=timer64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-timer-'),
sg.Button('', image_data=house64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-house-'),
sg.Button('', image_data=cpu64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-cpu-'),
sg.Button('', image_data=camera64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-camera-'),
sg.Button('', image_data=checkmark64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-checkmark-'),
sg.Button('', image_data=cookbook64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-cookbook-'),
sg.Button('', image_data=download64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-download-'),
sg.Button('', image_data=github64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-github-'),
sg.Button('', image_data=psg64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-psg-'),
sg.Button('', image_data=run64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-run-'),
sg.Button('', image_data=storage64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='-storage-'),
]]
toolbar_buttons = [[sg.Button('', image_data=close64[22:],button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0,0), key='_close_'),
sg.Button('', image_data=timer64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_timer_'),
sg.Button('', image_data=house64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_house_'),
sg.Button('', image_data=cpu64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_cpu_'),
sg.Button('', image_data=camera64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_camera_'),
sg.Button('', image_data=checkmark64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_checkmark_'),
sg.Button('', image_data=cookbook64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_cookbook_'),
sg.Button('', image_data=download64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_download_'),
sg.Button('', image_data=github64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_github_'),
sg.Button('', image_data=psg64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_psg_'),
sg.Button('', image_data=run64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_run_'),
sg.Button('', image_data=storage64[22:], button_color=('white', sg.COLOR_SYSTEM_DEFAULT), pad=(0, 0), key='_storage_'),
]]
# layout = toolbar_buttons
# ------ GUI Defintion ------ #
layout = [ [sg.Menu(menu_def, )],
[sg.Frame('', toolbar_buttons,title_color='white', background_color=sg.COLOR_SYSTEM_DEFAULT, pad=(0,0))],
[sg.Text('', size=(20,8))],
[sg.Text('Status Bar', relief=sg.RELIEF_SUNKEN, size=(55, 1), pad=(0, 3), key='_status_')]
]
layout = [[sg.Menu(menu_def, )],
[sg.Frame('', toolbar_buttons, title_color='white',
background_color=sg.COLOR_SYSTEM_DEFAULT, pad=(0, 0))],
[sg.Text('', size=(20, 8))],
[sg.Text('Status Bar', relief=sg.RELIEF_SUNKEN,
size=(55, 1), pad=(0, 3), key='-status-')]
]
window = sg.Window('Toolbar').Layout(layout)
window = sg.Window('Toolbar', layout)
# ---===--- Loop taking in user input --- #
while True:
button, value = window.Read()
button, value = window.read()
print(button)
if button in ('_close_', 'Exit') or button is None:
if button in ('-close-', 'Exit') or button is None:
break # exit button clicked
elif button == '_timer_':
elif button == '-timer-':
pass # add your call to launch a timer program
elif button == '_cpu_':
elif button == '-cpu-':
pass # add your call to launch a CPU measuring utility
if __name__ == '__main__':
house64 = 'data:image/png;base64,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'
timer64 = 'data:image/png;base64,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'
close64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAE30lEQVRIiZ2VXYgdRRqGn6+quvucM/85iRoTNevMBJFEWY0GFQTBC1HBlaz/jMpoFFfXBdmFvdiLvRIEFRHFGBXMjUQhF/6Bol6sSNaIruCNir/R/Dlx5iRzck736e6qby/6JDlx9CIWFN10Ue/7vW+9X7XcDn8bryWPL2vERkNQQPj9Q72K7F3s7Hxb9bZ98L0bj91jt1y23kxNTxIEGUQ/aTYR6WW9cud/Prx01zf7/7FP5EHXHG7Y6bVTpBPLMSegCWKEEMKvkihgjEWDP+FbEjxTa1bjv9l/CsIKF3ypHhUDSFGACCKC956iKKjV6/hfkCjgUNK0TW1oCA3h+EJk8UUBYFCsQaSyRajArUWLnEONcTrT68nTLtZaEKmmMTiUlsREGy9HO0dgcL1y6lgtZrAsEYFexhwxq2buYfru+1mcOo+828UYg4rgUH7OSkY3zbDq1lkaV1yFP9TqEyy18jiBCMF7DjYmOOu+hxifnCSKItZuvp/F6fPJ05TEwE+dHhN33MfpGy4iFAVjf7qF8etvBV9y1IilBApGIMt6TExOM372JKqKqhLFMdOz93Jk6jx+bHVoztzLyj9eiHqP2Gq7O3UlGAuq1RwYDlUwhoChMdSAz3ZxaEeD8T/fBggaAnGtxpqZWdKFBSbOPLMCCQGJItJPdrHw4lOYRgNsBM6dSCDGErIuodtGkhoyPEr68U5svcbI1ZsQY0CV2vAw9ZGRKjEiSBTR/fQjDm9/AddcjqoSul182kYHVDhJauRffUH7wD7ilatxzVOwI6PM7XiJLO2x4rob0CgGVTSEKigidD94j/ltW9Dg0b0/4BfmyQ8ewKUdWLZ6wCIB9SXFXJvQ+hLkc6QeEznHf199jY1rpjh1w0ZUFTGm7z18/tSj2Hffor5shKLdhhJCADMcw7IlKRIkAqkJRIa4LPl6d5c/PPJkBd5vpArcArD+ue101l1Md08bFxuIBUlOyOUggUIAVIl94Kv5wKqtz7L+7r/0bRHEmApcFbwnHhljw6tv0b3kEtK5gDWmj/GbfQAWZbdaztjyPOfP3oN6D8GDCO133uDAvx9CyxKsRX1JMjbBBa+8Rnbl5RSpR35RfXUGfVLnYGFBcTfdwLo77yLkPYy14CLa773JngfuoNy7QOh2WPnw09WVkufUm8s598G/s+eT9wmBJZ1m+sVTFNBc4Wi8vJ3v//kAJk7AOhbf3MGezTfjWwuYCcv8s1s58K+/okWOxDGdjz5g7+YZtKRSoL+igCp5FKVntGk48sTTzDWb1C+4mB833wgETD2CELBjEfNbtyAjo4xdcz27N11L6B5GGoZQhN+26KiSoII9LebnJx9BkggzNIQkyfEdItiRQGvbM7S2bQHJMGN1NO8ds2dQhBORYBCjAFEE1kFSw0QxuAiTJCAGce64vz4gviTkOTJcErIMMRbyDIxg7bHTFnc47clcmpdj43VkeBRJEkytgdTqSL2OiRMkSRDroH9t4EtCUaBZhmYpIUurZ9pFfVnuX+w62xfjeq3D3/6vbifXrT1XkzgWdREmipA4RlwMUYRY21cg/X+lJ5gSbIHGOVovCHmOCSX7DrbMx599icIhVI2cA5c5mC1gbGnITm4oqAOr0PoOXs9g51HAGiITyCDByXDp4KuiaoESmP8/YC0Y5GajmEsAAAAASUVORK5CYII='
psg64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAMAUExURQAAABlbkiVhkyZikyFjmShjkyhlly1mli5nlylnmS5olyppnC5qmi5rmzBpmDBpmTFqmDFqmTFqmjNrmzFrnDNsmzJsnDJtnTFunjNvnzRsmTRtmzVunTVunjVvnzZwnjlxny5toDFvozJwoTNzpjVwoDRzpDRzqDd4rThyojp0ozl1pTt2pjt3pz11ozt4qDl4qTp6rTl6rzx4qD55qTx5qj97qz17rT58rD98rT9+rz5+sEB3pEF9rkB+r0F+sEF/sT2AtD6AtT6Btk+Aqk2CrEOBs0GBtEKCtEGCtUSBskWBs0SCtEWDtUaEtkWFt0aGt0KFuUCEukOGu0eFuEWHu0eJvEiGuUiHukiIuUiIukmJu0uKvEyKvFCAp1CCqlODrVKCrl2Kr1OEs1KGsFWGsFaIsVaPvFqKsl6NsmKNsWeTuG6YvHadvlySwV6UxF+YxW+bxW6dxnKewHGex3SdwHSfx3egwXGizHmgwHqkxnyjxHio0f/RMf7QMv/TMf/SMv3SNf7UOv7UO//UPP/UPf/UPv/VP//WPP/XPv/VQ//WQv7XQ//WRP/XRf/WR//YRv/YSP/YSf/YSv/ZS//aS//ZTf/aTP7aTf7aTv7bT//cT//bUP/cUP7cUv/cU/7cVf/eVf/fVv/eV/7dWP/eWP/eWf/fWv/fW//fYvzcaf/hW//gXP/gXv/gX//hYP/hYf/hY//iYP/jY//gZf/iZP7iZf/jZv/iZ//lZv/jaf/kav7ka//maf/ma//kbf/lbv7mbP/mbv/mb//id//mcP/ncv/nc//ld//ndv/meP/ocf/ocv/oc//odP/odf/odv/peP/pff/qfY+11ZSzz5G41qC81aW/1P/jgf/qiv/qjv7qoMnZ5szb587d6eDm2+fo1+7v3e/x3vXw1fHx3gAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJblQd8AAAEAdFJOU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////wBT9wclAAAACXBIWXMAABcQAAAXEAEYYRHbAAAAGHRFWHRTb2Z0d2FyZQBwYWludC5uZXQgNC4xLjFjKpxLAAABzUlEQVQoU2P4jwNAJZIEuLJA9M2u/iNgAaiEELOgIFPc//+r6puaalvAQmAJdg4pPj4h5oT/2+raWtqaGmAS/PxC/IJAGdbEB7saW5pb20AyQAkFNiFhUSEgkGZNfjizua29u70XJJHr8j+eV0RGVkRMTJb56u2mvt7eSR0gCT2gPsbMGzbi8hJyPDl3OidPnDRlwhagRHbG/zTXe5WSqqqqmpzXb/VMmz5jztSVIDtSWFLvl3Jrampq8ZY8WThj1tx586ZCXFV9t1xRR1tbR6Lw0f6ZC+YvWDAb6tz/xUom+rrGymWPD8xaunjZ0oUgMZBEsYqZqampWsnTY/PWLF+xZhFIHCRRpW5raWFhUPT/3IJ1a9euW/H//5oTYAlDezs7Kwvv//+XbN6wcev6//+3/z8FltDwcrC3N8/7v3rHtu07Nv3/vxVo0CWQhJGPm5ubdf7/TXt279699//JnTA70j38fH19wv//33b00OGj+w6fPXz5KMRVTiH+/gHuFf//7zl+5szZs2fO7YPo+H/FOSIyPMqz5v//g+dAMocvQCX+XwsMjYmNdgSy9p0/d/bgRZAYWOL//4LgoDAwY+++02AaJoEJcEj8/w8A4UqG4COjF7gAAAAASUVORK5CYII='
cpu64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAFi0lEQVRIiZ1WS2wbRRj+/5l92O6u7WycTW03xLEd6uBUjVO1hfbSByLQEwhxoIhbCwcuvApUiEOFhAQVEiAOvK4gqoojSEhtgUNApaJKG5qkdWpa1JfcZL3teu3sZmeGQ9ZVGhIJ8Z/+2Vn93//45psBWMMqlcoXxWLxEACAaZpju3btOkkIoZRSsnv37hOmaY4BABSLxUOVSuXzteJIq32klMqyLBuqqhoAAKqqGpTSpKIoSUQESZK6OnuKohiKohiUUpkxtvivWCvWBABEOp1+sr+//5V169ZtnJub+6FUKh3Rdf3hVqv1l6Zp5Ww2ezASifQ0Go3fhoaGjsZisYdardaM4zjTiEgAQHQC4j0HkQghAAC4oiiJRCKxBQBIs9m8oOt6iRASa7VaVwEAYrFYP+e85TjOpXg8PiyE4LZtn/F93wYAgogghOD3AYS+UFW1q1AovGoYxp4wGxIEgS2EEIQQCQCAcx7gkslCCB8AwLbt07Va7SPP8xqdWPdmIElSxDTNfZZlncrn828MDg6+VavVPvF9fy4Wi/X19fUdWJHMfSaEYJlMZgwRpVqtdtQwjD31ev2HIAgWpJGRkS8VRTEMw9g9OTm5v7u7+9GpqamXq9XqxwAAmzZt+oBzjpzzYC0QIQRDRJpIJLanUqmdw8PDX1mW9ZPv+5bkOM5FVVVTiURia1i24rruDQCAUqn09sDAwCHGGEdEadnwlgOJZT5BRMIYc5rN5iXP8+ax0y9N04qc84Vt27aduHjx4uuEED46Ovo95xxEOH1ExKWEhQh9DPe4JEl0fn7+14mJiecQUWo2m7MAgNQ0zb3d3d3bhoaGjrTb7Wld1x/p6uoa2bBhw4uyLGsAEFBKKSIi51xQSjFcIiICIQRDAhDXdWue502Vy+X3hRALqqr2SoODg2/KsmzE4/GNlNJ1nPOF9evXPxYEAbiue7lWq72rKIphmub+GzdufBeNRg1d14cZYx4hhBJClFQqNRbOQlBKo8lkcms+n48vLi5a0vj4+OOKoiTT6fQzjuNcJYRIQRCALMswOzv7LSEk0tPT85TjOBeCIKi12+1rtm3/ruv6FgDgAMB7e3vHgiAAQgh1HOfquXPnXr958+Zx3/dtshopltp7nyEiUtd1rxuG8URfX99B13Un2+32rKIo3ZzztRgMdOfOnT/mcrkX+vv79zcajVOapm3XNC3HGINoNNpnWdZJz/P+TiQSOzRNK6bT6WcjkUh/q9WaQUTIZrMHEFEjhECz2fzL9/2ZkZGRz0zT3JfNZp+WqtXq+5FIJJXL5V5kjLVDdgDnnMVisYFyufxVSFHgnO9gjDFElIvF4jth34ExxgCAIiIyxtq2bZ+5cuXK5wsLC3NSvV4/BQDCsqw/hBBBLpeTO+WF/KdhC0TIHAoAIggCjogYMnjpEBAi27Z96ezZsy90aCoVCoXXVFVNZbPZ/TMzMy9xzr1ljSdhYLHicN0DCkFYWKFnGMamUqn06fXr17/xPG9e0nV9Y6jnWqiAPCydrTm5laxY+pcCABdCcEqprmnag4qiWNLExMTBZWI3Ho/Hd2Qymb1CCBpm+V8AQJZluHPnzum5ubnx8+fPH+iI3apync/nX04mk9vDXihCiMX/K9drXTjJZDK5FRHJ3bt3/9R1/cH/e+Esb0FnkKK3t3ff5s2bv+7p6Rm7devWsXK5/GGhUDjsOM5kNBp9oFKpfKNp2kC9Xv9xdHT0eCaTed513fPhlYmd4CsBOiDQarVmu7q6KpZl/XLt2rVjQggvHo8PTE9PH242m1PpdPrRy5cvf3L79u2fo9GoyRi7U61W3wsDL5fv1V8VjLFF3/ct3/ctAADP86wgCBq+7zcAABljtud5FgCA7/uWLMvWai8KAIB/ACsf4Gh+DNwbAAAAAElFTkSuQmCC'
camera64 = 'data:image/png;base64,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'
checkmark64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAD2ElEQVRIibWVe4hUVRzHP+feuTOz82gfrqwu5gM0zTQpS1yfoGQPyc3IjOwlYRElPcDICEP6Q6i/IvojCCIpTA0tSlSqJSvbTLZE0dbWxz4nXWdnxrk7M/feOY/+sHyEa7pt57/z45zP53x/B84R/B/jzeNLgeXADDHE4IeBV2Ihpo6LK1rzNqEhAW9oGw18UhelYeWUGHFL0tx5lqPZyBAI3mi9o8YRm16cWTlsVFLQVwjY2+4SSI2W+j8KXj+ybmwytO69xjo7Wyqzr8sldbaE60ksIdBlhTVo+KuHXppY5azftKzeNsbQkurntOuTKQQobYhFbCgPNsGaA5NDWm94ZlYV7fmAX3pcenIlTucDAqlJRENUxcJQLgwiwfMtYcpq4503JMJjq8M0d+XpyBRJnfUpBpJwyKYqFqbCcSCQg0gQyCeq4qHp90yr5Pd0kY6+ImnXJ1CaeDhEdSJCTSJKzLEHLXhu4oQEuWKZ79uzZAoX2hKPhOn+I6DtuEdfLriC4NE9L4CYhzEP8dH84Hz9kT0NBHLqvMlJmo5nyBQDylITj4RwM5rmw70orcEA0AL8Q/DgN8OBr/DltL8q64G1F52+obomwr6US7boE0hNhRPiVIdHx7H+EvA2sJ0tC3/+e8uFS27c/SS+7ElGrGkbnp5EfV0UArmGxt0Lzq/x5YzKWocz/T4FXyGEINvj0XE410QgJ7Fl4dqL4ecS3PVlJYgdllKzx04ZxqolY8h4mkm315JPl+z+nP8Bd++4hZ2LM/hyuokLCr7Eti28TJnOA5ndGLOUnYtLl+u2YMHnJ4BxY2bWsWj2SA72eoBBG4PnBvy2qwvpq81gVjhJp1Q7q9axLIFVMqSaz3ytfLWEpsbLwgFs6pc1o/R9+e7+eK9joSMWvjR4gSLA4FSGKLS7UyirUmRkbJFTG0VI6N17+oR0/bl8d/+A8HMJAG7bPB7BTmGL8TVz64mMiKGNQSuN0hqvq59CS59Kzq2zo8MrcH/s1V6qMIf9y5uvBL8gALj54xpgG5aYH589klB9BdoYjDY0XJ9k9HURPj2aRZ/ycL/tfouDK17+N/ilAoAbP6wAsRGLB8INI7BGJUAYLGEhLAtLCApfnDymc95NtD4eDMC8ZNiXzNKfSdLbt5K8N6o68nNMwoHqKCAwlkVwKI06ln2MtpWtVwMHBnjspHyNQO1Xe7pRbTmUEchCGbk/laKsdl0tfGBB51OKQM0hUD/ppk7kkTTy11NQku/TuUpdi+DKn/7wdyuAHzDcii0Uykwg/ezJoRMAVL9TCWwFjpJdvfpa4AB/Akx4zQw8GDagAAAAAElFTkSuQmCC'
cookbook64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAYCAIAAAB1KUohAAAACXBIWXMAAAsSAAALEgHS3X78AAADMUlEQVQ4jY1UQUgCWxS9782M5hQzle3NTRGEQdBipCKKECoEg4JaJAqCmyBsYauEaNOqjQtXLSKINuFiKMiwIMtF1iLK2kWRZLUoDRxo5s37ixfSt4+/u7xzz51z7r3nwc7Ojt1uBwCEEPwtWKXL5eIvLy+HhoYIIYIgCIJAKa0Do5RyHPfy8nJycnJ1dcUjhJxOZygUOj09zefzFoulDp5SihCKRqPLy8vJZBI4jgOAo6Mjj8cDABjj/6WdTqdDoRAAfJeyFn8MQohhGADAY4xFUSyVSpIkAYBpmgih+soRQmxm2GazbW5u7u7ujoyMKIrCmP+ePMdxv9nhSqXi8/lmZmb29vay2Syrs1gs8EM/QogQQgipBWOMOzs7397eWlpabDYbAMiyHAwGu7u7mQTWzu/3R6PRxsZG+HERvNVqjcVix8fHfX19Nzc3T09PHo+HUjo1NVUulx8fHwFgbW0tEolQSguFwtbWVpU/rlQqs7Ozc3NzqqrmcjmXy9Xe3m61WgcGBubn5wGgo6NjYWEBAEql0t3dHQBUx8ljjNva2orFYnNzM8/zBwcHFoslGo329/cXCgUA6OnpwRh/fHwsLS3lcjm2qm9wQ0NDPB7f398fHBx8eHjIZrOqqhaLRUmSwuFwPB53OBw+ny+dTn9+ftYujed5AEilUhMTE9U9saTX66WUJhKJmv0dHh4Gg0FgF4YxJoQwANNjGIaiKLFYbHp62ul0Li4umqb5H5crSVIymQwEAolEwu12s6SiKNfX15OTkwDgcDguLi4ikUgVUv0zCIJgs9lUVWWlrP3q6qrf72dfAaCrq2tjY0OW5RowTynVNM1qteq6XqW9srJiGAZCSNd1hNDt7W04HGZm+NeFiaKYTCa3t7fHx8fdbjez+9fXV7UR87Cu66Zp1oI1TQsEAl6vN51Os9smhCCEfpbWmMw0TZbBpmm+v7+3traWy2VKKdP825I/M7Isi6IIAFxTU9P6+nomk+nt7X19fX1+fsYY1/ez0+k8Pz+/v7/nMMblcnl4eDifz5+dnWmaVgfGolQq2e32sbGx7wcok8mMjo7C396wVCpFKSWE/ANWXYLwO0+V8wAAAABJRU5ErkJggg=='
download64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAACXBIWXMAAAsSAAALEgHS3X78AAAEl0lEQVRIia2WS2hdZRDHf/Odc+7NvbZpYky1Gk2rEbRa26pt8UWLitYHIqigCD426kIQxCfWhYu68U0RBBERXCq+WrXoorYIFWpbEY0lpk0NTWKtuUlzn+d834yLm5smqQspzurMcM785j+c+eYTTtUcESAzvhIAm/+azHacA4FodszAVNFTrUPm+Q6iecmUyJkEna5OiDCCXCtvJ2cnV+Ep+9R7/VIfQhmeryKeySywok+SSMMKMwqAihDXPIcPDDMURUQCgiPWjJCck6x87ZXXV3cXu3XTO5tkYOvAHbnIfZipTpghLdAMIEngi1cXvtlzwfrHpG0x5ismzsvo0E9D9z7z++M799s2EcSm67OUkAs5cpbzkkoMtPtAAzdXQ9zqjHkt1Ol5SHofx0KWYRUxrdiS3FlLtzz51wd7+v2OQl7qHnPtorUXS3ZxPRUKUT5x4mTDWu559LbCNS+9X9v025Duc4KoYdMAA7A4Mk92EMp/JFIZwR/rx9dL1teVdC2/Qe8yzQg+pS0JvLUzx3hjioPVQamGGlcu47KNq6qrPj+fsd+GeAEYA2SmRQiCNSJKP1Ad3IVaG0nnlWRxKqkkVlYxJxGZwhmFIo34U/fh0Hv4v6YYrY+ihYtkorDUNj+298GPvzv6ZRrkMzA/oyCXh9rEMOOHfiLfcx+5zhXkOnppswxEpJHVxdTjs0CycDHy9XcMlwc5a0E3EoTconOls/dyBsb6lYRLY4m/9T6blDgi8oHw3rPx83fesubl4oVPWFvXBUKoQzqB92Xitpite77n/k/epaN7AZO1CTIROtZ14fJC6ccS9ndGUhRLK0Eum1h2YGpH5eFfD47sjluzcFo+f+vp655F03alNhZhASMjloA1qtzedzab125kiw2QLhHaQ0zIFM2MztUdkBcqx1Lp+0o59NGRP49OVQs0Z3d6nEyMUMP8OGgVtAJaA19CagP4xn4e6DPuPhox1V9HTRFr/h9mRmWkwbJtGSsHK4xXq4cQGQDCDABM0ClEy6DlJiA9DLV90BgktirFzhrPXX0mT6Y9lAaqkAhRItRKGT3bjetTYd2aYM7JYcwm5wwaAP44hDyQYukokg5jliICZoFIoNjZ4Ol1HdhueOPgCLlFjt7twvo63HwztGuipml20lEBBlrGfBXzR5BsDGjOPBrAAkJKRKBwuuepNUXyP5/HN7tKXFGvcuMGY/3qhAO/NLCTJ7kFmIT0OPgjmAhiYKYIASFgGoCUyAILu+o8ckng0jSwsF1YuzxP0hYwm3tizwIIpKPQOIY4BXUYCiiYYWSIKYYHMoRAV1fKTddFxJKQOA/mmW9zFWRjoCmYw6R1lrcg2kxgAfCIeRxKMa+YBSw0Vc7fOScAZuAnMXWYE8yaIUFBDFSbS8sCgscsayZWD3jMAmhT7b8CnDPIeZw6RGTOLmwWFRALMA3BZvkamoBcwM3Zh7MA9Yb5I3v/YKoKTlr9sROKZVrlTGDWsylmkMTGxCQ4h0ObGaT1aRJzHsbtwJJmWSet0/9kIpB69gPbgersJA4oMm/pn6JlQI1/uWX87/YP06p9rkZQnAYAAAAASUVORK5CYII='
github64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAADAwMDQ0NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhyjGAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdUAAA3VAT3WWPEAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAABzSURBVChTbYxRFoAgDMPQ+98Z1zbIeJqPbU3RMRfDECqyGpjMg6ivT6NBbKTw5WySq0jKt/sHrXiJ8PwpAAVIgQGkwABSYAApMIAUGEAalFmK9UJ24dC1i7qdj6IO5F+xnxfLu0jS0c7kqxd3Dk+JY8/5AKFrLuM7mfCAAAAAAElFTkSuQmCC'
run64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAszD0iAAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdUAAA3VAT3WWPEAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAABqSURBVChTpY5JDsAwCMTy/09TMGvFpVF9aAZPRHpkcXC7OIodPg0uCjPq+MwCrWRGKkiIvLyTqzw3aqoI73eqUNAoXBXlg4zudxF+NONfPIVvbSZPgww5oW0Vz8T4Lgbt/xbjia+rahR5AEYEg4vdzh2JAAAAAElFTkSuQmCC'
storage64 = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAMAAADXqc3KAAAABGdBTUEAALGPC/xhBQAAAwBQTFRFAAAABwcHDQ0NDg4ODw8PFxcXGRkZGhoaGxsbHh4eIyMjJSUlJiYmJycnKCgoMTExMjIyNTU1NjY2Nzc3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAouNksgAAAQB0Uk5T////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////AFP3ByUAAAAJcEhZcwAADdQAAA3UAe+RuhUAAAAYdEVYdFNvZnR3YXJlAHBhaW50Lm5ldCA0LjEuMWMqnEsAAAC5SURBVChTfZLbDsMgDEPpbb3TDv7/W7PYuAztYUeqhO2QAGowkXIMIeYkaSU4QsNBi4GcyhNINpTglmq4GWSphvy/ldkuLXZ4HmAxy3NmFJaA4guKGCwsjClfV05+fWdhYBtFw+amB292aygW3M7fsPTwjmadZkCvHEtWaAYTViBqVwgTA3tJVnB6D/xhaimItDhjMBvlhtFsaIafnEtOaAY/twAw/eslK70CbX8obUvgJNw9Jv0+Zh8D4s5+VAm/LwAAAABJRU5ErkJggg=='
ShowMeTheButtons()

View file

@ -6,6 +6,8 @@ import PySimpleGUI as sg
Check out the variable menu_def for a hint on how to
define menus
"""
def second_window():
layout = [[sg.Text('The second form is small \nHere to show that opening a window using a window works')],
@ -15,23 +17,24 @@ def second_window():
event, values = window.read()
window.close()
def test_menus():
def test_menus():
sg.change_look_and_feel('LightGreen')
sg.set_options(element_padding=(0, 0))
# ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit' ]],
['&Edit', ['&Paste', ['Special', 'Normal',], 'Undo'],],
['&Toolbar', ['---', 'Command &1', 'Command &2', '---', 'Command &3', 'Command &4']],
['&Help', '&About...'],]
menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit']],
['&Edit', ['&Paste', ['Special', 'Normal', ], 'Undo'], ],
['&Toolbar', ['---', 'Command &1', 'Command &2',
'---', 'Command &3', 'Command &4']],
['&Help', '&About...'], ]
# ------ GUI Defintion ------ #
layout = [
[sg.Menu(menu_def, tearoff=False, pad=(20,1))],
[sg.Output(size=(60,20))],
]
[sg.Menu(menu_def, tearoff=False, pad=(20, 1))],
[sg.Output(size=(60, 20))],
]
window = sg.Window("Windows-like program",
layout,
@ -43,13 +46,14 @@ def test_menus():
# ------ Loop & Process button menu choices ------ #
while True:
event, values = window.read()
if event is None or event == 'Exit':
if event in (None, 'Exit'):
return
print('Event = ', event)
# ------ Process menu choices ------ #
if event == 'About...':
window.disappear()
sg.popup('About this program','Version 1.0', 'PySimpleGUI rocks...', grab_anywhere=True)
sg.popup('About this program', 'Version 1.0',
'PySimpleGUI rocks...', grab_anywhere=True)
window.reappear()
elif event == 'Open':
filename = sg.popup_get_file('file to open', no_window=True)
@ -57,4 +61,7 @@ def test_menus():
elif event == 'Properties':
second_window()
test_menus()
window.close()
test_menus()

View file

@ -1,46 +1,50 @@
#!/usr/bin/env python
import sys
if sys.version_info[0] >= 3:
import PySimpleGUI as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
'''
Parallel windows executing.
'''
layout1 = [[ sg.Text('Window 1') ],
[sg.Input(do_not_clear=True)],
[sg.Input('')],
[ sg.Button('Read')]]
window1 = sg.Window('My new window', location=(800,500)).Layout(layout1)
window1 = sg.Window('My new window', layout1, location=(800,500))
layout2 = [[ sg.Text('Window 2') ],
[sg.Input(do_not_clear=True)],
[sg.Input('')],
[ sg.Button('Read')]]
window2 = sg.Window('My new window', location=(800, 625), return_keyboard_events=True).Layout(layout2)
window2 = sg.Window('My new window', layout2, location=(800, 625), return_keyboard_events=True)
layout3 = [[ sg.Text('Window 3') ],
[sg.Input(do_not_clear=False)],
[ sg.Button('Read')]]
window3 = sg.Window('My new window', location=(800,750), return_keyboard_events=True).Layout(layout3)
window3 = sg.Window('My new window', layout3, location=(800,750), return_keyboard_events=True)
while True: # Event Loop
event, values = window1.Read(timeout=50)
event, values = window1.read(timeout=0)
if event is None:
break
elif event != '__timeout__':
print(event, values)
event, values = window2.Read(timeout=0)
event, values = window2.read(timeout=0)
if event is None:
break
elif event != '__timeout__':
print(event, values)
event, values = window3.Read(timeout=0)
event, values = window3.read(timeout=0)
if event is None:
break
elif event != '__timeout__':
print(event, values)
window1.close()
window2.close()
window3.close()

View file

@ -1,9 +1,4 @@
import sys
if sys.version_info[0] >= 3:
import PySimpleGUIQt as sg
else:
import PySimpleGUI27 as sg
import PySimpleGUI as sg
import queue
import logging
import threading
@ -49,15 +44,18 @@ class QueueHandler(logging.Handler):
def main():
window = sg.FlexForm('Log window', default_element_size=(30, 2), font=('Helvetica', ' 10'), default_button_element_size=(8, 2), return_keyboard_events=True)
layout = \
[
[sg.Multiline(size=(50, 15), key='Log')],
[sg.Button('Start', bind_return_key=True, key='_START_'), sg.Button('Exit')]
layout = [
[sg.MLine(size=(50, 15), key='Log')],
[sg.Button('Start', bind_return_key=True, key='-START-'), sg.Button('Exit')]
]
window.Layout(layout).Read(timeout=0)
window = sg.FlexForm('Log window', layout,
default_element_size=(30, 2),
font=('Helvetica', ' 10'),
default_button_element_size=(8, 2),
return_keyboard_events=True)
window.read(timeout=0)
appStarted = False
# Setup logging and start app
@ -70,13 +68,13 @@ def main():
# Loop taking in user input and querying queue
while True:
# Wake every 100ms and look for work
event, values = window.Read(timeout=100)
event, values = window.read(timeout=100)
if event == '_START_':
if event == '-START-':
if appStarted is False:
threadedApp.start()
logger.debug('App started')
window.FindElement('_START_').Update(disabled=True)
window['-START-'].update(disabled=True)
appStarted = True
elif event in (None, 'Exit'):
break
@ -88,10 +86,9 @@ def main():
pass
else:
msg = queue_handler.format(record)
window.FindElement('Log').Update(msg+'\n', append=True)
window['Log'].update(msg+'\n', append=True)
window.Close()
exit()
window.close()
if __name__ == '__main__':

View file

@ -1,15 +1,11 @@
#!/usr/bin/python3
import queue
import threading
import time
import PySimpleGUI as sg
# This program has been tested on all flavors of PySimpleGUI and it works with no problems at all
# To try something other than tkinter version, just comment out the first import and uncomment the one you want
import PySimpleGUI as sg
# import PySimpleGUIQt as sg
# import PySimpleGUIWx as sg
# import PySimpleGUIWeb as sg
"""
DESIGN PATTERN - Multithreaded Long Tasks GUI
@ -41,14 +37,6 @@ def long_operation_thread(seconds, gui_queue):
gui_queue.put('** Done **') # put a message into queue for GUI
###### ## ## ####
## ## ## ## ##
## ## ## ##
## #### ## ## ##
## ## ## ## ##
## ## ## ## ##
###### ####### ####
def the_gui():
"""
Starts and executes the GUI
@ -60,23 +48,27 @@ def the_gui():
layout = [[sg.Text('Long task to perform example')],
[sg.Output(size=(70, 12))],
[sg.Text('Number of seconds your task will take'),sg.Input(key='_SECONDS_', size=(5,1)), sg.Button('Do Long Task', bind_return_key=True)],
[sg.Text('Number of seconds your task will take'),
sg.Input(key='-SECONDS-', size=(5, 1)),
sg.Button('Do Long Task', bind_return_key=True)],
[sg.Button('Click Me'), sg.Button('Exit')], ]
window = sg.Window('Multithreaded Window').Layout(layout)
window = sg.Window('Multithreaded Window', layout)
# --------------------- EVENT LOOP ---------------------
while True:
event, values = window.Read(timeout=100) # wait for up to 100 ms for a GUI event
if event is None or event == 'Exit':
event, values = window.read(timeout=100)
if event in (None, 'Exit'):
break
elif event.startswith('Do'):
try:
seconds = int(values['_SECONDS_'])
print('Starting thread to do long work....sending value of {} seconds'.format(seconds))
threading.Thread(target=long_operation_thread, args=(seconds , gui_queue,), daemon=True).start()
seconds = int(values['-SECONDS-'])
print('Thread ALIVE! Long work....sending value of {} seconds'.format(seconds))
threading.Thread(target=long_operation_thread,
args=(seconds, gui_queue,), daemon=True).start()
except Exception as e:
print('Error starting work thread. Did you input a valid # of seconds? You entered: %s' % values['_SECONDS_'])
print('Error starting work thread. Bad seconds input: "%s"' %
values['-SECONDS-'])
elif event == 'Click Me':
print('Your GUI is alive and well')
# --------------- Check for incoming messages from threads ---------------
@ -90,17 +82,8 @@ def the_gui():
print('Got a message back from the thread: ', message)
# if user exits the window, then close the window and exit the GUI func
window.Close()
## ## ### #### ## ##
### ### ## ## ## ### ##
#### #### ## ## ## #### ##
## ### ## ## ## ## ## ## ##
## ## ######### ## ## ####
## ## ## ## ## ## ###
## ## ## ## #### ## ##
window.close()
if __name__ == '__main__':
the_gui()
print('Exiting Program')
print('Exiting Program')

View file

@ -8,13 +8,7 @@ import queue
import threading
import time
import itertools
# This program has been tested on all flavors of PySimpleGUI and it works with no problems at all
# To try something other than tkinter version, just comment out the first import and uncomment the one you want
import PySimpleGUI as sg
# import PySimpleGUIQt as sg
# import PySimpleGUIWx as sg
# import PySimpleGUIWeb as sg
"""
DESIGN PATTERN - Multithreaded GUI
@ -33,13 +27,13 @@ import PySimpleGUI as sg
"""
######## ## ## ######## ######## ### ########
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ##
## ######### ######## ###### ## ## ## ##
## ## ## ## ## ## ######### ## ##
## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ######## ## ## ########
# ######## ## ## ######## ######## ### ########
# ## ## ## ## ## ## ## ## ## ##
# ## ## ## ## ## ## ## ## ## ##
# ## ######### ######## ###### ## ## ## ##
# ## ## ## ## ## ## ######### ## ##
# ## ## ## ## ## ## ## ## ## ##
# ## ## ## ## ## ######## ## ## ########
def worker_thread(thread_name, run_freq, gui_queue):
"""
@ -54,15 +48,17 @@ def worker_thread(thread_name, run_freq, gui_queue):
print('Starting thread - {} that runs every {} ms'.format(thread_name, run_freq))
for i in itertools.count(): # loop forever, keeping count in i as it loops
time.sleep(run_freq/1000) # sleep for a while
gui_queue.put('{} - {}'.format(thread_name, i)) # put a message into queue for GUI
# put a message into queue for GUI
gui_queue.put('{} - {}'.format(thread_name, i))
# ###### ## ## ####
# ## ## ## ## ##
# ## ## ## ##
# ## #### ## ## ##
# ## ## ## ## ##
# ## ## ## ## ##
# ###### ####### ####
###### ## ## ####
## ## ## ## ##
## ## ## ##
## #### ## ## ##
## ## ## ## ##
## ## ## ## ##
###### ####### ####
def the_gui(gui_queue):
"""
@ -73,18 +69,19 @@ def the_gui(gui_queue):
:param gui_queue: Queue the GUI should read from
:return:
"""
layout = [ [sg.Text('Multithreaded Window Example')],
[sg.Text('', size=(15,1), key='_OUTPUT_')],
[sg.Output(size=(40,6))],
[sg.Button('Exit')],]
layout = [[sg.Text('Multithreaded Window Example')],
[sg.Text('', size=(15, 1), key='-OUTPUT-')],
[sg.Output(size=(40, 6))],
[sg.Button('Exit')], ]
window = sg.Window('Multithreaded Window').Layout(layout)
window = sg.Window('Multithreaded Window', layout)
# --------------------- EVENT LOOP ---------------------
while True:
event, values = window.Read(timeout=100) # wait for up to 100 ms for a GUI event
if event is None or event == 'Exit':
# wait for up to 100 ms for a GUI event
event, values = window.read(timeout=100)
if event in (None, 'Exit'):
break
#--------------- Loop through all messages coming in from threads ---------------
# --------------- Loop through all messages coming in from threads ---------------
while True: # loop executes until runs out of messages in Queue
try: # see if something has been posted to Queue
message = gui_queue.get_nowait()
@ -92,11 +89,12 @@ def the_gui(gui_queue):
break # break from the loop if no more messages are queued up
# if message received from queue, display the message in the Window
if message:
window.Element('_OUTPUT_').Update(message)
window.Refresh() # do a refresh because could be showing multiple messages before next Read
window['-OUTPUT-'].update(message)
# do a refresh because could be showing multiple messages before next Read
window.refresh()
print(message)
# if user exits the window, then close the window and exit the GUI func
window.Close()
window.close()
## ## ### #### ## ##
@ -108,12 +106,16 @@ def the_gui(gui_queue):
## ## ## ## #### ## ##
if __name__ == '__main__':
#-- Create a Queue to communicate with GUI --
gui_queue = queue.Queue() # queue used to communicate between the gui and the threads
#-- Start worker threads, one runs twice as often as the other
threading.Thread(target=worker_thread, args=('Thread 1', 500, gui_queue,), daemon=True).start()
threading.Thread(target=worker_thread, args=('Thread 2', 200, gui_queue,), daemon=True).start()
threading.Thread(target=worker_thread, args=('Thread 3', 1000, gui_queue,), daemon=True).start()
#-- Start the GUI passing in the Queue --
# -- Create a Queue to communicate with GUI --
# queue used to communicate between the gui and the threads
gui_queue = queue.Queue()
# -- Start worker threads, one runs twice as often as the other
threading.Thread(target=worker_thread, args=(
'Thread 1', 500, gui_queue,), daemon=True).start()
threading.Thread(target=worker_thread, args=(
'Thread 2', 200, gui_queue,), daemon=True).start()
threading.Thread(target=worker_thread, args=(
'Thread 3', 1000, gui_queue,), daemon=True).start()
# -- Start the GUI passing in the Queue --
the_gui(gui_queue)
print('Exiting Program')
print('Exiting Program')

Some files were not shown because too many files have changed in this diff Show more