From b5e001dabcbaba4dcdf1c747e430c759d9797aee Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Tue, 13 Nov 2018 10:33:55 -0500 Subject: [PATCH] Latest updates from Tony --- Colours.gif | Bin 41396 -> 0 bytes .../ButtonClick.wav | Bin .../Color-Guide.png | Bin .../Color-names.png | Bin ...Plot (Matplotlib numpy pyplot(y=sinx)) .py | 65 ++++++++ .../10b PSG Plot (axes moved).py | 57 +++++++ .../10c PSG Plot (axes pi format).py | 73 +++++++++ ...0d PSG (Plots Tabs and sin cos options).py | 100 ++++++++++++ .../MacOS versions/10e PSG (Same Window).py | 98 ++++++++++++ .../10f PSG (linear and quadratics).py | 121 ++++++++++++++ .../1a PSG (Entry and PopUp).py | 36 +++++ .../MacOS versions/1b PSG (Format).py | 41 +++++ .../1c PSG (persistent form and bind key).py | 35 +++++ ...PSG (named input keys and catch errors).py | 36 +++++ .../1e PSG (validation and Look and Feel).py | 36 +++++ .../1e PSG (validation).py} | 0 ... PSG (checkbox and radiobuttons) - Copy.py | 49 ++++++ .../MacOS versions/2b. PSG (Add logo).py | 42 +++++ .../3 PSG (multiline display).py | 46 ++++++ .../4a PSG (Sliders and combo).py | 55 +++++++ .../4b PSG (Spinner and combo) .py | 43 +++++ .../5a PSG (listboxes add remove).py | 51 ++++++ .../6a PSG (search linear and binary).py | 90 +++++++++++ .../6b PSG (search - disabled buttons).py | 98 ++++++++++++ .../6c PSG (search text preloaded).py | 79 ++++++++++ .../6d PSG (sort and search with textbox.py | 139 ++++++++++++++++ .../6e PSG (sort and search with listbox).py | 137 ++++++++++++++++ .../6f PSG (data from text file).py | 148 ++++++++++++++++++ ...ta entry calc using file save retrieve).py | 67 ++++++++ .../7b PSG (add validation and error trap).py | 72 +++++++++ ...et pathname to save and retrieve files).py | 80 ++++++++++ .../8a PSG (Data to plot from csv file).py | 40 +++++ .../8b PSG (Tables and calc from csv file).py | 32 ++-- .../8c PSG (Tables - add sort).py | 77 +++++++++ .../8d PSG (Tables - add logo).py | 71 +++++++++ .../9a PSG Windows(location hide).py | 52 ++++++ .../MacOS versions/9b PSG Tabs example.py | 22 +++ .../9c PSG Tabs example plus.py | 89 +++++++++++ .../{ => MacOS versions}/AFL.png | Bin .../AFL2018 (sorted alpha teams).csv | 0 .../AFL2018 (sorted pts and %).csv | 0 .../{ => MacOS versions}/Gym_Logo.png | Bin .../{ => MacOS versions}/Names(sorted).txt | 0 .../{ => MacOS versions}/Names.txt | 0 .../MacOS versions/Test.txt | 3 + .../MacOS versions/TonyCrewe2.txt | 3 + .../{ => MacOS versions}/default_icon.ico | Bin .../MacOS versions/results.txt | 3 + .../{ => MacOS versions}/weight 2018.csv | 0 ProgrammingClassExamples/Tony.txt | 3 - ...Plot (Matplotlib numpy pyplot(y=sinx)) .py | 0 .../10b PSG Plot (axes moved).py | 0 .../10c PSG Plot (axes pi format).py | 0 ...0d PSG (Plots Tabs and sin cos options).py | 0 .../10e PSG (Same Window).py | 0 .../10f PSG (linear and quadratics).py | 16 +- .../1a PSG (Entry and PopUp).py | 5 +- .../{ => Win10 versions}/1b PSG (Format).py | 4 +- .../1c PSG (persistent form and bind key).py | 0 ...PSG (named input keys and catch errors).py | 0 .../1e PSG (validation and Look and Feel).py | 34 ++++ ... PSG (checkbox and radiobuttons) - Copy.py | 0 .../2b. PSG (Add logo).py | 2 +- .../2b_makewinexe_file.py | 0 .../3 PSG (multiline display).py | 0 .../4a PSG (Sliders and combo).py | 0 .../4b PSG (Spinner and combo) .py | 0 .../5a PSG (listboxes add remove).py | 0 .../6a PSG (search linear and binary).py | 0 .../6b PSG (search - disabled buttons).py | 0 .../6c PSG (search text preloaded).py | 3 - .../6d PSG (sort and search with textbox.py | 0 .../6e PSG (sort and search with listbox).py | 0 .../6f PSG (data from text file).py | 13 +- ...ta entry calc using file save retrieve).py | 2 +- .../7b PSG (add validation and error trap).py | 2 +- ...t pathname to save and retrieve files).py} | 2 +- .../8a PSG (Data to plot from csv file).py | 0 .../8b PSG (Tables and calc from csv file).py | 67 ++++++++ .../8c PSG (Tables - add sort).py | 14 +- .../8d PSG (Tables - add logo).py | 19 ++- .../9a PSG Windows(location hide).py | 0 .../9b PSG Tabs example.py | 4 + .../9c PSG Tabs example plus.py | 4 +- .../Win10 versions/AFL.png | Bin 0 -> 7100 bytes .../AFL2018 (sorted alpha teams).csv | 19 +++ .../AFL2018 (sorted pts and %).csv | 19 +++ .../Win10 versions/Gym_Logo.png | Bin 0 -> 14255 bytes .../Win10 versions/Names.txt | 10 ++ .../Win10 versions/default_icon.ico | Bin 0 -> 23462 bytes .../Win10 versions/weight 2018.csv | 98 ++++++++++++ ProgrammingClassExamples/results.txt | 3 - requirements.txt | 2 +- 93 files changed, 2579 insertions(+), 52 deletions(-) delete mode 100644 Colours.gif rename ButtonClick.wav => DemoPrograms/ButtonClick.wav (100%) rename Color-Guide.png => DemoPrograms/Color-Guide.png (100%) rename Color-names.png => DemoPrograms/Color-names.png (100%) create mode 100644 ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py create mode 100644 ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py create mode 100644 ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py create mode 100644 ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py create mode 100644 ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py create mode 100644 ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py create mode 100644 ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py create mode 100644 ProgrammingClassExamples/MacOS versions/1b PSG (Format).py create mode 100644 ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py create mode 100644 ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py create mode 100644 ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py rename ProgrammingClassExamples/{1e PSG (validation and Look and Feel).py => MacOS versions/1e PSG (validation).py} (100%) create mode 100644 ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py create mode 100644 ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py create mode 100644 ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py create mode 100644 ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py create mode 100644 ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py create mode 100644 ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py create mode 100644 ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py create mode 100644 ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py create mode 100644 ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py create mode 100644 ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py create mode 100644 ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py create mode 100644 ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py create mode 100644 ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py create mode 100644 ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py create mode 100644 ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py create mode 100644 ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py rename ProgrammingClassExamples/{ => MacOS versions}/8b PSG (Tables and calc from csv file).py (63%) create mode 100644 ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py create mode 100644 ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py create mode 100644 ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py create mode 100644 ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py create mode 100644 ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py rename ProgrammingClassExamples/{ => MacOS versions}/AFL.png (100%) rename ProgrammingClassExamples/{ => MacOS versions}/AFL2018 (sorted alpha teams).csv (100%) rename ProgrammingClassExamples/{ => MacOS versions}/AFL2018 (sorted pts and %).csv (100%) rename ProgrammingClassExamples/{ => MacOS versions}/Gym_Logo.png (100%) rename ProgrammingClassExamples/{ => MacOS versions}/Names(sorted).txt (100%) rename ProgrammingClassExamples/{ => MacOS versions}/Names.txt (100%) create mode 100644 ProgrammingClassExamples/MacOS versions/Test.txt create mode 100644 ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt rename ProgrammingClassExamples/{ => MacOS versions}/default_icon.ico (100%) create mode 100644 ProgrammingClassExamples/MacOS versions/results.txt rename ProgrammingClassExamples/{ => MacOS versions}/weight 2018.csv (100%) delete mode 100644 ProgrammingClassExamples/Tony.txt rename ProgrammingClassExamples/{ => Win10 versions}/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/10b PSG Plot (axes moved).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/10c PSG Plot (axes pi format).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/10d PSG (Plots Tabs and sin cos options).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/10e PSG (Same Window).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/10f PSG (linear and quadratics).py (89%) rename ProgrammingClassExamples/{ => Win10 versions}/1a PSG (Entry and PopUp).py (87%) rename ProgrammingClassExamples/{ => Win10 versions}/1b PSG (Format).py (90%) rename ProgrammingClassExamples/{ => Win10 versions}/1c PSG (persistent form and bind key).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/1d PSG (named input keys and catch errors).py (100%) create mode 100644 ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py rename ProgrammingClassExamples/{ => Win10 versions}/2a. PSG (checkbox and radiobuttons) - Copy.py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/2b. PSG (Add logo).py (94%) rename ProgrammingClassExamples/{ => Win10 versions}/2b_makewinexe_file.py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/3 PSG (multiline display).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/4a PSG (Sliders and combo).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/4b PSG (Spinner and combo) .py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/5a PSG (listboxes add remove).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/6a PSG (search linear and binary).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/6b PSG (search - disabled buttons).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/6c PSG (search text preloaded).py (94%) rename ProgrammingClassExamples/{ => Win10 versions}/6d PSG (sort and search with textbox.py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/6e PSG (sort and search with listbox).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/6f PSG (data from text file).py (88%) rename ProgrammingClassExamples/{ => Win10 versions}/7a PSG (Data entry calc using file save retrieve).py (96%) rename ProgrammingClassExamples/{ => Win10 versions}/7b PSG (add validation and error trap).py (97%) rename ProgrammingClassExamples/{7c PSG (add get pathname to save and retrieve files), - Copy.py => Win10 versions/7c PSG (add get pathname to save and retrieve files).py} (97%) rename ProgrammingClassExamples/{ => Win10 versions}/8a PSG (Data to plot from csv file).py (100%) create mode 100644 ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py rename ProgrammingClassExamples/{ => Win10 versions}/8c PSG (Tables - add sort).py (87%) rename ProgrammingClassExamples/{ => Win10 versions}/8d PSG (Tables - add logo).py (78%) rename ProgrammingClassExamples/{ => Win10 versions}/9a PSG Windows(location hide).py (100%) rename ProgrammingClassExamples/{ => Win10 versions}/9b PSG Tabs example.py (89%) rename ProgrammingClassExamples/{ => Win10 versions}/9c PSG Tabs example plus.py (96%) create mode 100644 ProgrammingClassExamples/Win10 versions/AFL.png create mode 100644 ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv create mode 100644 ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv create mode 100644 ProgrammingClassExamples/Win10 versions/Gym_Logo.png create mode 100644 ProgrammingClassExamples/Win10 versions/Names.txt create mode 100644 ProgrammingClassExamples/Win10 versions/default_icon.ico create mode 100644 ProgrammingClassExamples/Win10 versions/weight 2018.csv delete mode 100644 ProgrammingClassExamples/results.txt diff --git a/Colours.gif b/Colours.gif deleted file mode 100644 index e730fd303a68dcfa5842ec28b8150eb970bfaf59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41396 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 VE71}!5fd{}6E~3)H6kDY06Rea6Da@y diff --git a/ButtonClick.wav b/DemoPrograms/ButtonClick.wav similarity index 100% rename from ButtonClick.wav rename to DemoPrograms/ButtonClick.wav diff --git a/Color-Guide.png b/DemoPrograms/Color-Guide.png similarity index 100% rename from Color-Guide.png rename to DemoPrograms/Color-Guide.png diff --git a/Color-names.png b/DemoPrograms/Color-names.png similarity index 100% rename from Color-names.png rename to DemoPrograms/Color-names.png diff --git a/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py b/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py new file mode 100644 index 00000000..0343059c --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py @@ -0,0 +1,65 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. +Adapted: From https://gitlab.com/lotspaih/PySimpleGUI/tree/master + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) +""" + +#No exactly sure how all this works, but taken from example given as a template. +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code ---------------------- +#see https://matplotlib.org/ +fig = plt.figure() +ax = fig.add_subplot(111) +#x-values +x = np.linspace(-np.pi*2, np.pi*2, 100) +#y-values +y = np.sin(x) +plt.plot(x,y) + +ax.set_title('sin(x)') +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py b/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py new file mode 100644 index 00000000..f20bce43 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10b PSG Plot (axes moved).py @@ -0,0 +1,57 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- +fig=plt.figure() +ax = fig.add_subplot(111) +x = np.linspace(-np.pi*2, np.pi*2, 100) +y= np.sin(x) +plt.plot(x,y) + +ax.set_title('sin(x)') + +#centre bottom and left axes to zero + +ax.spines['left'].set_position('zero') +ax.spines['right'].set_color('none') +ax.spines['bottom'].set_position('zero') +ax.spines['top'].set_color('none') + +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes centred)', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py b/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py new file mode 100644 index 00000000..721ffbad --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10c PSG Plot (axes pi format).py @@ -0,0 +1,73 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + + + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. + +Basic steps are: + * Create a Canvas Element + * Layout form + * Display form (NON BLOCKING) + * Draw plots onto convas + * Display form (BLOCKING) +""" + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- +fig=plt.figure() +ax = fig.add_subplot(111) +x = np.linspace(-np.pi*2, np.pi*2, 100) +y= np.sin(x) +plt.plot(x/np.pi,y) + +ax.set_title('sin(x)') +#centre bottom and left axes to zero + +ax.spines['left'].set_position('zero') +ax.spines['right'].set_color('none') +ax.spines['bottom'].set_position('zero') +ax.spines['top'].set_color('none') + +#Format axes - nicer eh! +ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +#------------End Matplotlib code -------------------- + +layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib (axes pi format)', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +window = sg.Window('Matplot in PySimpleGUI', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +button, value = window.Read() + + diff --git a/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py b/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py new file mode 100644 index 00000000..203c3281 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10d PSG (Plots Tabs and sin cos options).py @@ -0,0 +1,100 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 14, 'bold'), + text_color = 'DarkBlue', + input_text_color ='DarkBlue', + button_color = ('DarkBlue', 'White')) + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(amp, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-np.pi*2, np.pi*2, 100) + if function == 'sine': + y= amp*np.sin(x) + ax.set_title('sin(x)') + else: + y=amp*np.cos(x) + ax.set_title('cos(x)') + plt.plot(x/np.pi,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + #Format axes - nicer eh! + ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'sine' +set_plot(amp, function) + +#------------End Matplotlib code -------------------- + +#use Tabs - one for options, one for canvas to be displayed +#set spinner for amplitude and combo for function type + +tab1_layout = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))], + [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'), + sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'), + sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))], + [sg.ReadButton('Redraw Plot')], + [sg.Text('', size = (2, 25))]] + +tab2_layout = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +layout = [[sg.TabGroup([[sg.Tab('Select options', tab1_layout), sg.Tab('Display Plot', tab2_layout)]])]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + amp = int(value['_spin_']) + function = value['_function_'] + set_plot(amp,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py b/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py new file mode 100644 index 00000000..041bfe54 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10e PSG (Same Window).py @@ -0,0 +1,98 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 14, 'bold'), + text_color = 'DarkBlue', + input_text_color ='DarkBlue', + button_color = ('DarkBlue', 'White')) + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(amp, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-np.pi*2, np.pi*2, 100) + if function == 'sine': + y= amp*np.sin(x) + ax.set_title('sin(x)') + else: + y=amp*np.cos(x) + ax.set_title('cos(x)') + plt.plot(x/np.pi,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + #Format axes - nicer eh! + ax.xaxis.set_major_formatter(ticker.FormatStrFormatter('%g $\pi$')) + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'sine' +set_plot(amp, function) + +#------------End Matplotlib code -------------------- + +#using one window based on two columns instead of Tabs +column1 = [[sg.Text('Select Amplitude and trig function type', font = ('Calibri', 18, 'bold'))], + [sg.Spin([sz for sz in range (1,5)], initial_value =1, size = (2,1), key = '_spin_'), + sg.Text('Amplitude', size = (10, 1), font = ('Calibri', 12, 'bold'))], + [sg.InputCombo(['sine', 'cosine'], size = (8, 4), key = '_function_'), + sg.Text('Function', size = (10, 1),font = ('Calibri', 12, 'bold'))], + [sg.ReadButton('Redraw Plot')], + [sg.Text('', size = (1, 27))]] + +column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options', font = ('Calibri', 18, 'bold'))], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(6, 2))]] + +layout = [[sg.Column(column1), sg.Column(column2)]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + amp = int(value['_spin_']) + function = value['_function_'] + set_plot(amp,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py b/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py new file mode 100644 index 00000000..580fa88f --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/10f PSG (linear and quadratics).py @@ -0,0 +1,121 @@ +#matplotlib, numpy, pyplot +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import matplotlib +# added this to work with MacOs +matplotlib.use('TkAgg') +import matplotlib.pyplot as plt +import matplotlib.ticker as ticker +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import numpy as np +import tkinter as tk + +sg.SetOptions (background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font = ('Arial', 14, 'bold'), + text_color = 'Black', + input_text_color ='Black', + button_color = ('Black', 'White')) + +#sg.ChangeLookAndFeel('Black') + +def draw_figure(canvas, figure, loc = (0,0)): + + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + + +#------------ Matplotlib code -------------------- + +def set_plot(a,b,c, function): + global figure_w, figure_h, fig + fig=plt.figure() + ax = fig.add_subplot(111) + x = np.linspace(-10, 10, 100) + if function == 'y = ax + b': + y= a*x + b + if a == 1: + a = '' + if a == -1: + a = '-' + title = str('y = ') + str(a) + 'x + ' + str(b) + ax.set_title(title) + else: + y = a*x**2 + b*x + c + #avoiding getting -1x or -1x**2 instead of -x for title + if a == 1: + a = '' + if a == -1: + a = '-' + if b == 1: + b = '' + if b == -1: + b = '-' + title = str('y = ') + str(a) + 'x**2 + ' + str(b) + 'x + ' + str(c) + ax.set_title(title) + plt.plot(x,y) + + + #centre bottom and left axes to zero + + ax.spines['left'].set_position('zero') + ax.spines['right'].set_color('none') + ax.spines['bottom'].set_position('zero') + ax.spines['top'].set_color('none') + + + figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +amp = 1 +function = 'y = ax + b' +set_plot(1,1,1, function) + +#------------End Matplotlib code -------------------- + +#column 1 for function type and constant values ... + +column1 = [ + [sg.Text('Select constants & function type', )], + [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (16, 4), key = '_function_'), + sg.Text('Function', size = (10, 1))], [sg.Text('', size = (1, 2))], + [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_a_'), + sg.Text('a', size = (3, 1)), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_b_'), + sg.Text('b', size = (3, 1)), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_c_'), + sg.Text('c', size = (3, 1))], [sg.Text('', size = (1, 1))], + [sg.ReadButton('Redraw Plot', size = (14,1))], + [sg.Text('', size = (1, 14))]] + +column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options')], + [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], + [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1))]] + +layout = [[sg.Column(column1), sg.Column(column2)]] +window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() + +fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + +while True: + button, value = window.Read() + if button == 'Redraw Plot': + a = int(value['_a_']) + b = int(value['_b_']) + c = int(value['_c_']) + function = value['_function_'] + set_plot(a,b,c,function) + fig_photo = draw_figure(window.FindElement('_canvas_').TKCanvas, fig) + + if button is None: + break + + diff --git a/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py b/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py new file mode 100644 index 00000000..86ecab1c --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1a PSG (Entry and PopUp).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#layout, Text, Input,button on line below +layout = [ + [sg.Text('Celcius'), sg.InputText()], + [sg.Submit()], + ] + +#setup window with Title +window = sg.Window('Temperature Converter').Layout(layout) + +#get value (part of a list) +button, value = window.Read() +if button is None: + #windows was closed without button being pressed + exit(0) + +#convert and create string +fahrenheit = round(9/5*float(value[0]) +32, 1) +result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) +#display in Popup +sg.Popup('Result', result) + + + + + + + + + + diff --git a/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py b/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py new file mode 100644 index 00000000..34670547 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1b PSG (Format).py @@ -0,0 +1,41 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#Set formatting options for all elements rather than individually. +#MacOs - colour background issue buttons - make text LightBlue + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 10, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) +#adjust widths +layout = [ + [sg.Text('Celcius', size =(12,1)), sg.InputText(size = (8,1))], + [sg.Submit()] + ] + +window = sg.Window('Converter').Layout(layout) +button, value = window.Read() +if button is None: + #windows was closed without button being pressed + exit(0) +fahrenheit = round(9/5*float(value[0]) +32, 1) +result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) +sg.Popup('Result',result) + + + + + + + + + + diff --git a/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py b/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py new file mode 100644 index 00000000..e686da7f --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1c PSG (persistent form and bind key).py @@ -0,0 +1,35 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 12, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) +#update (via list) values and and display answers +#value[0] is celcius input, value[1] is input to place result. +#Use ReadButton with while true: - keeps window open. + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1))], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1))], + [sg.ReadButton('Submit', bind_return_key = True)]] +#Return = button press +window = sg.Window('Converter').Layout(layout) + +while True: + #get result + button, value = window.Read() + #break out of loop is button not pressed. + if button is not None: + fahrenheit = round(9/5*float(value[0]) +32, 1) + #put result in 2nd input box + window.FindElement(1).Update(fahrenheit) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py b/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py new file mode 100644 index 00000000..88c567ba --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1d PSG (named input keys and catch errors).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 12, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) +#name inputs (key) uses dictionary- easy to see updating of results +#value[input] first input value te c... +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.FlexForm('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text or blank entry: + try: + fahrenheit = round(9/5*float(value['_input_']) +32, 1) + #put result in text box + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py new file mode 100644 index 00000000..c31194ae --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/1e PSG (validation and Look and Feel).py @@ -0,0 +1,36 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg + +#Can use a variety of themes - plus individual options +#Not on MacOS +#sg.ChangeLookAndFeel('SandyBeach') +#use set Options see previous +sg.SetOptions (font = ('Calbri', 12, 'bold')) + + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (6,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (6,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.Window('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text, floats or blank entry: + #Also validation for range [0, 50] + try: + if float(value['_input_']) > 50 or float(value['_input_']) <0: + sg.Popup('Error','Out of range') + else: + fahrenheit = round(9/5*int(value['_input_']) +32, 1) + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/MacOS versions/1e PSG (validation).py similarity index 100% rename from ProgrammingClassExamples/1e PSG (validation and Look and Feel).py rename to ProgrammingClassExamples/MacOS versions/1e PSG (validation).py diff --git a/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py b/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py new file mode 100644 index 00000000..189959b4 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/2a. PSG (checkbox and radiobuttons) - Copy.py @@ -0,0 +1,49 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#Set colour scheme and font +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions (background_color = 'LightPink', + element_background_color = 'LightPink', + text_element_background_color = 'LightPink', + font = ('Arial', 14, 'bold'), + text_color = 'Green', + input_text_color ='Green', + button_color = ('Green', 'White')) + +#One checkbox and three radio buttons (grouped as 'Radio1') +#value[0] - checkbox, Value[1-3] radiobutton selection +layout = [[sg.Text('Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox(' Student? 10% off', size = (25,1)), + sg.ReadButton('Display Cost', size = (14,1))], + [sg.Radio('1 month $50', 'Radio1', default = True), + sg.Radio('3 months $100', 'Radio1'), + sg.Radio('1 year $300', 'Radio1')], + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +window = sg.Window('Gym Membership').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + #apply discount + cost = cost*0.9 + + #format as currency $ symbol and 2 d.p. - make a string + result = str(' Cost: ' + '${:.2f}'.format(cost)) + #put the result in Textbox + window.FindElement('result').Update(result) + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py b/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py new file mode 100644 index 00000000..aa4d1038 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/2b. PSG (Add logo).py @@ -0,0 +1,42 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg +import os + +sg.SetOptions (font =('Calibri',12,'bold')) + +#get pathname to current file +dirname, filename = os.path.split(os.path.abspath(__file__)) +#add file name for image +pathname = os.path.join(dirname ,'Gym_Logo.png') + +layout = [[sg.Image(pathname),sg.Text(' Membership Calculator', font = ('Calibri', 16, 'bold'))], + [sg.Checkbox(' Student? 10% off', size = (25,1)), + sg.ReadButton('Display Cost', size = (14,1),button_color = ('Red', 'White'))], + [sg.Radio('1 month $50', 'Radio1', default = True), + sg.Radio('3 months $100', 'Radio1'), + sg.Radio('1 year $300', 'Radio1')], + [sg.Text('', size = (30,1), justification = 'center', font =('Calibri', 16, 'bold'), key = 'result')]] + +window = sg.Window('Gym Membership').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + if value[1]: + cost = 50 + elif value[2]: + cost = 100 + else: + cost = 300 + if value[0]: + cost = cost*0.9 + + #format as currency $ symbol and 2 d.p. - make a string + result = str(' Cost: ' + '${:.2f}'.format(cost)) + window.FindElement('result').Update(result) + + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py b/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py new file mode 100644 index 00000000..d1348a91 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/3 PSG (multiline display).py @@ -0,0 +1,46 @@ + +#PySimple examples (v 3.8) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions (background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font = ('Courier New', 12, 'bold'), + text_color = 'White', + input_text_color ='White', + button_color = ('Grey', 'White')) + + +layout = [ + [sg.Text('Enter and Add Data to Display', font = ('Calibri', 16,'bold'))], + [sg.Text('Race:', size = (5,1)), sg.InputText(size = (8,1)), + sg.Text('Club:', size = (5,1)), sg.InputText(size = (8,1))], + [sg.Text('Name:', size = (5,1)), sg.InputText(size = (8,1)), + sg.Text('Time:', size = (5,1)), sg.InputText(size = (8,1)),sg.Text(' '), + sg.ReadButton('Add Data', font = ('Calibri', 12, 'bold'))], + [sg.Text('_'*40)], + [sg.Text(' Race Club Name Time')], + [sg.Multiline(size =(44,6),key = '_multiline_')] + ] + +window = sg.Window('Enter & Display Data').Layout(layout) + +string = '' +S=[] +while True: + + button, value = window.Read() + if button is not None: + #use string formatting - best way? plus Courier New font - non-proportional font + S = S + ['{:^9s}{:<11s}{:<10s}{:>8s}'.format(value[0],value[1],value[2],value[3])] + for s in S: + string = string + s + '\n' + window.FindElement('_multiline_').Update(string) + string ='' + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py b/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py new file mode 100644 index 00000000..77258ca8 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/4a PSG (Sliders and combo).py @@ -0,0 +1,55 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions (background_color = 'LightPink', + element_background_color = 'LightPink', + text_element_background_color = 'LightPink', + font = ('Calibri', 14, 'bold'), + text_color = 'Black', + input_text_color ='Black', + button_color = ('Black', 'White')) +#use of Column to help with layout - vertical sliders take up space + +column1 = [ + [sg.Text('Pick operation', size = (15,1), font = ('Calibri', 16, 'bold'))], + [sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (10,8))], + [sg.Text('', size =(1,4))]] +column2 = [ + [sg.ReadButton('Submit', font = ('Calibri', 16, 'bold'), size = (8, 1))], + [sg.Text('Result:', font = ('Calibri', 16, 'bold'))],[sg.InputText(size = (12,1), key = '_result_')] + ] + + +layout = [ + [sg.Text('Slider and Combo box demo', font = ('Calibri', 16,'bold'))], + [sg.Slider(range = (-9, 9),orientation = 'v', size = (5,20), default_value = 0), + sg.Slider(range = (-9, 9),orientation = 'v', size = (5, 20), default_value = 0), + sg.Text(' '), sg.Column(column1), sg.Column(column2)]] + +#added grab_anywhere to when moving slider, who window doesn't move. + +window = sg.Window('Enter & Display Data',grab_anywhere = False).Layout(layout) + +#Get selection from combo: value[2] +#Slider values: value[0] and value[1] +while True: + button, value = window.Read() + if button is not None: + if value[2] == 'Add': + result = value[0] + value[1] + elif value[2] == 'Multiply': + result = value[0] * value[1] + elif value[2] == 'Subtract': + result = value[0] - value[1] + elif value[2] == 'Divide': #check for zero + if value[1] ==0: + sg.Popup('Second value can\'t be zero') + result = 'NA' + else: + result = value[0] / value[1] + window.FindElement('_result_').Update(result) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py b/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py new file mode 100644 index 00000000..8d696c31 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/4b PSG (Spinner and combo) .py @@ -0,0 +1,43 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'LightGreen', + element_background_color = 'LightGreen', + text_element_background_color = 'LightGreen', + font= ('Calibri', 12, 'bold')) + +layout = [ + [sg.Text('Spinner and Combo box demo', font = ('Calibri', 14, 'bold'))], + [sg.Spin([sz for sz in range (-9,10)], size = (2,1),initial_value = 0), + sg.Spin([sz for sz in range (-9,10)], size = (2,1), initial_value = 0), + sg.Text('Pick operation ->', size = (15,1)), + sg.InputCombo(['Add','Subtract','Multiply','Divide'], size = (8,6))], + [sg.Text('Result: ')],[sg.InputText(size = (5,1), key = '_result_'), + sg.ReadButton('Calculate', button_color = ('Black', 'White'))]] + +window = sg.Window('Enter & Display Data', grab_anywhere= False).Layout(layout) + +while True: + button, value = window.Read() + + if button is not None: + #convert returned values to integers + val = [int(value[0]), int(value[1])] + if value[2] == 'Add': + result = val[0] + val[1] + elif value[2] == 'Multiply': + result = val[0] * val[1] + elif value[2] == 'Subtract': + result = val[0] - val[1] + elif value[2] == 'Divide': + if val[1] ==0: + sg.Popup('Second value can\'t be zero') + result = 'NA' + else: + result = round( val[0] / val[1], 3) + window.FindElement('_result_').Update(result) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py b/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py new file mode 100644 index 00000000..293b6929 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/5a PSG (listboxes add remove).py @@ -0,0 +1,51 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +#sg.ChangeLookAndFeel('BlueMono') +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Calibri', 14, 'bold'), + text_color = 'Black', + input_text_color ='Black', + button_color = ('Black', 'White')) + +#use column feature with height listbox takes up +column1 = [ + [sg.Text('Add or Delete Items\nfrom a Listbox')], + [sg.InputText( size = (15,1), key = 'add'), sg.ReadButton('Add', size = (5,1))], + [sg.ReadButton('Delete selected entry', size = (18,1))]] + +#initial listbox entries +List = ['Austalia', 'Canada', 'Greece'] + +#add initial List to listbox +layout = [ + [sg.Listbox(values=[l for l in List], size = (20,8), key ='_listbox_'), + sg.Column(column1)]] + +window = sg.Window('Listbox').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #value[listbox] returns a list + #using value[listbox][0] gives the string + if button == 'Delete selected entry': + #ensure something is selected + if value['_listbox_'] == []: + sg.Popup('Error','You must select a Country') + else: + #find and remove this + List.remove(value['_listbox_'][0]) + if button == 'Add': + #add string in add box to list + List.append(value['add']) + List.sort() + #update listbox + window.FindElement('_listbox_').Update(List) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py b/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py new file mode 100644 index 00000000..45bf802a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6a PSG (search linear and binary).py @@ -0,0 +1,90 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + + +sg.SetOptions(background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font= ('Calibri', 14, 'bold')) + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.ReadButton('Binary Search', size = (11,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#names for Demo, could be loaded from a file +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +#function to display list +def display_list(list, display): + names = '' + for l in list: #add list elements with new line + names = names + l + '\n' + window.FindElement(display).Update(names) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: #Check each value + found = True + window.FindElement('_display1_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + #Start with found is False + found = False + while lo <= hi: + #Start in middle + mid = (lo + hi) //2 + #get the value from the search box + if l[mid] == value['_binary_']: + window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.') + #If found display name and stop + found = True + break + elif l[mid] < value['_binary_']: + #Search in top half + lo = mid + 1 + else: + #Search in lower half + hi = mid - 1 + #If we get to end - display not found + if not found: + window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found') + +while True: + button, value = window.Read() + + if button is not None: + #show names - unordered and sorted + if button == 'Show Names': + display_list(names,'_display1_') + display_list(sorted_names, '_display2_') + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py b/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py new file mode 100644 index 00000000..8c917166 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6b PSG (search - disabled buttons).py @@ -0,0 +1,98 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold')), sg.ReadButton('Show Names')], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', key = '_ls_',size = (11,1)), sg.ReadButton('Binary Search', key ='_bs_',size = (11,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#finalize allows the disabling of the two buttons before .Read statement +window.Finalize() +window.FindElement('_ls_').Update(disabled = True) +window.FindElement('_bs_').Update(disabled = True) + +#names for Demo, could be loaded from a file +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +#function to display list +def display_list(list, display): + names = '' + #add list elements with new line + for l in list: + names = names + l + '\n' + window.FindElement(display).Update(names) + #enable buttons now data loaded + window.FindElement('_ls_').Update(disabled = False) + window.FindElement('_bs_').Update(disabled = False) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + #Check each value + if l == value['_linear_']: + found = True + window.FindElement('_display1_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display1_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + #Start with found is Flase + found = False + while lo <= hi: + #Start in middle + mid = (lo + hi) //2 + #get the value from the search box + if l[mid] == value['_binary_']: + window.FindElement('_display2_').Update('Binary search\n' + l[mid] + ' found.') + #If found display and stop + found = True + break + elif l[mid] < value['_binary_']: + #Search in top half + lo = mid + 1 + else: + #Search in lower half + hi = mid - 1 + #If we get to end - display not found + if not found: + window.FindElement('_display2_').Update(value['_binary_'] + ' was \nNot found') + +while True: + button, value = window.Read() + if button is not None: + #show names - unordered and sorted + if button == 'Show Names': + display_list(names,'_display1_') + display_list(sorted_names, '_display2_') + if button == '_ls_': + linear_search() + if button == '_bs_': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py b/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py new file mode 100644 index 00000000..65b3c3b4 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6c PSG (search text preloaded).py @@ -0,0 +1,79 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'Grey', + element_background_color = 'Grey', + text_element_background_color = 'Grey', + font= ('Calibri', 14, 'bold')) + +#names for Demo, could be loaded from a file + +names = ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] +name = '' +for l in names: + name = name + l + '\n' + +sorted_names = ['Andrea','Belinda','Deborah','Helen', + 'Jenny','Kylie','Meredith','Pauline', + 'Roberta','Wendy'] + +sortname = '' +for l in sorted_names: + sortname = sortname + l +'\n' + +layout =[[sg.Text('Search Demo', font =('Calibri', 18, 'bold'))], +[sg.Text(name,size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display1_'), + sg.Text(sortname,size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.ReadButton('Binary Search', size = (11,1))], + ] +window = sg.Window('Search Demo').Layout(layout) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + sg.Popup('Linear search\n' + l + ' found.') + break + if not found: + sg.Popup('Linear search\n' +(value['_linear_'] + ' was not found')) + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + sg.Popup('Binary search\n' + l[mid] + ' found.') + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + sg.Popup('Binary search\n' +(value['_binary_'] + ' was not found')) + +while True: + button, value = window.Read() + + if button is not None: + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py b/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py new file mode 100644 index 00000000..ea354d90 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6d PSG (sort and search with textbox.py @@ -0,0 +1,139 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOS + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +#setup column (called column1) of buttons to use in layout + +column1 = [[sg.ReadButton('Original list', size = (11,1))], + [sg.ReadButton('Default sort', size = (11,1))], + [sg.ReadButton('Sort: selection',size = (11,1))], + [sg.ReadButton('Sort: quick', size = (11,1))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Text('',size = (14, 11),relief=sg.RELIEF_SOLID,font = ('Calibri', 12), background_color = 'White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*35,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +#names for Demo, could be loaded from a file +names= ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +#function to display list +def display_list(list): + #store list in Multiline text globally + global list_displayed + list_displayed = list + display = '' + #add list elements with new line + for l in list: + display = display + l + '\n' + window.FindElement('_display_').Update(display) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort - See Janson Ch 7 +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + #find smallest value + if l[j] < l[smallest]: + #swap it to front + smallest = j + #repeat from next position + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort - See Janson Ch 7 +def qsort_holder(names): + l = names[:] + #pass List, first and last + quick_sort(l, 0, len(l) -1) + display_list(l) +#Quicksort is a partition sort +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + #continue splitting - sort small list + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + window.FindElement('_display_').Update('Linear search\n' + l + ' found.') + break + if not found: + window.FindElement('_display_').Update(value['_linear_'] + ' was \nNot found') + +#Binary Search - only works for ordered lists +def binary_search(): + l= list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + window.FindElement('_display_').Update('Binary search\n' + l[mid] + ' found.') + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + window.FindElement('_display_').Update(value['_binary_'] + ' was \nNot found') + + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py b/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py new file mode 100644 index 00000000..b39be3bb --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6e PSG (sort and search with listbox).py @@ -0,0 +1,137 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +sg.SetOptions(background_color = 'DarkGrey', + element_background_color = 'DarkGrey', + text_element_background_color = 'DarkGrey', + font= ('Calibri', 14, 'bold')) + +#setup column (called column1) of buttons to use in layout + +column1 = [[sg.ReadButton('Original list', size = (10,1))], + [sg.ReadButton('Default sort', size = (10,1))], + [sg.ReadButton('Sort: selection',size = (10,1))], + [sg.ReadButton('Sort: quick', size = (10,1))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*38,font = ('Calibri', 16))], + [sg.InputText(size = (10,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (11,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +names= ['Roberta', 'Kylie', 'Jenny', 'Helen', + 'Andrea', 'Meredith','Deborah','Pauline', + 'Belinda', 'Wendy'] + +#function to display list +def display_list(list): + global list_displayed + #store list in Multiline text globally + list_displayed = list + #add list elements with new line + values = [l for l in list] + window.FindElement('_display_').Update(values) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + if l[j] < l[smallest]: + smallest = j + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort +def qsort_holder(names): + l = names[:] + quick_sort(l, 0, len(l) - 1) + display_list(l) + +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + #Create list for display + result = ['Linear search', l + ' found'] + window.FindElement('_display_').Update(result) + break + if not found: + #Create list for display + result = [value['_linear_'], 'was not found'] + window.FindElement('_display_').Update(result) + +#Binary Search +def binary_search(): + l = list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + #Create list for display + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display_').Update(result) + found = True + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + #Create list for display + result = [value['_binary_'], 'was not found'] + window.FindElement('_display_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py b/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py new file mode 100644 index 00000000..76118d8b --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/6f PSG (data from text file).py @@ -0,0 +1,148 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +#get pathname to current file + +dirname, filename = os.path.split(os.path.abspath(__file__)) +pathname = os.path.join(dirname, 'Names.txt') #original data +spathname = os.path.join(dirname, 'Names(sorted).txt') #sorted data + +#Get data from file +names = [line.strip() for line in open(pathname)] + +column1 = [[sg.ReadButton('Original list', size = (11,1))], + [sg.ReadButton('Default sort', size = (11,1))], + [sg.ReadButton('Sort: selection',size = (11,1))], + [sg.ReadButton('Sort: quick', size = (11,1))], + [sg.Text('_________________',font = ('Calibri', 16))], + [sg.ReadButton('Save data\ndisplayed', size = (11,2))]] + +layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], +[sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], + [sg.Text('_'*38,font = ('Calibri', 16))], + [sg.InputText(size = (11,1), key = '_linear_'), sg.Text(' '), sg.InputText(size = (11,1), key = '_binary_')], + [sg.ReadButton('Linear Search', size = (12,1)), sg.Text(' '), sg.ReadButton('Binary Search', size = (11,1))], + ] + +window = sg.Window('Search and Sort Demo').Layout(layout) + +#function to display list +def display_list(list): + global list_displayed + #store list in Multiline text globally + list_displayed = list + #add list elements with new line + values = [l for l in list] + window.FindElement('_display_').Update(values) + +#use inbuilt python sort +def default(names): + l = names[:] + l.sort() + display_list(l) + +#Selection sort +def sel_sort(names): + l = names[:] + for i in range(len(l)): + smallest = i + for j in range(i+1, len(l)): + if l[j] < l[smallest]: + smallest = j + l[smallest], l[i] = l[i], l[smallest] + display_list(l) + +#Quick sort +def qsort_holder(names): + l = names[:] + quick_sort(l, 0, len(l) - 1) + display_list(l) + +def quick_sort(l, first, last): + if first >= last: + return l + pivot = l[first] + low = first + high = last + while low < high: + while l[high] > pivot: + high = high -1 + while l[low] < pivot: + low = low + 1 + if low <= high: + l[high], l[low] = l[low], l[high] + low = low + 1 + high = high -1 + quick_sort(l, first, low -1) + quick_sort(l, low, last) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: + found = True + #Create list for display + result = ['Linear search', l + ' found'] + window.FindElement('_display_').Update(result) + break + if not found: + #Create list for display + result = [value['_linear_'], 'was not found'] + window.FindElement('_display_').Update(result) + +#Binary Search +def binary_search(): + l = list_displayed[:] + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + #Create list for display + found = True + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display_').Update(result) + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + #Create list for display + result = [value['_binary_'], 'was not found'] + window.FindElement('_display_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Original list': + display_list(names) + if button == 'Default sort': + default(names) + if button == 'Sort: selection': + sel_sort(names) + if button == 'Sort: quick': + qsort_holder(names) + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + if button == 'Save data\ndisplayed': + f = open(spathname, 'w') + for name in list_displayed: + print (name, file = f) + f.close() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py b/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py new file mode 100644 index 00000000..e7ba2386 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/7a PSG (Data entry calc using file save retrieve).py @@ -0,0 +1,67 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')], + [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')], + [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')], + [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')], + [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')], + [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt' ) + + #needs validation and try/catch error checking, will crash if blank or text entry for marks + + if button == '_save_': + #create dictionary index _m1_ ... _m4_ + for i in range (1,5): + index = '_m' + str(i) + '_' + total += float(value[index]) + average = total/4 + #open file and save + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + + #some error checking for missing file needed here + + if button == '_display_': + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py b/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py new file mode 100644 index 00000000..412bbb64 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/7b PSG (add validation and error trap).py @@ -0,0 +1,72 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os #to work with windows OS + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')], + [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')], + [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')], + [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')], + [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')], + [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt' ) + #generic catch error - blanks or wrong data types + try: + if button == '_save_': + for i in range (1,5): + index = '_m' + str(i) + '_' + + #Check for values between 0 and 100 + if float(value[index]) < 0 or float(value[index]) >100: + sg.Popup('Out of Range', 'Enter Marks between 0 and 100') + else: + total += float(value[index]) + average = total/4 + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + except ValueError: + sg.Popup('Error','Check entries and try again') + + if button == '_display_': + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + try: + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + except: + sg.PopupError('Error', 'Problem finding or reading file') + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py b/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py new file mode 100644 index 00000000..b3d208a3 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/7c PSG (add get pathname to save and retrieve files).py @@ -0,0 +1,80 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os #to work with windows OS + +#sg.ChangeLookAndFeel('GreenTan') + +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font= ('Calibri', 14, 'bold')) + +layout = [ + [sg.Text('Enter a Name and four Marks')], + [sg.Text('Name:', size =(8,1)), sg.InputText(size = (10,1), key = '_name_')], + [sg.Text('Mark1:', size =(8,1)), sg.InputText(size = (5,1), key = '_m1_')], + [sg.Text('Mark2:', size =(8,1)), sg.InputText(size = (5,1), key = '_m2_')], + [sg.Text('Mark3:', size =(8,1)), sg.InputText(size = (5,1), key = '_m3_')], + [sg.Text('Mark4:', size =(8,1)), sg.InputText(size = (5,1), key = '_m4_')], + [sg.ReadButton('Save', size = (6,1),key = '_save_'), sg.Text('Press to Save to file')], + [sg.ReadButton('Display',size = (6,1), key = '_display_'), sg.Text('To retrieve and Display')], + [sg.Multiline(size = (24,4), key = '_multiline_', pad = (2,15))]] + +window = sg.Window('Simple Average Finder').Layout(layout) + + +while True: + button, value = window.Read() #value is a dictionary holding name and marks (4) + if button is not None: + #initialise variables + total = 0.0 + index = '' + name = value['_name_'] + #get pathname to current file + dirname, filename = os.path.split(os.path.abspath(__file__)) + #add desired file name for saving to path + pathname = os.path.join(dirname , 'results.txt') + #generic catch error - blanks or wrong data types + try: + if button == '_save_': + for i in range (1,5): + index = '_m' + str(i) + '_' + + #Check for values between 0 and 100 + if float(value[index]) < 0 or float(value[index]) >100: + sg.Popup('Out of Range', 'Enter Marks between 0 and 100') + else: + total += float(value[index]) + average = total/4 + #check location and file name for file, no_window so go straight to folder selection + + foldername = sg.PopupGetFolder('', no_window=True) + filename = sg.PopupGetFile('Please enter a file name for your results') + pathname = os.path.join(foldername ,filename + '.txt') + + f = open(pathname, 'w') + print (name, file = f) + print (total, file = f) + print (average, file = f) + f.close() + except ValueError: + sg.Popup('Error','Check entries and try again') + + if button == '_display_': + #get pathname: folder and file + pathname = sg.PopupGetFile('file to open', no_window=True, file_types=(("text files","*.txt"),)) + #This loads the file line by line into a list called data. + #the strip() removes whitespaces from beginning and end of each line. + try: + data = [line.strip() for line in open(pathname)] + #create single string to display in multiline object. + string = 'Name: ' + data[0] +'\nTotal: ' + str(data[1]) + '\nAverage: ' + str(data[2]) + window.FindElement('_multiline_').Update(string) + except: + sg.PopupError('Error', 'Problem finding or reading file') + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py b/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py new file mode 100644 index 00000000..c8b6b85c --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8a PSG (Data to plot from csv file).py @@ -0,0 +1,40 @@ +#matplotlib, pyplt and csv +#Tony Crewe +#Sep 2017 - updated Oct 2018 MacOs + +import matplotlib.pyplot as plt +import csv +from matplotlib.ticker import MaxNLocator + + +x=[] +y=[] + +with open('weight 2018.csv', 'r', encoding = 'utf-8-sig') as csvfile: + plots = csv.reader(csvfile) + for data in plots: + #get heading for x and y axes + var1 = (data[0]) + var2 = (data[1]) + break + for data in plots: + #get values - add to x list and y list + x.append(data[0]) + y.append(float(data[1])) + + +ax = plt.subplot(1,1,1) +ax.set_ylim([82, 96]) +ax.xaxis.set_major_locator(MaxNLocator(10)) +ax.spines['right'].set_color('none') +ax.spines['top'].set_color('none') + +plt.plot(x,y, label = 'data loaded\nfrom csv file') +plt.axhline(y = 85.5, color = 'orange', linestyle = '--', label = 'target') +plt.xlabel(var1) +plt.ylabel(var2) +plt.title('weight loss from\n first quarter 2018') + + +plt.legend() +plt.show() diff --git a/ProgrammingClassExamples/8b PSG (Tables and calc from csv file).py b/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py similarity index 63% rename from ProgrammingClassExamples/8b PSG (Tables and calc from csv file).py rename to ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py index 0fae40a4..174303cd 100644 --- a/ProgrammingClassExamples/8b PSG (Tables and calc from csv file).py +++ b/ProgrammingClassExamples/MacOS versions/8b PSG (Tables and calc from csv file).py @@ -1,7 +1,6 @@ - -#PySimple examples (v 3.8) +#PySimple examples (v 3.9.3) #Tony Crewe -#Sep 2018 +#Oct 2018 MacOs #Based of Example program from MikeTheWatchGuy #https://gitlab.com/lotspaih/PySimpleGUI @@ -9,7 +8,9 @@ import sys import PySimpleGUI as sg import csv -sg.ChangeLookAndFeel('BrownBlue') +#sg.ChangeLookAndFeel('BrownBlue') +sg.SetOptions(background_color = 'LightBlue', + element_background_color = 'LightBlue') def calc_ladder(): @@ -44,18 +45,25 @@ def calc_ladder(): #use Table (explore settings) and add to column layout - col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, - max_col_width = 12,justification='right', size=(None, len(data)))]] + # + #------ With MacOs -- manually adjust col_widths, auto to False ------------ + # + col_layout = [[sg.Table(values=data, headings=header,col_widths = (16, 4,4,4,4,6,6,7,4), auto_size_columns=False, + max_col_width = 30,justification='right', size=(None, len(data)))]] - layout = [[sg.Column(col_layout, size=(500,400), scrollable=True)],] + layout = [[sg.Column(col_layout, size=(520,360), scrollable=True)],] - window = sg.Window('Table', location = (700, 325), grab_anywhere=False).Layout(layout) + window = sg.Window('AFL Ladder',location = (500, 310), grab_anywhere = False).Layout(layout) b, v = window.Read() -slayout = [[sg.Text('Load AFL file to display results with points and percentage'),sg.ReadButton('Load File', size = (20,1))]] -swindow = sg.Window('Load File', location = (700,250)).Layout(slayout) +slayout = [[sg.Text('Load AFL file to display results with points and percentage', font = ('Arial', 14, 'bold')), + sg.ReadButton('Load File', font = ('Arial', 14, 'bold'), size = (15,1))]] +swindow = sg.Window('Load File', location = (500,250)).Layout(slayout) while True: button, value = swindow.Read() - if button == 'Load File': - calc_ladder() + if button is not None: + if button == 'Load File': + calc_ladder() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py b/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py new file mode 100644 index 00000000..4071b971 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8c PSG (Tables - add sort).py @@ -0,0 +1,77 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Oct 2018 MacOs + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +import operator + +#sg.ChangeLookAndFeel('Dark') +sg.SetOptions(background_color = 'LightGrey', + element_background_color = 'LightGrey') + +def table_example(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + #populate table with file contents + #Assume we know csv has heading in row 1 + #Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown + #data is a list of lists containing data about each team + #data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W, + #data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A + #no error checking or validation used. + + #initialise variables + data = [] + header_list = [] + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + header = next(reader) + data = list(reader) + header = header + ['%', 'Pts'] + for i in range (len(data)): + #calculate % + percent = int(data[i][5])/int(data[i][6])*100 + data[i] = data[i] + [percent] + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] + #sort data + #first by % + + data.sort(key = operator.itemgetter(7), reverse = True) + #then by pts + + data.sort(key = operator.itemgetter(8), reverse = True) + + #and format string to 2 decimal places + for i in range(len(data)): + data[i][7] = str('{:.2f}'.format(data[i][7])) + + #use Table (explore settings) and add to column layout + # + #------ With MacOs -- manually adjust col_widths, auto to False ------------ + # + col_layout = [[sg.Table(values=data, headings=header, col_widths = (16, 3,3,3,3,6,6,7,4), auto_size_columns=False, + max_col_width = 30,justification='right', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(480,360), scrollable=True)],] + + window = sg.Window('Ladder', location = (350, 310), grab_anywhere = False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Text(' Load AFL (csv) file to display sorted results.', font = ('Calibri', 16, 'bold')), + sg.ReadButton('Load File', font = ('Calibri', 16, 'bold'), button_color = ('Red', 'White'), size = (10,1))]] +swindow = sg.Window('Load File', location = (350,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + table_example() + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py b/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py new file mode 100644 index 00000000..c2fe109b --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/8d PSG (Tables - add logo).py @@ -0,0 +1,71 @@ +#PySimple examples (v 3.9.3) +#Tony Crewe +#Oct 2018 MacOs + +#Based of Example program from MikeTheWatchGuy +#https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv +import operator +import os + +sg.SetOptions(background_color = 'Black', + element_background_color = 'Black', + font = ('Calibri', 16, 'bold'), + text_color = 'White') + +#get pathname to current file and add file name for image +dirname, filename = os.path.split(os.path.abspath(__file__)) + +pathname = os.path.join(dirname , 'AFL.png' ) + +def table_example(): + + filename = sg.PopupGetFile('Get required file', no_window = True,file_types=(("CSV Files","*.csv"),)) + + + data = [] + header_list = [] + + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range (1): + header = next(reader) + data = list(reader) + header = header + ['%', 'Pts'] + for i in range (len(data)): + + percent = int(data[i][5])/int(data[i][6])*100 + data[i] = data[i] + [percent] + + pts = int(data[i][2])*4 + int(data[i][4])*2 + data[i] = data[i] + [pts] + + data.sort(key = operator.itemgetter(7), reverse = True) + data.sort(key = operator.itemgetter(8), reverse = True) + + for i in range(len(data)): + data[i][7] = str('{:.2f}'.format(data[i][7])) + + col_layout = [[sg.Table(values=data, headings=header, col_widths = (16, 3,3,3,3,6,6,6,4), auto_size_columns=False, + max_col_width = 30,justification='right', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(480,360), scrollable=True)],] + + window = sg.Window('Table', no_titlebar = False, location = (350, 318), grab_anywhere = False).Layout(layout) + b, v = window.Read() + +slayout = [[sg.Image(pathname),sg.Text(' Load AFL (csv) file to display results. '), + sg.ReadButton('Load File', size = (10,1))]] +swindow = sg.Window('Load File', location = (350,250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + table_example() + else: + break + diff --git a/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py b/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py new file mode 100644 index 00000000..312af3b4 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/9a PSG Windows(location hide).py @@ -0,0 +1,52 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Sep 2018 MacOs + +import PySimpleGUI as sg + +#sg.ChangeLookAndFeel('SandyBeach') +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 14, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White') + ) + +layout0 = [[sg.ReadButton('Show/Hide window1'),sg.ReadButton('Show/Hide window2')]] + +layout1 =[[ sg.Text('window1')], [sg.Multiline( size = (35, 10))]] +layout2 =[[ sg.Text('window2')], [sg.Multiline( size = (35, 10))]] +window0 = sg.Window('Home Window', location = (200, 140)).Layout(layout0) + +window1 = sg.Window('Window1', location = (200, 200)).Layout(layout1).Finalize() +window1.Hide() +w1 = False + +window2 = sg.Window('Window2', location = (600, 200)).Layout(layout2).Finalize() +window2.Hide() +w2 = False + +while True: + button, v = window0.Read() + if button is not None: + if button =='Show/Hide window1': + if w1 == True: + window1.Hide() + w1 = False + else: + window1.UnHide() + w1=True + if button =='Show/Hide window2': + if w2 == True: + window2.Hide() + w2 = False + else: + window2.UnHide() + w2=True + else: + break + + + diff --git a/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py b/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py new file mode 100644 index 00000000..7c4ec0f5 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/9b PSG Tabs example.py @@ -0,0 +1,22 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg + +tab1_layout = [[sg.Text('This is inside tab 1')]] + +tab2_layout = [[sg.Text('This is inside tab 2')]] + +layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), + sg.Tab('Tab 2', tab2_layout)]])], + [sg.ReadButton('Read')]] + +window = sg.Window('Main Window').Layout(layout) + +while True: + b, v = window.Read() + if b is not None: + print(b,v) + else: + break diff --git a/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py b/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py new file mode 100644 index 00000000..b69965e3 --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/9c PSG Tabs example plus.py @@ -0,0 +1,89 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 MacOs + +import PySimpleGUI as sg +import os + +#sg.ChangeLookAndFeel('BlueMono') +sg.SetOptions (background_color = 'LightBlue', + element_background_color = 'LightBlue', + text_element_background_color = 'LightBlue', + font = ('Arial', 12, 'bold'), + text_color = 'Blue', + input_text_color ='Blue', + button_color = ('Blue', 'White')) + +#get pathname to current file + +dirname, filename = os.path.split(os.path.abspath(__file__)) +pathname = os.path.join(dirname , 'Names.txt' ) + +#Get data from file +names = [line.strip() for line in open(pathname)] +sorted_names = names[:] +sorted_names.sort() + +tab1_layout =[[sg.Text('Linear Search Demo', font =('Calibri', 14, 'bold'))], + [sg.Listbox(values =[n for n in names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display1_')], + [sg.Text('_'*25,font = ('Calibri', 12))], + [sg.Text('Enter name to search for:',font = ('Calibri', 14, 'bold'))], + [sg.InputText(size = (15,1), key = '_linear_')], + [sg.ReadButton('Linear Search', font = ('Calibri', 14, 'bold'), size = (11,1))]] + +tab2_layout = [[sg.Text('Binary Search Demo', font =('Calibri', 14, 'bold'))], + [sg.Listbox(values =[n for n in sorted_names], size = (15, 12),font = ('Calibri', 12), background_color ='White',key = '_display2_')], + [sg.Text('_'*25,font = ('Calibri', 12))], + [sg.Text('Enter name to search for:',font = ('Calibri', 14, 'bold'))], + [sg.InputText(size = (15,1), key = '_binary_')], + [sg.ReadButton('Binary Search',font = ('Calibri', 14, 'bold'), size = (11,1))]] + +layout = [ + [sg.TabGroup([[sg.Tab('Linear Search', tab1_layout),sg.Tab('Binary Search', tab2_layout)]])]] + +window = sg.Window('Main Window').Layout(layout) + +#Linear Search - no need for Ordered list +def linear_search(): + l = names[:] + found = False + for l in l: + if l == value['_linear_']: #Check each value + found = True + result = ['Linear search', l + ' found'] + window.FindElement('_display1_').Update(result) + break + if not found: + result = [value['_linear_'], 'was not found'] + window.FindElement('_display1_').Update(result) + +#Binary Search - only works for ordered lists +def binary_search(): + l = sorted_names + lo = 0 + hi = len(l)-1 + found = False + while lo <= hi: + mid = (lo + hi) //2 + if l[mid] == value['_binary_']: + found = True + result = ['Binary search', l[mid] + ' found.'] + window.FindElement('_display2_').Update(result) + break + elif l[mid] < value['_binary_']: + lo = mid + 1 + else: + hi = mid - 1 + if not found: + result = [value['_binary_'], 'was not found'] + window.FindElement('_display2_').Update(result) + +while True: + button, value = window.Read() + if button is not None: + if button == 'Linear Search': + linear_search() + if button == 'Binary Search': + binary_search() + else: + break diff --git a/ProgrammingClassExamples/AFL.png b/ProgrammingClassExamples/MacOS versions/AFL.png similarity index 100% rename from ProgrammingClassExamples/AFL.png rename to ProgrammingClassExamples/MacOS versions/AFL.png diff --git a/ProgrammingClassExamples/AFL2018 (sorted alpha teams).csv b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv similarity index 100% rename from ProgrammingClassExamples/AFL2018 (sorted alpha teams).csv rename to ProgrammingClassExamples/MacOS versions/AFL2018 (sorted alpha teams).csv diff --git a/ProgrammingClassExamples/AFL2018 (sorted pts and %).csv b/ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv similarity index 100% rename from ProgrammingClassExamples/AFL2018 (sorted pts and %).csv rename to ProgrammingClassExamples/MacOS versions/AFL2018 (sorted pts and %).csv diff --git a/ProgrammingClassExamples/Gym_Logo.png b/ProgrammingClassExamples/MacOS versions/Gym_Logo.png similarity index 100% rename from ProgrammingClassExamples/Gym_Logo.png rename to ProgrammingClassExamples/MacOS versions/Gym_Logo.png diff --git a/ProgrammingClassExamples/Names(sorted).txt b/ProgrammingClassExamples/MacOS versions/Names(sorted).txt similarity index 100% rename from ProgrammingClassExamples/Names(sorted).txt rename to ProgrammingClassExamples/MacOS versions/Names(sorted).txt diff --git a/ProgrammingClassExamples/Names.txt b/ProgrammingClassExamples/MacOS versions/Names.txt similarity index 100% rename from ProgrammingClassExamples/Names.txt rename to ProgrammingClassExamples/MacOS versions/Names.txt diff --git a/ProgrammingClassExamples/MacOS versions/Test.txt b/ProgrammingClassExamples/MacOS versions/Test.txt new file mode 100644 index 00000000..6f15df0a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/Test.txt @@ -0,0 +1,3 @@ +T +202.0 +50.5 diff --git a/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt b/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt new file mode 100644 index 00000000..5ee47eaf --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/TonyCrewe2.txt @@ -0,0 +1,3 @@ +Tony +158.0 +39.5 diff --git a/ProgrammingClassExamples/default_icon.ico b/ProgrammingClassExamples/MacOS versions/default_icon.ico similarity index 100% rename from ProgrammingClassExamples/default_icon.ico rename to ProgrammingClassExamples/MacOS versions/default_icon.ico diff --git a/ProgrammingClassExamples/MacOS versions/results.txt b/ProgrammingClassExamples/MacOS versions/results.txt new file mode 100644 index 00000000..0d13392a --- /dev/null +++ b/ProgrammingClassExamples/MacOS versions/results.txt @@ -0,0 +1,3 @@ +Tony +224.0 +56.0 diff --git a/ProgrammingClassExamples/weight 2018.csv b/ProgrammingClassExamples/MacOS versions/weight 2018.csv similarity index 100% rename from ProgrammingClassExamples/weight 2018.csv rename to ProgrammingClassExamples/MacOS versions/weight 2018.csv diff --git a/ProgrammingClassExamples/Tony.txt b/ProgrammingClassExamples/Tony.txt deleted file mode 100644 index c70fa00e..00000000 --- a/ProgrammingClassExamples/Tony.txt +++ /dev/null @@ -1,3 +0,0 @@ -Tony -275.0 -68.75 diff --git a/ProgrammingClassExamples/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py b/ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py similarity index 100% rename from ProgrammingClassExamples/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py rename to ProgrammingClassExamples/Win10 versions/10a PSG Plot (Matplotlib numpy pyplot(y=sinx)) .py diff --git a/ProgrammingClassExamples/10b PSG Plot (axes moved).py b/ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py similarity index 100% rename from ProgrammingClassExamples/10b PSG Plot (axes moved).py rename to ProgrammingClassExamples/Win10 versions/10b PSG Plot (axes moved).py diff --git a/ProgrammingClassExamples/10c PSG Plot (axes pi format).py b/ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py similarity index 100% rename from ProgrammingClassExamples/10c PSG Plot (axes pi format).py rename to ProgrammingClassExamples/Win10 versions/10c PSG Plot (axes pi format).py diff --git a/ProgrammingClassExamples/10d PSG (Plots Tabs and sin cos options).py b/ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py similarity index 100% rename from ProgrammingClassExamples/10d PSG (Plots Tabs and sin cos options).py rename to ProgrammingClassExamples/Win10 versions/10d PSG (Plots Tabs and sin cos options).py diff --git a/ProgrammingClassExamples/10e PSG (Same Window).py b/ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py similarity index 100% rename from ProgrammingClassExamples/10e PSG (Same Window).py rename to ProgrammingClassExamples/Win10 versions/10e PSG (Same Window).py diff --git a/ProgrammingClassExamples/10f PSG (linear and quadratics).py b/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py similarity index 89% rename from ProgrammingClassExamples/10f PSG (linear and quadratics).py rename to ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py index 64625263..b208bd76 100644 --- a/ProgrammingClassExamples/10f PSG (linear and quadratics).py +++ b/ProgrammingClassExamples/Win10 versions/10f PSG (linear and quadratics).py @@ -10,7 +10,7 @@ import matplotlib.backends.tkagg as tkagg import numpy as np import tkinter as tk -sg.ChangeLookAndFeel('Purple') +sg.ChangeLookAndFeel('Black') sg.SetOptions(font = ('Calibri', 14, 'bold')) def draw_figure(canvas, figure, loc = (0,0)): @@ -74,21 +74,21 @@ set_plot(1,1,1, function) #column 1 for function type and constant values ... column1 = [ - [sg.Text('Select constants and function type', )], - [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (12, 4), key = '_function_'), + [sg.Text('Select constants & function type', )], + [sg.InputCombo(['y = ax + b', 'y = ax^2 + bx + c'], size = (16, 4), key = '_function_'), sg.Text('Function', size = (10, 1))], [sg.Text('', size = (1, 2))], - [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (2,1), key = '_a_'), + [sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_a_'), sg.Text('a', size = (3, 1)), - sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (2,1), key = '_b_'), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_b_'), sg.Text('b', size = (3, 1)), - sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (2,1), key = '_c_'), + sg.Spin([sz for sz in range (-6,6)], initial_value =1, size = (3,2), key = '_c_'), sg.Text('c', size = (3, 1))], [sg.Text('', size = (1, 1))], - [sg.ReadButton('Redraw Plot')], + [sg.ReadButton('Redraw Plot', button_color = ('White', 'Red'))], [sg.Text('', size = (1, 14))]] column2 = [[sg.Text('Plot Test - PySimpleGUI and Matplotlib and options')], [sg.Canvas(size = (figure_w, figure_h), key = '_canvas_')], - [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1))]] + [sg.OK(pad=((figure_w / 2, 0), 1), size=(4, 1), button_color = ('White', 'Red'))]] layout = [[sg.Column(column1), sg.Column(column2)]] window = sg.Window('Matplot, PySimpleGUI and options', force_toplevel = True).Layout(layout).Finalize() diff --git a/ProgrammingClassExamples/1a PSG (Entry and PopUp).py b/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py similarity index 87% rename from ProgrammingClassExamples/1a PSG (Entry and PopUp).py rename to ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py index 377eabc7..1b7b9ded 100644 --- a/ProgrammingClassExamples/1a PSG (Entry and PopUp).py +++ b/ProgrammingClassExamples/Win10 versions/1a PSG (Entry and PopUp).py @@ -15,7 +15,10 @@ window = sg.Window('Temperature Converter').Layout(layout) #get value (part of a list) button, value = window.Read() - +if button is None: + #windows was closed without button being pressed + exit(0) + #convert and create string fahrenheit = round(9/5*float(value[0]) +32, 1) result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) diff --git a/ProgrammingClassExamples/1b PSG (Format).py b/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py similarity index 90% rename from ProgrammingClassExamples/1b PSG (Format).py rename to ProgrammingClassExamples/Win10 versions/1b PSG (Format).py index d5b5540b..2b65953f 100644 --- a/ProgrammingClassExamples/1b PSG (Format).py +++ b/ProgrammingClassExamples/Win10 versions/1b PSG (Format).py @@ -21,7 +21,9 @@ layout = [ window = sg.Window('Converter').Layout(layout) button, value = window.Read() - +if button is None: + #windows was closed without button being pressed + exit(0) fahrenheit = round(9/5*float(value[0]) +32, 1) result = 'Temperature in Fahrenheit is: ' + str(fahrenheit) sg.Popup('Result',result) diff --git a/ProgrammingClassExamples/1c PSG (persistent form and bind key).py b/ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py similarity index 100% rename from ProgrammingClassExamples/1c PSG (persistent form and bind key).py rename to ProgrammingClassExamples/Win10 versions/1c PSG (persistent form and bind key).py diff --git a/ProgrammingClassExamples/1d PSG (named input keys and catch errors).py b/ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py similarity index 100% rename from ProgrammingClassExamples/1d PSG (named input keys and catch errors).py rename to ProgrammingClassExamples/Win10 versions/1d PSG (named input keys and catch errors).py diff --git a/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py b/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py new file mode 100644 index 00000000..3db950a1 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/1e PSG (validation and Look and Feel).py @@ -0,0 +1,34 @@ +#PySimple examples (v 3.8) +#Tony Crewe +#Sep 2018 + +import PySimpleGUI as sg + +#Can use a variety of themes - plus individual options +sg.ChangeLookAndFeel('SandyBeach') +sg.SetOptions (font = ('Arial', 10, 'bold')) + + +layout = [ [sg.Text('Enter a Temperature in Celcius')], + [sg.Text('Celcius', size =(8,1)), sg.InputText(size = (15,1),key = '_input_')], + [sg.Text('Result', size =(8,1)), sg.InputText(size = (15,1),key = '_result_')], + [sg.ReadButton('Submit', bind_return_key = True)]] + +window = sg.Window('Temp Converter').Layout(layout) + +while True: + button, value = window.Read() + if button is not None: + #catch program errors for text, floats or blank entry: + #Also validation for range [0, 50] + try: + if float(value['_input_']) > 50 or float(value['_input_']) <0: + sg.Popup('Error','Out of range') + else: + fahrenheit = round(9/5*int(value['_input_']) +32, 1) + window.FindElement('_result_').Update(fahrenheit) + except ValueError: + sg.Popup('Error','Please try again') + + else: + break diff --git a/ProgrammingClassExamples/2a. PSG (checkbox and radiobuttons) - Copy.py b/ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py similarity index 100% rename from ProgrammingClassExamples/2a. PSG (checkbox and radiobuttons) - Copy.py rename to ProgrammingClassExamples/Win10 versions/2a. PSG (checkbox and radiobuttons) - Copy.py diff --git a/ProgrammingClassExamples/2b. PSG (Add logo).py b/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py similarity index 94% rename from ProgrammingClassExamples/2b. PSG (Add logo).py rename to ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py index c931028b..cf35f47d 100644 --- a/ProgrammingClassExamples/2b. PSG (Add logo).py +++ b/ProgrammingClassExamples/Win10 versions/2b. PSG (Add logo).py @@ -10,7 +10,7 @@ sg.SetOptions (font =('Calibri',12,'bold')) #get pathname to current file dirname, filename = os.path.split(os.path.abspath(__file__)) #add file name for image -pathname = dirname + '\\Gym_Logo.png' +pathname = os.path.join(dirname ,'Gym_Logo.png') layout = [[sg.Image(pathname),sg.Text(' Membership Calculator', font = ('Calibri', 16, 'bold'))], [sg.Checkbox(' Student? 10% off', size = (25,1)), diff --git a/ProgrammingClassExamples/2b_makewinexe_file.py b/ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py similarity index 100% rename from ProgrammingClassExamples/2b_makewinexe_file.py rename to ProgrammingClassExamples/Win10 versions/2b_makewinexe_file.py diff --git a/ProgrammingClassExamples/3 PSG (multiline display).py b/ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py similarity index 100% rename from ProgrammingClassExamples/3 PSG (multiline display).py rename to ProgrammingClassExamples/Win10 versions/3 PSG (multiline display).py diff --git a/ProgrammingClassExamples/4a PSG (Sliders and combo).py b/ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py similarity index 100% rename from ProgrammingClassExamples/4a PSG (Sliders and combo).py rename to ProgrammingClassExamples/Win10 versions/4a PSG (Sliders and combo).py diff --git a/ProgrammingClassExamples/4b PSG (Spinner and combo) .py b/ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py similarity index 100% rename from ProgrammingClassExamples/4b PSG (Spinner and combo) .py rename to ProgrammingClassExamples/Win10 versions/4b PSG (Spinner and combo) .py diff --git a/ProgrammingClassExamples/5a PSG (listboxes add remove).py b/ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py similarity index 100% rename from ProgrammingClassExamples/5a PSG (listboxes add remove).py rename to ProgrammingClassExamples/Win10 versions/5a PSG (listboxes add remove).py diff --git a/ProgrammingClassExamples/6a PSG (search linear and binary).py b/ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py similarity index 100% rename from ProgrammingClassExamples/6a PSG (search linear and binary).py rename to ProgrammingClassExamples/Win10 versions/6a PSG (search linear and binary).py diff --git a/ProgrammingClassExamples/6b PSG (search - disabled buttons).py b/ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py similarity index 100% rename from ProgrammingClassExamples/6b PSG (search - disabled buttons).py rename to ProgrammingClassExamples/Win10 versions/6b PSG (search - disabled buttons).py diff --git a/ProgrammingClassExamples/6c PSG (search text preloaded).py b/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py similarity index 94% rename from ProgrammingClassExamples/6c PSG (search text preloaded).py rename to ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py index 164ff001..89009642 100644 --- a/ProgrammingClassExamples/6c PSG (search text preloaded).py +++ b/ProgrammingClassExamples/Win10 versions/6c PSG (search text preloaded).py @@ -67,9 +67,6 @@ while True: button, value = window.Read() if button is not None: - if button == 'Show Names': - display_list(names,'_display1_') - display_list(sorted_names, '_display2_') if button == 'Linear Search': linear_search() if button == 'Binary Search': diff --git a/ProgrammingClassExamples/6d PSG (sort and search with textbox.py b/ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py similarity index 100% rename from ProgrammingClassExamples/6d PSG (sort and search with textbox.py rename to ProgrammingClassExamples/Win10 versions/6d PSG (sort and search with textbox.py diff --git a/ProgrammingClassExamples/6e PSG (sort and search with listbox).py b/ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py similarity index 100% rename from ProgrammingClassExamples/6e PSG (sort and search with listbox).py rename to ProgrammingClassExamples/Win10 versions/6e PSG (sort and search with listbox).py diff --git a/ProgrammingClassExamples/6f PSG (data from text file).py b/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py similarity index 88% rename from ProgrammingClassExamples/6f PSG (data from text file).py rename to ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py index 67e550bf..126dcfa0 100644 --- a/ProgrammingClassExamples/6f PSG (data from text file).py +++ b/ProgrammingClassExamples/Win10 versions/6f PSG (data from text file).py @@ -10,8 +10,8 @@ sg.SetOptions (font =('Calibri',12,'bold')) #get pathname to current file dirname, filename = os.path.split(os.path.abspath(__file__)) -pathname = dirname + '\\Names.txt' #original data -spathname = dirname + '\\Names(sorted).txt' #sorted data +pathname = os.path.join(dirname, 'Names.txt') #original data +spathname = os.path.join(dirname, 'Names(sorted).txt') #sorted data #Get data from file names = [line.strip() for line in open(pathname)] @@ -19,7 +19,9 @@ names = [line.strip() for line in open(pathname)] column1 = [[sg.ReadButton('Original list', size = (13,1))], [sg.ReadButton('Default sort', size = (13,1))], [sg.ReadButton('Sort: selection',size = (13,1))], - [sg.ReadButton('Sort: quick', size = (13,1))]] + [sg.ReadButton('Sort: quick', size = (13,1))], + [sg.Text('______________',font = ('Calibri', 12))], + [sg.ReadButton('Save data\ndisplayed', size = (13,2))]] layout =[[sg.Text('Search and Sort Demo', font =('Calibri', 20, 'bold'))], [sg.Listbox(values =[''], size = (14, 11),font = ('Calibri', 12), background_color ='White',key = '_display_'), sg.Column(column1)], @@ -134,5 +136,10 @@ while True: linear_search() if button == 'Binary Search': binary_search() + if button == 'Save data\ndisplayed': + f = open(spathname, 'w') + for name in list_displayed: + print (name, file = f) + f.close() else: break diff --git a/ProgrammingClassExamples/7a PSG (Data entry calc using file save retrieve).py b/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py similarity index 96% rename from ProgrammingClassExamples/7a PSG (Data entry calc using file save retrieve).py rename to ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py index 8058e4e2..002599f1 100644 --- a/ProgrammingClassExamples/7a PSG (Data entry calc using file save retrieve).py +++ b/ProgrammingClassExamples/Win10 versions/7a PSG (Data entry calc using file save retrieve).py @@ -32,7 +32,7 @@ while True: #get pathname to current file dirname, filename = os.path.split(os.path.abspath(__file__)) #add desired file name for saving to path - pathname = dirname + '\\results.txt' + pathname = os.path.join(dirname , 'results.txt' ) #needs validation and try/catch error checking, will crash if blank or text entry for marks diff --git a/ProgrammingClassExamples/7b PSG (add validation and error trap).py b/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py similarity index 97% rename from ProgrammingClassExamples/7b PSG (add validation and error trap).py rename to ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py index c3e5b59b..53bfb180 100644 --- a/ProgrammingClassExamples/7b PSG (add validation and error trap).py +++ b/ProgrammingClassExamples/Win10 versions/7b PSG (add validation and error trap).py @@ -32,7 +32,7 @@ while True: #get pathname to current file dirname, filename = os.path.split(os.path.abspath(__file__)) #add desired file name for saving to path - pathname = dirname + '\\results.txt' + pathname = os.path.join(dirname , 'results.txt' ) #generic catch error - blanks or wrong data types try: if button == '_save_': diff --git a/ProgrammingClassExamples/7c PSG (add get pathname to save and retrieve files), - Copy.py b/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py similarity index 97% rename from ProgrammingClassExamples/7c PSG (add get pathname to save and retrieve files), - Copy.py rename to ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py index 8da13b48..a4af2ca2 100644 --- a/ProgrammingClassExamples/7c PSG (add get pathname to save and retrieve files), - Copy.py +++ b/ProgrammingClassExamples/Win10 versions/7c PSG (add get pathname to save and retrieve files).py @@ -49,7 +49,7 @@ while True: foldername = sg.PopupGetFolder('', no_window=True) filename = sg.PopupGetFile('Please enter a file name for your results') - pathname = foldername + '\\' + filename + '.txt' + pathname = os.path.join(foldername ,filename + '.txt') f = open(pathname, 'w') print (name, file = f) diff --git a/ProgrammingClassExamples/8a PSG (Data to plot from csv file).py b/ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py similarity index 100% rename from ProgrammingClassExamples/8a PSG (Data to plot from csv file).py rename to ProgrammingClassExamples/Win10 versions/8a PSG (Data to plot from csv file).py diff --git a/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py b/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py new file mode 100644 index 00000000..880caee9 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/8b PSG (Tables and calc from csv file).py @@ -0,0 +1,67 @@ +# PySimple examples (v 3.9.3) +# Tony Crewe +# Sep 2018 - updated Oct 2018 + +# Based of Example program from MikeTheWatchGuy +# https://gitlab.com/lotspaih/PySimpleGUI + +import sys +import PySimpleGUI as sg +import csv + +sg.ChangeLookAndFeel('BrownBlue') + + +def calc_ladder(): + filename = sg.PopupGetFile('Get required file', no_window=True, file_types=(("CSV Files", "*.csv"),)) + # populate table with file contents + # Assume we know csv has heading in row 1 + # Assume we know 7 columns of data - relevenat to AFL w/o Pts or % shown + # data is a list of lists containing data about each team + # data[0] is one teams data data[0[[0] = team, data[0][1] P, data[0] [2] W, + # data[0][3] L, data [0][4] D, data [0][5] F, data [0][6] A + # no error checking or validation used. + + # initialise variable + data = [] + header_list = [] + # read csv + with open(filename, "r") as infile: + reader = csv.reader(infile) + for i in range(1): + # get headings + header = next(reader) + # read everything else into a list of rows + data = list(reader) + # add headings + header = header + ['%', 'Pts'] + for i in range(len(data)): + # calculate % and format to 2 decimal places + percent = str('{:.2f}'.format(int(data[i][5]) / int(data[i][6]) * 100)) + data[i] = data[i] + [percent] # add to data + pts = int(data[i][2]) * 4 + int(data[i][4]) * 2 + data[i] = data[i] + [pts] # add to data + + # use Table (explore settings) and add to column layout + col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, + max_col_width=12, justification='right', background_color='White', + text_color='Black', alternating_row_color='LightBlue', size=(None, len(data)))]] + + layout = [[sg.Column(col_layout, size=(500, 400), scrollable=True)], ] + + window = sg.Window('Table', location=(700, 325), grab_anywhere=False).Layout(layout) + b, v = window.Read() + + +slayout = [ + [sg.Text('Load AFL file to display results with points and percentage'), sg.ReadButton('Load File', size=(20, 1))]] +swindow = sg.Window('Load File', location=(700, 250)).Layout(slayout) + +while True: + button, value = swindow.Read() + if button is not None: + if button == 'Load File': + calc_ladder() + else: + break + diff --git a/ProgrammingClassExamples/8c PSG (Tables - add sort).py b/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py similarity index 87% rename from ProgrammingClassExamples/8c PSG (Tables - add sort).py rename to ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py index 019eb71d..1880145d 100644 --- a/ProgrammingClassExamples/8c PSG (Tables - add sort).py +++ b/ProgrammingClassExamples/Win10 versions/8c PSG (Tables - add sort).py @@ -1,6 +1,6 @@ -#PySimple examples (v 3.8) +#PySimple examples (v 3.9.3) #Tony Crewe -#Sep 2018 +#Sep 2018 - updated Oct 2018 #Based of Example program from MikeTheWatchGuy #https://gitlab.com/lotspaih/PySimpleGUI @@ -48,7 +48,8 @@ def table_example(): data[i][7] = str('{:.2f}'.format(data[i][7])) #use Table (explore settings) and add to column layout col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, - max_col_width = 12,justification='right', size=(None, len(data)))]] + max_col_width = 12,justification='right', text_color = 'White', + alternating_row_color = 'Grey', size=(None, len(data)))]] #experimented with size and location to get windows to fit :-) #remove titlebar of main display window @@ -62,5 +63,8 @@ swindow = sg.Window('Load File', location = (654,250)).Layout(slayout) while True: button, value = swindow.Read() - if button == 'Load File': - table_example() + if button is not None: + if button == 'Load File': + table_example() + else: + break diff --git a/ProgrammingClassExamples/8d PSG (Tables - add logo).py b/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py similarity index 78% rename from ProgrammingClassExamples/8d PSG (Tables - add logo).py rename to ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py index 72c8d018..1e3819d5 100644 --- a/ProgrammingClassExamples/8d PSG (Tables - add logo).py +++ b/ProgrammingClassExamples/Win10 versions/8d PSG (Tables - add logo).py @@ -1,6 +1,6 @@ -#PySimple examples (v 3.8) +#PySimple examples (v 3.9.3) #Tony Crewe -#Sep 2018 +#Sep 2018 - updated Oct 2018 #Based of Example program from MikeTheWatchGuy #https://gitlab.com/lotspaih/PySimpleGUI @@ -11,9 +11,12 @@ import csv import operator import os +sg.ChangeLookAndFeel('Dark') + #get pathname to current file and add file name for image dirname, filename = os.path.split(os.path.abspath(__file__)) -pathname = dirname + '\\AFL.png' + +pathname = os.path.join(dirname , 'AFL.png' ) def table_example(): @@ -43,7 +46,8 @@ def table_example(): data[i][7] = str('{:.2f}'.format(data[i][7])) col_layout = [[sg.Table(values=data, headings=header, auto_size_columns=True, - max_col_width = 12,justification='right', size=(None, len(data)))]] + max_col_width = 12,justification='right', text_color = 'White', + alternating_row_color = 'Grey', size=(None, len(data)))]] layout = [[sg.Column(col_layout, size=(443,400), scrollable=True)],] window = sg.Window('Table', location = (662, 328), no_titlebar=True, grab_anywhere=False).Layout(layout) @@ -55,5 +59,8 @@ swindow = sg.Window('Load File', location = (654,250)).Layout(slayout) while True: button, value = swindow.Read() - if button == 'Load File': - table_example() + if button is not None: + if button == 'Load File': + table_example() + else: + break diff --git a/ProgrammingClassExamples/9a PSG Windows(location hide).py b/ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py similarity index 100% rename from ProgrammingClassExamples/9a PSG Windows(location hide).py rename to ProgrammingClassExamples/Win10 versions/9a PSG Windows(location hide).py diff --git a/ProgrammingClassExamples/9b PSG Tabs example.py b/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py similarity index 89% rename from ProgrammingClassExamples/9b PSG Tabs example.py rename to ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py index 3f6dfb89..1ddcf009 100644 --- a/ProgrammingClassExamples/9b PSG Tabs example.py +++ b/ProgrammingClassExamples/Win10 versions/9b PSG Tabs example.py @@ -1,3 +1,7 @@ +#PySimple examples (v 3.9) +#Tony Crewe +#Oct 2018 + import PySimpleGUI as sg tab1_layout = [[sg.Text('This is inside tab 1')]] diff --git a/ProgrammingClassExamples/9c PSG Tabs example plus.py b/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py similarity index 96% rename from ProgrammingClassExamples/9c PSG Tabs example plus.py rename to ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py index 85d57ede..68829e85 100644 --- a/ProgrammingClassExamples/9c PSG Tabs example plus.py +++ b/ProgrammingClassExamples/Win10 versions/9c PSG Tabs example plus.py @@ -6,8 +6,8 @@ sg.ChangeLookAndFeel('BlueMono') #get pathname to current file dirname, filename = os.path.split(os.path.abspath(__file__)) -pathname = dirname + '\\Names.txt' -spathname = dirname + '\\Names(sorted).txt' +pathname = os.path.join(dirname , 'Names.txt') + #Get data from file names = [line.strip() for line in open(pathname)] sorted_names = names[:] diff --git a/ProgrammingClassExamples/Win10 versions/AFL.png b/ProgrammingClassExamples/Win10 versions/AFL.png new file mode 100644 index 0000000000000000000000000000000000000000..ee3a355975726e681140ce92dd1783a74a0bab57 GIT binary patch literal 7100 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 literal 0 HcmV?d00001 diff --git a/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv new file mode 100644 index 00000000..798296f6 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted alpha teams).csv @@ -0,0 +1,19 @@ +Team,P,W,L,D,F,A +Adelaide Crows,22,12,10,0,1941,1865 +Brisbane Lions,22,5,17,0,1825,2049 +Carlton,22,2,20,0,1353,2282 +Collingwood,22,15,7,0,2046,1699 +Essendon,22,12,10,0,1932,1838 +Fremantle,22,8,14,0,1556,2041 +Geelong Cats,22,13,9,0,2045,1554 +Gold Coast Suns,22,4,18,0,1308,2182 +GWS Giants,22,13,8,1,1898,1661 +Hawthorn,22,15,7,0,1972,1642 +Melbourne,22,14,8,0,2299,1749 +North Melbourne,22,12,10,0,1950,1790 +Port Adelaide,22,12,10,0,1780,1654 +Richmond,22,18,4,0,2143,1574 +St Kilda,22,4,17,1,1606,2125 +Sydney Swans,22,14,8,0,1822,1664 +West Coast Eagles,22,16,6,0,2012,1657 +Western Bulldogs,22,8,14,0,1575,2037 diff --git a/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv new file mode 100644 index 00000000..71cb8c18 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/AFL2018 (sorted pts and %).csv @@ -0,0 +1,19 @@ +Team,P,W,L,D,F,A +Richmond,22,18,4,0,2143,1574 +West Coast Eagles,22,16,6,0,2012,1657 +Collingwood,22,15,7,0,2046,1699 +Hawthorn,22,15,7,0,1972,1642 +Melbourne,22,14,8,0,2299,1749 +Sydney Swans,22,14,8,0,1822,1664 +GWS Giants,22,13,8,1,1898,1661 +Geelong Cats,22,13,9,0,2045,1554 +North Melbourne,22,12,10,0,1950,1790 +Port Adelaide,22,12,10,0,1780,1654 +Essendon,22,12,10,0,1932,1838 +Adelaide Crows,22,12,10,0,1941,1865 +Western Bulldogs,22,8,14,0,1575,2037 +Fremantle,22,8,14,0,1556,2041 +Brisbane Lions,22,5,17,0,1825,2049 +St Kilda,22,4,17,1,1606,2125 +Gold Coast Suns,22,4,18,0,1308,2182 +Carlton,22,2,20,0,1353,2282 diff --git a/ProgrammingClassExamples/Win10 versions/Gym_Logo.png b/ProgrammingClassExamples/Win10 versions/Gym_Logo.png new file mode 100644 index 0000000000000000000000000000000000000000..45bb5f7bc5eb0f708630d1c4136e10c85e5af4a9 GIT binary patch literal 14255 zcmc(GbyQqUwlD4hLV~*oZQR}6rEwZ)BuL{H+zAlef(Hm8KyVH2P6+N22=4B$lTT*m zzL|CJy6=zIYaQG5+giJJ)j72~QcXqn85$893=GUOc{wQ!=+y*zD54-i&v@ttp3n=b zqnw@#3=H~ZKI;Fu@I)xc9aBL+sJu4gEhTXw9LJ2&G{{;L`5isJO!Wv?7^-e z3Qv1G2NwZPVXEJ91)%r8$N(ye-w;<@VJh)o3MqifY7~+XXD|gfD-Vk~I~NB9FFz|g z4;w!R7c&J18#^z6jTgYq$->4iz{VrM$xrd;j|!^I*}_slLrUgPUC<|CDr;9)M*#r9 z!^4BsgOe5FYz1KF=jR8oaR4|tSfB_N7cU1_kSB|S3-wKj+8xULry2hi?V{!7 z2nJ|?T_A4G=3r@eu!Af0KiDgK@uF{sjv5wD}LvUoHOvg=WmZH{!4G z{!$O^0|6pNET&O^TbH zotKk}!opm@65?zRg64>gJ;(|SaCESuqWFggk`OzHvogd2EKCJO|AQ_sDXHcRv9z&+ zHc(Og3b%m#FMeGc3s-AlDh?jDf2Jyd9jyK!v;Rp}`_cap z59R$6q6xBhv;(`Sft}TCJi&Iq4fw4H_$ycK-2OoGasd94srMh~{~&8S*gzeHD)`mu z0@Bcv4%pe{w^lX|4yc^p^xr;fLdy-*Hy&yuUzAoDC=@xW%3OM~Ta3Q2%)VCCGsXpK$dPp;A=hRuV=$BmFGzpcA6*{mW+LX0Y zq4c*Vk%F zS)MYbZvoHm6|bM@@x6|oA(MFr+3}!jrzC6GD${xisW|IrP42sm!^bYl-aK7$scT;( z6N@Ls4|@1Wer=l<(+Ew#SVOfKCYHgC*_^D{A}FNqiQ`_S&QVekQ0B^dx@D`a(^i+U zB#I&84kqIE7RdfU-MFHfK!&p0cNG_hE%4@&xwgJu_8l?r;Z|g1q!(UPVM~5KwGboY z=j+L0O;KBGYc_ro%qCc}=P=!6k2}0{W_7Mpr#|pOfQrI`D0G_cdI1oJ{_6p`e!F zmLS~YnYPE|-dJ+g`X%>;yY%$*7cIs|PwH#PG#eL<1NM7y4GT(DFst2L7jZM-ya0uR zgD7G-3ytps$>&!i3!f;uRpVj#5szal$vShqAMd?5h+Jlh!I7lFJ_hH%Lv`<=;7E4`Z-+k`P zw62g@q1ce@qgn}#O51lXI+~Q|&Cr^*#`jd(M0Gy6D;uT+7%!!3YimhfaLg&D-58D( zHa4dF9S4(to2@iQ2KcxyQ~R$dZeixoeH~E3*-3uhT2>kPv9)>sMPVoJ#u=iA<{P#f zHnFAq8KupFZY!e#bwMACWz`tYwqq@0!*F=WEG-`R4oAi;0m zwLa-65Obyo5E19X>|FJVMrv^9*VK4+x9a+dquE8J^b;fxthmv?4D-E@%d4%88B`@} z;{^eK`sHi+DcT!JsK;1{-LGt%U3aUBW(YsODKn zB6%$y9?|*~DoB&%h?)%{L(nVmIvHgodOoqD1{t-lgq|>##*oroe8b+nu321ckyXVX zwyU3NowS?LO^8yE%wqliT4IeBmJ-iUDT3LPw|DHWQVe(;{X{~|3SRrMW|PT_Qkh>- zp%#GG>q_G;p;kX<*XidYoUGvHWhZNeQgrH4wDV&tH87G-o-q+AzXPn_Duq^mZgMAF`~Ao%yK_bz-`w!a zM|Ta08=kt)0Xgd%VdnaUnbSL)lMzZhXve`BPq31KX<8RnH_=1So;~YhVq{b?R%u?h zb!4TabA}(EXG*cSiSJz~;~5-i%dT>n2mq(%5LR8(q$!;k=-xBzm~~mIslA@cZ)wOK zkxD9#75F(Gl5^WVAumg!Gsx!F$z9v@{{4Hw?pu|k-2TDUWJOGmMJHrh8X7wxuhRmy zcO6JNcmg@ZjUh1nAP}gNA5hEY;YG;00#iB~9{t@;Qs;Hs{fDHbUAi2l6UAgh8`o#1 zC(RZ9&_TN^#KR>0!{xi%&C$KCEE6firy-s}?G)@njj-GsU9~1)W#%`*{~Z+yq!y8qB@C#G&=0LbM^WVE8vslHN42>z4|gCKh-6=ZW#Aidn3o@f30A=9Ca$*WCX%Rns0Guu{RfUF zO>h-$bjEL(JEd(>X#z>&Voqqu>ur^)OceM+Sz5%*S3kSHmu?x*%n$ z)VP^-T7#Hi9G4ezA5Kkl5u6~@3N4_EE7B%7G*otM@TbYQh`c_s#zz{i z9m>4ld)w*&dGFJ@I%&(E+m69WBE?_wGNIl$2ut7B-pp)W723ZzV#qT;s^i?MiYjD} z=XK5Kyq{OCvR((n0g!)`+iAa;(FuE1T-ao6Ds+1dJZ)GEb~eGBS5a{`9l(Kb+Jw=T ztB~8(^yYWetdj9DJ5kZ5Pj^2p_{tSpxah}f%u7Q^{cY- zq=P**KaCT6@bS9LqyP&o6?zg(UluFYj-bKg%hb4Y=d2F_K5~Auw~d3&OU*YHnJKD; zSfW7~1VT9=M(krdJ_BYZ6%`WPk6PDDe0~(3FDa3i^TNTRV@$|Om)MsCU$z|S1bnU? z#T$G#;hVAEpfar~BxjW?37as&yI#v5)OFZ5=F$?zmE2Xf4Xwye^N<%>#8S9@dT*hi zt?lO3qk{5?B#pfny8cB*aa_)jDz1a-Yaxm?u~S~*@@BsccgCZjG2IkKNXrLawjyLi zaK9&}llaX1d{cr$9U41rq&gw~+Ohr(&+N70v$g&ee^hQ>0z{U`~P?4Jc)QJj8|a2xXxvmPlF zhzk{VYx3Z?@=Jv-)K8?*lNHgH=zQOhe=#8blAVEi??%_;Ar$RpA`&O;cg}@pNK?p_ zkMgE=*NW$jlbthK{x4Ck?Z6<)! zQ8d;XiFdT52*~1>?Aj(BI0CefU0>V+2c)Nh(d zxDt|11IG4-E^dwBzTeT(pe&8?kcYsvh$JyjZJxX7u}`Jws&~u-Y-aY#$I(qn^PU;- zjHhK9as;o~O1eFCA{z);6~3TXDJa$~`o23=g6KVf@pIm`eDmjLtKGdl(be|(i9u<7 zeo!aE+nAVx#Ago^p#a$r-*vzrZa;HY=!}R~5ue6M;7T~8CQ5WkxaFybZMmL|TYP~~ zr7y66EDw6$#rL9|0?RfKe_$7B0-viy#bhoMnTF%rh2zrXxmSn!3E1Mbw3-t?{0zR@ z?!yw26To|fNgJ#6_#(0FGA3LDSrGvd^J*Ajp$rWV4_iYZZBM<#5W^m_@Ag^&B$nc( zAxum9&OISV&Q1LU#Nz5<<1ga|dj?^>7DdodgL|~J6NmREWMW3HLwgP)%9dMXXTu?y z@Xc8q{$$)KDH;cB`74A;A;E=9gayS$FZjH%$1&w@V`HD<9Kz|DbJ*e;$MDcDQXcVo z-Lj7xo*wUPZqIkld+<%z_PX4#@S#7GVl*k$LIoVIxha8Nd&g zw1E?b&q!D$>ABt`QG!XuQgeR3I7W=}iP^6lXB0oq>t2LL8k4g2kn~&JoQ!OUrlA&d zqwpieD2^Tr>su94S$cgU>*3}`MFHjm#n_f7P=M@E;wH81)_AE&vqI5KS^nqT)wwEg zAY{)LjzoQin^v4)b&UCE=PBBIk3*p)wk6;q37|5#^*J!pB(_X zoC6Og#}`Qwybi8ui(<(h4@R$^+VPXwoJViQahmP`Io}_zR`P|JbWu8zU-0MwET5xv z&eY@Pd`UioC6i_{>*!`TN7kOkcFHVyFN_~XUW%@updjJJnp#GV$6_i(PR~K6gAw9~ zoaDX{if^1YOpA*7orKBr_IQ9kM`?IupSTA{-@gWLRGiO5c^tL&S=FoR5PTT<;OiWa#JQku8uwkS{>qyB zRLQ8}Ry}l5wA$>6Y=4uQ$?xk!k!WEgmWbF<$LrU&d#_|D()f@$X>De@BY{RgHG)kt zb+Gg`C>op{=6$XSY-A*_Ic#*#?65!2?shlovtmUkSwi0!UC+129Z*1l#tn{vxH#{# zvV=Lgx!qXaAV2kHQ>NeoJ=I1>*xA`lgf1pEYw&AQW8!Q@O4V9N50}1%%D-36;8{8i z7rkFwy1&0KYMAYF3QlH&EH^)f`tP?t64=`Qz@n1fWS%T4h;OM(7El=Mk2NiRs|b^& zr7=Bxzj(HH^{_l;)1r#AKZJR`%0NUuW#ijvWxPm+Puu$}{U?j)-eRr&kearmx6gGN zdy>mu*?I4z4@Z5S8cE<8c>PLkX$p@Aq(}?5CrEb zs`I@g7&%q=w4XX?^~Mv(UuM!~tcL9&u9U%}96?*Z{wQ*P+(o~}f3)6!?&jtu!H|JF zTYfA&I!e16(trqSgEB`%EYGU_eTQ@*G7CIAds3iEO!e|RPM_t9fy?=Z|F)UgTe!ts zn((Pki_I^PYUwsv9{tzV^;)UPBf&;{lNAX%`-1n=jjlcqx|0YU^k_lkeCX%MceXe< zi6AMutO+x`Te=Wq!uv8lx3HhHrCfNtt!s(6FF&Fe&UPcf>I1ihGT0{+*$D4MZwzq}Cb`Hx+z}QXw`058tRZ!b{Oxc>o@BpUwe`mF7%^-)5i6w8?T=YNS^n{`j}C~rB2QeFRAnq zuvB}}s9?M}sO6s2(2zjdeSMZtxhO)5@{ueY1gt}hVBXlvtRYnnPm%|lnchBOk9oiQK8>Z=Z z4PW^JR--Vqsbts9UpC9&NI7ACE;Oi9w_PLDK=8Vk7Q_Q$tFtE)Km~{F!``&63C>Oi3x8o4PMw`tlM+rK!$-!BT>vCA}q7 zI1m)Uo~c_oKakV&nSMfLIb4_qI~uUAl-eHwyynxz5RL9=JFArn0LlCIoj%}cR!$x; z9(^iN)MQ9X5^#Q*C8+>7yJ5hdLKy;+kEwSE+v+#&uPcZzb@}9$k%!>qN((PG= zUve%t!Pohyn&R#Lcx`EI+%ek%nH$3yQ3Nm5L| zPPmC+=wzk3>-x4aBZIJH4=tkW$K&ls&G5FzcnSP@uC@0&IpJ%T@xCak@p8Eokld15 z)nQ^9;eBCj<_dOZX&EWrA-8eznRG{Z`2ocD6%jv#7l>xzf#Tc-JQFdR^vJf#@MAoc zr+j1;p>V0ig@w|HhdEejH^M=#UK$z+@C)^DuOCULA6OlqAnj*8b|WO+dLRbqzyP?k;ea& zxBW864p~nn$JQf-yIISrb$hu9K11~6ws}QLHCunm&L(G3%}2Zf2yhOLIA?bD5_ZvR zXwYAru3v6ij!RMLVw-(0V@hsnH{5dNA-uYZ<%+BuuaCCXamj{I9kCd#TA2Ra!rtaX zmD@tUq5e&)#^(xmr>8IG>DWm+DH;)tiC>UokMyXvTOyuSG4tW!7;wBHM_&H?nUOM% z!(~k$8(H%)<|#;^j^a5nR_PPx+0EC(rYK>VcKRJigPtML$tR{#%XJ$E;u*}U!Pa;ypN z#4m-Sm+!@PPJXSi&#jGiQd5o`@-Z2UcLO_n|b4N^#%?B#`OV zI~aj&Y<5(C4yV6hOakS?VE&|6$uymv!+PA7cAU*6?^3HjfGHtCX^^2x)?B+nN{OeiF|Y3Xq3q&tncsml#iAv zdNXfZ{CdUDqFDqp;<2KC`^`)JB~5DlWl?+4kl3#j=sJZ3j@%;2aFPzX! zl9-W6zov+SYvx3Sh0KI@h!WWuB&~Na$b2%?`V)~?NW?*lt>Ewpp*{@y65ar8;uV;2 zU^o=S@F_wxFhwNrVNr?wjmQ@9ei$32HQ>itC9hN6(0Ss}G(O15=j*$n!>Mzx#R9F8 z-MGP6UVXcxS>MYdAxz$48jd^+H4MJ*0aN{}-hK}C6t_pm8%Y3yy?ccxF7P*v&4{{I z({TOVg-0)d}W~yZsS%@x;b_)w+3{dKG;_w3zE66Is_G zKE}(_xXG8=?_P8MYuNMc0Klq!93J1bcCUkB4ZXJ~EU~ zy~6Ouf^00Ek?HLY9b}8IqjX0D!5>Wbt#NhJIZoo^d|vEZSrOJZsV z5ILnLY)+P(Oozq$3X+BHP;`Vf&H}ICz4~r-DvK%iMN?7&DeVEo<8ALjf^2C``gb2u z^JU^5I_I{OKDry}`m5sCS&n7<`b?ado7~tVzVi?$CBog!|E-Kdoamvr4%!5bvoIc?`th;-J*TCCs5}BlY5vE=rv|hQ%K) z<;z+?M>Z9FJS;1qs2VZq77R19$_-()IPKWR)|OzSZA^WXYtqmQT3Xt3=-WAVkgW&F z+J}V9-n9*UN-elqPW>4x2ccM+p;LHsF^O*BY4hRJ{8nl z?K-)zsyXlzgrJFG(Np>=+|Cb{5%WrKSqvAK7JsxQ^9vCGWEMeS5Cz;_=sJ%-snlzN z?aS|C5rQ!RAt6;#NOPcE|->;UU58$X$fL!+|mrq@x4r6CG};=B#uC*w{L#D?i0oPT(~az z(&yb%Wh*Hx8Xwtg*#;KR=*LC3l3bhEqTm7$X$XeuCVD4xvP+` z-(cupfps`ir#NNLQ*?6y7MYhzs38u-lEd)?jxy)gr9P*BQ$e!LWjS;eIN+ zjgh3{f-{;9I+n}0{pQM{@aO@9wyNgn%cP_cCH63;fJQ}Z>>19x?Ip-e%Q5&*J%cfjLebTyy-F+de(I|ytxWGW=pJenH{&@pjcJ?R&a@6e%d z1PVqbes~eCq2dF_?|w*S@J6>wJs<~r+`8^vGdO!H?)~S9J6eg>C1KSeyKu#^krA0t zDYK1xT~ge#XoC35pOGU5r&^sxNUwxwN_W2ql3nk}yP%W8*=uFj#%^~b*bsGD6LxNN zkg2bSf=F3&KCOPq6Cu?0BH7UF@6Q`o#|X+n^YTNUs1o@Q-ZCLoX)YU2N0p*KxYzXZ z)!L3Umc0GpPs+2OhutY&q{+CQVg={+Us0GO2$=;dAoN)Bv|bUHmtu~WOiIKGdc4au zxsvPF3tC1p_POpF8N!K9J_~jB<&-^7q}R7+N*CT%O=bX0widtBje(q_`Px19SEf9x z+vxFTRc@z}FMNcox*nKQhMs%3b#7VZNQobR{#np{_(8=Yy@)e>f`K0f##LREHFiDI z;Vox6!|Gi->TUpmz5=-aar zi(>!^nvR6E&LUY=_4M@U0sS(dpHfJK9(iXkrN@kw!#>7}KBmb;6Hu!4GcB_&F3?_y z-m-D)%zRt%*e{4j4M3NCnH3(IN>FRT85GoLgpy`_N@cBQO1svJatpGgOZI6B6A)WE zk4d)ZJ(|-jFWSpCP>8RXtwS%A5SGDA8Q1rGH!LRwM@BCFZa6*7vu|Xj1~0o1{^`QR z6(w^{tmTb+6Q381gd0r0UbF_{tcI(dPKcDVANlGLXOZ%;f2g7HGjaOJ+SJzUk=;gw zEB?6j^c%ENA9@kd+^N^P7fKb~O<1Df(X$HtH%O+AUN)j>Pj^j7fi|;!s=0XBE}RbY zBp>K-;S683L1eALi3xCM;}Wy_Ut_`^S5~o?EmFz2w?9a!A$CA9YCCUS&3|gys<}oKH>Om1rI&WSwBw{+rQc#LWp+ArV9!$U z+8vc$V%i+jjZGEJSqNq(CrCPx6Gz57W zt2atqQ?|7m>&y7a4FFY=E0FZCfFT~RU;;6MN+5?oH4v6rDy;(6U*uvmL#yibrk8@jYd~%$l{!3+;fW0M}dPxsnTYz;SyfDd(;2d226O8z+ zOJ+Xe{Udv&pfYo&6VDr>uv&te>(6MSFYzrgX_4t{(~=S3UN)qmBR0)9HYzHad&D(A zIT)vesgRPfCWnTMFJFm#2vW|dPkfPXK>^HL!)rf6Vfpqjs+8A-(N<4YaVTn{D+G7^uzFtJuymNpPj+tHC~MX87FWU+B{pznW&j+S z?M$%mJ>@AfhT?Q2h}_udvUR!n*g2&*iu)b4K8sQ0HkXr~)vsB`HZxM~CT-?OF&^t2 zk0}y3j+&B986k&aLP$Im!)e>Gl=ISL&69l*EKT{91%BT(fU@QGxC?9RV^I*3XXwqakIdw2L%wZF8y;h3Lu zBQTQN1@CbP(8l~S!xQ-KBc8tRm}F;(IUJGRCjhpwb*ilj^@ol51AEp&sV&%b#{13? zg&a$OnqC%%g-g=3+?p|ea*e_EabvZ`>P(n%J3yaT3YGdB$xNl^f|Rpn{H@3CA8Yq_gtmsx>di0+`xmY~Jk#SO4U;?H z^P%)=`Xz<6ohb&A1;W)m-n>YV6n}l}+}KgkxVVU8pr@WRRM`uvFA>Pd;G06>kwWyQ zeG?%n5gVJdpvA+Joce8t=S3O3+d)7*caW1fwz8L(SDQICHsZ{gvg*3ki6AE#@Zs6@ zJ^_bCe>il@y&TqCB&>pb-L@*g3!LY_LO<5?g@?6?J-F#}E$MhuH(vCJ?esTewv-u{ zQ#n|yIK~>93pb$&A{vg*V!ACdM47;yLCf@cD!$VshX4a)UoINXBZ!SWL-;N>r!jz` zK&9-x3{z64x%9oO;P#Jj?EBab!}E1w>F%PDo<{vI#&5Gb{Gq%4k7)aTB!fVt64kyF z+u2+8M_z)Xx%u+$yOf@^_NC{ik2nDxbm+nmF~c4KZ`G#WmBckv_rf5|>m^eL@J1*b zhVhB0dTp_H77-P(|07;}sdg%yb;uMmQL*ybrIV+C+GoR0> zTg}=c>SsZ(2#&7v&JbkPfcstDHZvuM*AR$5^0fe3kZm|J72y2+;LuP;kSfJzQ;bTr zAetvQ475+xa`cX5gTeT2_aREZ1mTozJ58fQk%YrAH40+Q%gReOB2|!#yiMt_9JVR)8<25f<%WAH6H-c7>Mn>jqvlBg&ALj*+H-B2b1^ zA{X48pLn&tOolKfF$PD&%?AjXb`RJV_VmyT$HylSwTYH}t}-O0i$5UFCfgzxW{7=% zWuJ)1JneK~Zx0%0XYXsf`I*7vH%@}zMRA`Kl{L^@*3baNR3e|AoGegQQE_N~yxrSt z@M)Lmafc59{HTYkaQ>*AVJYHyY`PKgoLXpB7HQM88bZ)p-scU+>xC*o87 zH8cEE8?{gG2XWy27<*bc2qe;gg`>EmRj}r6x`nq&$VdKwl*0MeC>tKV)FE%l0gFE> zASF5Zq6DGLVQ&1r{^yd>nDmq1zi)~Q7X0Fm?c+081s+1+>3pU(EOvcs zJ6-BUp!1~e>RLl0aTyT9z-JIDy9g^}g6>{Tsz4O@M#Cj`Gf`D!4wKftPk4ihpd=WQ zzM14pG<|N$;6;xj{VJ6l+wKXT>~g)ZHT6ue^XP_P1IC9NpRW})s5un*&Gj+Jp{D^o zcnWdh{Ip`s7Q0um0!7$ix$4c;;d8@}p=^FgK1=>1A*cqUxOlgvA2AbZY6u@tQnHj| z=A6PR050FZ|Gaw;SzEG?iFt-oGIT+4e0@~4OdR+43|MaM4U ziplOodR5k-LN3ngcvlu5GQvySpjy2&ba()Fg$7gUK1xXS&%AIlj`jy)1Y6W)f)u<) z!+2h&_3jx{@gGj_R=OVA;Ibi|&stFc3qiI*#rs6&up<7~(3iJ+Y&Ze5Bf(#rGw7=R z_nQF!=eI2Br_gkGpzp25>=PN@v}`2{aVJ?eGsObU!Y0PQJyQ8`MD_K#F1zjFI9I46 z&Bc#5NTaDy4}$Dr)Ty^{1w&{J?J|O|((P_eH#sQ^w(swK9-uowM*Ba7fbnB*#Tl-h z$FV(=$@SLY8g@s=MDF$>*!|V(6MjP04G#3Cpuw#if00xO#?0)f<{K36`t}D830UN? zXT+BR2zNML=7xrgFXTQIR9lT1kK#S;nLK&ZibnSe-9qOJ3(z1xaQ%9W4_KvLouJn~ z>^}P;-3@^_$45xVSZ{V8b^ZEHn;hzj(X2yX<=3%H{;t9K;Ijq5#T4x65JQX^_71@! z9mXRb*(>}^wzw06Iy?3CpZCIgVq>ZBpcS=6S0;{SX>32(=G>UXq=0XUub9)Xn{n=h zyL~y(@mXJbuR_C~mE{XBw2E4AapZryQzQ#Zyr-9DV`CE=OUyeO<*OrBY|q!H3uwKj zqP*s4xiHH>PP^yhyI+Cv4`TE3O9>rI0koz(UjW~ywgeYf_J8Y^nak#;-Y*G*s|l#f zs2syjUNT#3mlRjn zMXOt+{Gy-Sp-H2XBVvT^Nd}*}5@;%dA#nq92LxT@bq+mkp02EW;+7uDcJw(MZooIv zW(Z>P`GM@7kV1`O`6eDT&<%M}I~QYrIG|4(`0yDAIuSY@z6$$NsF=zlnakK6!l&|< z;+UP!1erdH1lAgorWPX^!0qe5pz%a`vw=oZ(&M!p>R8^z?M@}b64)nCQSOiKZ7JLv zyU6;jS0b<~L5vfEIT~{ERA`3eY6%B-mddQxx%B!AE|bo&&k-vg-zZpoHOs%a-1~l1 z2~V_{JA(FE@THmB)cRcnC6}-W{ko5I;1^n?l`c^67NO{gQIxNSW8xOODWD!qfz4^# z?|V=?GpPH;aL#YNI}!oKO>Rag+z?SbmEw~Qm7_vlP3qCtBN5C)MbjRKI*~7=ff|np z5+*6}@t}~gwU`0ag?j!t9~k~Spv1`!gm_R d?@pdzTIAwa8K~*Ae*L9RURp)!i-c*={{f6B3G4s> literal 0 HcmV?d00001 diff --git a/ProgrammingClassExamples/Win10 versions/Names.txt b/ProgrammingClassExamples/Win10 versions/Names.txt new file mode 100644 index 00000000..d1b9fd24 --- /dev/null +++ b/ProgrammingClassExamples/Win10 versions/Names.txt @@ -0,0 +1,10 @@ +Roberta +Kylie +Jenny +Helen +Andrea +Meredith +Deborah +Pauline +Belinda +Wendy \ No newline at end of file diff --git a/ProgrammingClassExamples/Win10 versions/default_icon.ico b/ProgrammingClassExamples/Win10 versions/default_icon.ico new file mode 100644 index 0000000000000000000000000000000000000000..1a41525eccc9d2942797a9049eece9aef370b868 GIT binary patch literal 23462 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