Release 3.9.1 & 1.1.2

This commit is contained in:
MikeTheWatchGuy 2018-10-08 13:30:33 -04:00
parent 8f7356f425
commit 91da5ed7b2
23 changed files with 487 additions and 150 deletions

View File

@ -20,7 +20,7 @@ column1 = [[sg.Text('Column 1', background_color='#F7F3EC', justification='cente
layout = [ layout = [
[sg.Menu(menu_def, tearoff=True)], [sg.Menu(menu_def, tearoff=True)],
[sg.Text('All graphic widgets in one form!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE)], [sg.Text('All graphic widgets in one Window!', size=(30, 1), justification='center', font=("Helvetica", 25), relief=sg.RELIEF_RIDGE, text_color='midnightblue')],
[sg.Text('Here is some text.... and a place to enter text')], [sg.Text('Here is some text.... and a place to enter text')],
[sg.InputText('This is my text')], [sg.InputText('This is my text')],
[sg.Frame(layout=[ [sg.Frame(layout=[

View File

@ -16,16 +16,16 @@ sg.SetOptions(element_padding=(0,0))
layout = [[sg.T('User:', pad=((3,0),0)), sg.OptionMenu(values = ('User 1', 'User 2'), size=(20,1)), sg.T('0', size=(8,1))], layout = [[sg.T('User:', pad=((3,0),0)), sg.OptionMenu(values = ('User 1', 'User 2'), size=(20,1)), sg.T('0', size=(8,1))],
[sg.T('Customer:', pad=((3,0),0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20,1)), sg.T('1', size=(8,1))], [sg.T('Customer:', pad=((3,0),0)), sg.OptionMenu(values=('Customer 1', 'Customer 2'), size=(20,1)), sg.T('1', size=(8,1))],
[sg.T('Notes:', pad=((3,0),0)), sg.In(size=(44,1), background_color='white', text_color='black')], [sg.T('Notes:', pad=((3,0),0)), sg.In(size=(44,1), background_color='white', text_color='black')],
[sg.ReadButton('Start', button_color=('white', 'black'), key='Start'), [sg.ReadButton('Start', button_color=('white', 'black'), key='_Start_'),
sg.ReadButton('Stop', button_color=('white', 'black'), key='Stop'), sg.ReadButton('Stop', button_color=('white', 'black'), key='_Stop_'),
sg.ReadButton('Reset', button_color=('white', 'firebrick3'), key='Reset'), sg.ReadButton('Reset', button_color=('white', 'firebrick3'), key='_Reset_'),
sg.ReadButton('Submit', button_color=('white', 'springgreen4'), key='Submit')]] sg.ReadButton('Submit', button_color=('white', 'springgreen4'), key='_Submit_')]]
window = sg.Window("Time Tracker", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False, window = sg.Window("Time Tracker", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False,
default_button_element_size=(12,1)).Layout(layout).Finalize() default_button_element_size=(12,1)).Layout(layout).Finalize()
for key, state in {'Start': False, 'Stop': True, 'Reset': True, 'Submit': True}.items(): for key, state in {'_Start_': False, '_Stop_': True, '_Reset_': True, '_Submit_': True}.items():
window.FindElement(key).Update(disabled=state) window.FindElement(key).Update(disabled=state)
recording = have_data = False recording = have_data = False
@ -34,18 +34,18 @@ while True:
print(button) print(button)
if button is None: if button is None:
sys.exit(69) sys.exit(69)
if button is 'Start': if button == '_Start_':
for key, state in {'Start':True, 'Stop':False, 'Reset':False, 'Submit':True}.items(): for key, state in {'_Start_':True, '_Stop_':False, '_Reset_':False, '_Submit_':True}.items():
window.FindElement(key).Update(disabled=state) window.FindElement(key).Update(disabled=state)
recording = True recording = True
elif button is 'Stop' and recording: elif button == '_Stop_' and recording:
[window.FindElement(key).Update(disabled=value) for key,value in {'Start':False, 'Stop':True, 'Reset':False, 'Submit':False}.items()] [window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':False, '_Submit_':False}.items()]
recording = False recording = False
have_data = True have_data = True
elif button is 'Reset': elif button == '_Reset_':
[window.FindElement(key).Update(disabled=value) for key,value in {'Start':False, 'Stop':True, 'Reset':True, 'Submit':True}.items()] [window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':True, '_Submit_':True}.items()]
recording = False recording = False
have_data = False have_data = False
elif button is 'Submit' and have_data: elif button is '_Submit_' and have_data:
[window.FindElement(key).Update(disabled=value) for key,value in {'Start':False, 'Stop':True, 'Reset':True, 'Submit':False}.items()] [window.FindElement(key).Update(disabled=value) for key,value in {'_Start_':False, '_Stop_':True, '_Reset_':True, '_Submit_':False}.items()]
recording = False recording = False

View File

@ -11,6 +11,7 @@ else:
Shows a big chart of colors... give it a few seconds to create it Shows a big chart of colors... give it a few seconds to create it
Once large window is shown, you can click on any color and another window will popup Once large window is shown, you can click on any color and another window will popup
showing both white and black text on that color showing both white and black text on that color
Uses TOOLTIPS to show the hex values for the colors. Hover over a color and a tooltip will show you the RGB
You will find the list of tkinter colors here: You will find the list of tkinter colors here:
http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm
@ -670,7 +671,7 @@ color_map = {
} }
sg.SetOptions(button_element_size=(12,1), element_padding=(0,0), auto_size_buttons=False, border_width=1) sg.SetOptions(button_element_size=(12,1), element_padding=(0,0), auto_size_buttons=False, border_width=1, tooltip_time=100)
layout = [[sg.Text('Hover mouse to see RGB value, click for white & black text', text_color='blue', font='Any 15', relief=sg.RELIEF_SUNKEN, justification='center', size=(100,1), background_color='light green', pad=(0,(0,20))),]] layout = [[sg.Text('Hover mouse to see RGB value, click for white & black text', text_color='blue', font='Any 15', relief=sg.RELIEF_SUNKEN, justification='center', size=(100,1), background_color='light green', pad=(0,(0,20))),]]
row = [] row = []
@ -689,5 +690,5 @@ while True:
if b is None: if b is None:
break break
# -- Create a secondary window that shows white and black text on chosen color # -- Create a secondary window that shows white and black text on chosen color
layout2 =[[sg.Button(b, button_color=('white', b), tooltip=color_map[b]), sg.Button(b, button_color=('black', b), tooltip=color_map[b])] ] layout2 =[[sg.DummyButton(b, button_color=('white', b), tooltip=color_map[b]), sg.DummyButton(b, button_color=('black', b), tooltip=color_map[b])] ]
sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).Read() sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).ReadNonBlocking()

View File

@ -109,5 +109,5 @@ while True:
if b is None: if b is None:
break break
# -- Create a secondary window that shows white and black text on chosen color # -- Create a secondary window that shows white and black text on chosen color
layout2 =[[sg.Button(b, button_color=('white', b)), sg.Button(b, button_color=('black', b))] ] layout2 =[[sg.DummyButton(b, button_color=('white', b)), sg.DummyButton(b, button_color=('black', b))] ]
sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).Read() sg.Window('Buttons with white and black text', keep_on_top=True).Layout(layout2).ReadNonBlocking()

View File

@ -277,7 +277,7 @@ def CallbackSimulation():
break break
# All done! # All done!
sg.PopupOk('Done') sg.PopupOK('Done')
def RealtimeButtons(): def RealtimeButtons():
""" """

View File

@ -45,12 +45,16 @@ def main():
# ---------------- Create Form ---------------- # ---------------- Create Form ----------------
sg.ChangeLookAndFeel('Black') sg.ChangeLookAndFeel('Black')
layout = [[sg.Text('', size=(8,1), font=('Helvetica', 20),text_color=sg.YELLOWS[0], justification='center', key='text')], layout = [[sg.Text('', size=(8,1), font=('Helvetica', 20),text_color=sg.YELLOWS[0],
justification='center', key='text')],
[sg.Text('', size=(30, 8), font=('Courier New', 12),text_color='white', justification='left', key='processes')], [sg.Text('', size=(30, 8), font=('Courier New', 12),text_color='white', justification='left', key='processes')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15,0), 0)), sg.Spin([x+1 for x in range(10)], 1, key='spin')],] [sg.Exit(button_color=('white', 'firebrick4'), pad=((15,0), 0), size=(9,1)),
sg.Spin([x+1 for x in range(10)], 1, key='spin')],]
window = sg.Window('CPU Utilization', no_titlebar=True, auto_size_buttons=False, window = sg.Window('CPU Utilization',
keep_on_top=True, grab_anywhere=True).Layout(layout) no_titlebar=True,
keep_on_top=True,
grab_anywhere=True).Layout(layout)
# start cpu measurement thread # start cpu measurement thread
thread = Thread(target=CPU_thread,args=(None,)) thread = Thread(target=CPU_thread,args=(None,))

View File

@ -10,12 +10,17 @@ import psutil
# ---------------- Create Form ---------------- # ---------------- Create Form ----------------
sg.ChangeLookAndFeel('Black') sg.ChangeLookAndFeel('Black')
layout = [[sg.Text('')],
[sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], layout = [[sg.Text('CPU Utilization')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0)), [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='_text_')],
sg.Spin([x + 1 for x in range(10)], 1, key='spin')]] [sg.Exit(button_color=('white', 'firebrick4'), pad=((15, 0), 0), size=(9,1)),
# Layout the rows of the form and perform a read. Indicate the form is non-blocking! sg.Spin([x + 1 for x in range(10)], 1, key='_spin_')]]
window = sg.Window('CPU Meter', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True).Layout(layout)
# Layout the rows of the Window
window = sg.Window('CPU Meter',
no_titlebar=True,
keep_on_top=True,
grab_anywhere=True).Layout(layout)
# ---------------- main loop ---------------- # ---------------- main loop ----------------
while (True): while (True):
@ -26,7 +31,7 @@ while (True):
if values is None or button == 'Exit': if values is None or button == 'Exit':
break break
try: try:
interval = int(values['spin']) interval = int(values['_spin_'])
except: except:
interval = 1 interval = 1
@ -34,7 +39,7 @@ while (True):
# --------- Display timer in window -------- # --------- Display timer in window --------
window.FindElement('text').Update(f'CPU {cpu_percent:02.0f}%') window.FindElement('_text_').Update(f'CPU {cpu_percent:02.0f}%')
# Broke out of main loop. Close the window. # Broke out of main loop. Close the window.
window.CloseNonBlocking() window.CloseNonBlocking()

View File

@ -23,7 +23,7 @@ layout = [[sg.Text('')],
sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'), sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'),
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]] sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
window = sg.Window('Running Timer', no_titlebar=False, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True).Layout(layout) window = sg.Window('Running Timer', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True).Layout(layout)
# ---------------- main loop ---------------- # ---------------- main loop ----------------
current_time = 0 current_time = 0

View File

@ -11,7 +11,7 @@ layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0,0), graph_top_r
window = sg.Window('Graph test').Layout(layout).Finalize() window = sg.Window('Graph test').Layout(layout).Finalize()
graph = window.FindElement('graph') graph = window.FindElement('graph')
circle = graph.DrawCircle((75,75), 25, fill_color='black',line_color='white') circle =graph .DrawCircle((75,75), 25, fill_color='black',line_color='white')
point = graph.DrawPoint((75,75), 10, color='green') point = graph.DrawPoint((75,75), 10, color='green')
oval = graph.DrawOval((25,300), (100,280), fill_color='purple', line_color='purple' ) oval = graph.DrawOval((25,300), (100,280), fill_color='purple', line_color='purple' )
rectangle = graph.DrawRectangle((25,300), (100,280), line_color='purple' ) rectangle = graph.DrawRectangle((25,300), (100,280), line_color='purple' )

View File

@ -22,9 +22,9 @@ Dependecies
Python v3 Python v3
PIL PIL
""" """
# Get the folder containing the images from the user # Get the folder containin:g the images from the user
rc, folder = sg.GetPathBox('Image Browser', 'Image folder to open', default_path='') folder = sg.PopupGetFolder('Image folder to open', default_path='')
if not rc or not folder: if not folder:
sg.PopupCancel('Cancelling') sg.PopupCancel('Cancelling')
raise SystemExit() raise SystemExit()
@ -89,7 +89,7 @@ i=0
while True: while True:
# read the form # read the form
button, values = window.Read() button, values = window.Read()
print(button, values)
# perform button and keyboard operations # perform button and keyboard operations
if button is None: if button is None:
break break
@ -103,7 +103,7 @@ while True:
if i < 0: if i < 0:
i = num_files + i i = num_files + i
filename = os.path.join(folder, fnames[i]) filename = os.path.join(folder, fnames[i])
elif button in ('Read', ''): # something from the listbox elif button == 'listbox': # something from the listbox
f = values["listbox"][0] # selected filename f = values["listbox"][0] # selected filename
filename = os.path.join(folder, f) # read this file filename = os.path.join(folder, f) # read this file
i = fnames.index(f) # update running index i = fnames.index(f) # update running index

View File

@ -35,7 +35,7 @@ while True:
if button == 'Clear': # clear keys if clear button if button == 'Clear': # clear keys if clear button
keys_entered = '' keys_entered = ''
elif button in '1234567890': elif button in '1234567890':
keys_entere=d = values['input'] # get what's been entered so far keys_entered = values['input'] # get what's been entered so far
keys_entered += button # add the new digit keys_entered += button # add the new digit
elif button == 'Submit': elif button == 'Submit':
keys_entered = values['input'] keys_entered = values['input']

View File

@ -16,29 +16,33 @@ import random
""" """
def LEDIndicator(key): def LEDIndicator(key=None, radius=30):
return sg.Graph(canvas_size=(30, 30), graph_bottom_left=(-20, -20), graph_top_right=(20, 20), return sg.Graph(canvas_size=(radius, radius),
pad=(0, 0), key=key) graph_bottom_left=(-radius, -radius),
graph_top_right=(radius, radius),
pad=(0, 0), key=key)
def SetLED(window, key, color): def SetLED(window, key, color):
graph = window.FindElement(key) graph = window.FindElement(key)
graph.Erase() graph.Erase()
graph.DrawCircle((0, 0), 10, fill_color=color, line_color=color) graph.DrawCircle((0, 0), 12, fill_color=color, line_color=color)
layout = [[sg.Text('My Status Report')], layout = [[sg.Text('My LED Status Indicators', size=(20,1))],
[sg.Text('CPU Use'), LEDIndicator('_cpu_')], [sg.Text('CPU Use'), LEDIndicator('_cpu_')],
[sg.Text('RAM'), LEDIndicator('_ram_')], [sg.Text('RAM'), LEDIndicator('_ram_')],
[sg.Text('Temperature'), LEDIndicator('_temp_')], [sg.Text('Temperature'), LEDIndicator('_temp_')],
[sg.Text('Server 1'), LEDIndicator('_server1_')], [sg.Text('Server 1'), LEDIndicator('_server1_')],
[sg.Exit()]] [sg.RButton('Exit')]]
window = sg.Window('My new window', default_element_size=(12, 1), auto_size_text=False).Layout(layout).Finalize() window = sg.Window('My new window', default_element_size=(12, 1), auto_size_text=False).Layout(layout).Finalize()
i = 0 i = 0
while True: # Event Loop while True: # Event Loop
button, value = window.ReadNonBlocking() button, value = window.ReadNonBlocking()
if button == 'Exit':
window.CloseNonBlocking()
break
if value is None: if value is None:
break break
i += 1 i += 1

View File

@ -76,7 +76,7 @@ class PlayerGUI():
image_filename=image_exit, image_size=(50,50), image_subsample=2, border_width=0, )] image_filename=image_exit, image_size=(50,50), image_subsample=2, border_width=0, )]
] ]
window = sg.FlexForm('MIDI File Player', default_element_size=(30, 1), font=("Helvetica", 25)).Layout(layout).Finalize() window = sg.Window('MIDI File Player', default_element_size=(30, 1), font=("Helvetica", 25)).Layout(layout).Finalize()
self.Window = window self.Window = window
@ -87,7 +87,7 @@ class PlayerGUI():
# ------------------------------------------------------------------------- # # ------------------------------------------------------------------------- #
def PlayerPlaybackGUIUpdate(self, DisplayString): def PlayerPlaybackGUIUpdate(self, DisplayString):
window = self.Window window = self.Window
if 'window' not in locals() or window is None: # if the form has been destoyed don't mess with it if 'window' not in locals() or window is None: # if the widnow has been destoyed don't mess with it
return PLAYER_COMMAND_EXIT return PLAYER_COMMAND_EXIT
self.TextElem.Update(DisplayString) self.TextElem.Update(DisplayString)
button, (values) = window.ReadNonBlocking() button, (values) = window.ReadNonBlocking()

View File

@ -23,22 +23,6 @@ Basic steps are:
""" """
def draw_figure(canvas, figure, loc=(0, 0)):
""" Draw a matplotlib figure onto a Tk canvas
loc: location of top-left corner of figure on canvas in pixels.
Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
"""
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
#------------------------------- PASTE YOUR MATPLOTLIB CODE HERE ------------------------------- #------------------------------- PASTE YOUR MATPLOTLIB CODE HERE -------------------------------
import numpy as np import numpy as np
@ -95,7 +79,28 @@ figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
#------------------------------- END OF YOUR MATPLOTLIB CODE ------------------------------- #------------------------------- END OF YOUR MATPLOTLIB CODE -------------------------------
# define the form layout #------------------------------- Beginning of Matplotlib helper code -----------------------
def draw_figure(canvas, figure, loc=(0, 0)):
""" Draw a matplotlib figure onto a Tk canvas
loc: location of top-left corner of figure on canvas in pixels.
Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py
"""
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
#------------------------------- Beginning of GUI CODE -------------------------------
# define the window layout
layout = [[sg.Text('Plot test', font='Any 18')], layout = [[sg.Text('Plot test', font='Any 18')],
[sg.Canvas(size=(figure_w, figure_h), key='canvas')], [sg.Canvas(size=(figure_w, figure_h), key='canvas')],
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]] [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]

View File

@ -1,7 +1,7 @@
#!/usr/bin/env python #!/usr/bin/env python
import sys import sys
if sys.version_info[0] >= 3: if sys.version_info[0] >= 3:
import PySimpleGUI_mod as sg import PySimpleGUI as sg
else: else:
import PySimpleGUI27 as sg import PySimpleGUI27 as sg
""" """
@ -20,26 +20,26 @@ def SecondForm():
def TestMenus(): def TestMenus():
import PySimpleGUI as sg
sg.ChangeLookAndFeel('LightGreen') sg.ChangeLookAndFeel('LightGreen')
sg.SetOptions(element_padding=(0, 0)) sg.SetOptions(element_padding=(0, 0))
# ------ Menu Definition ------ # # ------ Menu Definition ------ #
menu_def = [['&File', ['&Open', '&Save', '---', 'Properties', 'E&xit' ]], menu_def = [['&File', ['&Open', '&Save', '&Properties', 'E&xit' ]],
['&Edit', ['Paste', ['Special', 'Normal',], 'Undo'],], ['&Edit', ['&Paste', ['Special', 'Normal',], 'Undo'],],
['' ['&Toolbar', ['---', 'Command &1', 'Command &2', '---', 'Command &3', 'Command &4']],
'&Help', '&About...'],] ['&Help', '&About...'],]
# ------ GUI Defintion ------ # # ------ GUI Defintion ------ #
layout = [ layout = [
[sg.Menu(menu_def, tearoff=False)], [sg.Menu(menu_def, tearoff=True)],
[sg.Output(size=(60,20))], [sg.Output(size=(60,20))],
[sg.In('Test', key='input', do_not_clear=True)] [sg.In('Test', key='input', do_not_clear=True)]
] ]
window = sg.Window("Windows-like program", default_element_size=(12, 1), auto_size_text=False, auto_size_buttons=False, window = sg.Window("Windows-like program", default_element_size=(12, 1), auto_size_text=False,
default_button_element_size=(12, 1)).Layout(layout) auto_size_buttons=False, default_button_element_size=(12, 1)).Layout(layout)
# ------ Loop & Process button menu choices ------ # # ------ Loop & Process button menu choices ------ #
while True: while True:
@ -58,6 +58,4 @@ def TestMenus():
elif button == 'Properties': elif button == 'Properties':
SecondForm() SecondForm()
TestMenus() TestMenus()

View File

@ -6,7 +6,7 @@ else:
import PySimpleGUI27 as sg import PySimpleGUI27 as sg
# Here, have some windows on me.... # Here, have some windows on me....
[sg.PopupNoWait(location=(500+100*x,500)) for x in range(10)] [sg.PopupNoWait('No-wait Popup', location=(500+100*x,500)) for x in range(10)]
answer = sg.PopupYesNo('Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?') answer = sg.PopupYesNo('Do not worry about all those open windows... they will disappear at the end', 'Are you OK with that?')
@ -26,7 +26,6 @@ sg.Popup('Simple popup')
sg.PopupNoTitlebar('No titlebar') sg.PopupNoTitlebar('No titlebar')
sg.PopupNoBorder('No border') sg.PopupNoBorder('No border')
sg.PopupNoFrame('No frame') sg.PopupNoFrame('No frame')
# sg.PopupNoButtons('No Buttons') # don't mix with non-blocking... disaster ahead...
sg.PopupCancel('Cancel') sg.PopupCancel('Cancel')
sg.PopupOKCancel('OK Cancel') sg.PopupOKCancel('OK Cancel')
sg.PopupAutoClose('Autoclose') sg.PopupAutoClose('Autoclose')

View File

@ -31,10 +31,9 @@ If you want to change the GUI, make changes to the GUI portion marked below.
import numpy as np import numpy as np
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
N = 5
values_to_plot = (20, 35, 30, 35, 27) values_to_plot = (20, 35, 30, 35, 27)
ind = np.arange(N) # the x locations for the groups ind = np.arange(len(values_to_plot))
width = 0.4 # the width of the bars: can also be len(x) sequence width = 0.4
p1 = plt.bar(ind, values_to_plot, width) p1 = plt.bar(ind, values_to_plot, width)

View File

@ -53,7 +53,7 @@ def Launcher2():
window.Layout(layout) window.Layout(layout)
# ---===--- Loop taking in user input and using it to query HowDoI --- # # ---===--- Loop taking in user input --- #
while True: while True:
(button, value) = window.Read() (button, value) = window.Read()
if button in ('EXIT', None): if button in ('EXIT', None):

11
Demo_YouTube_Intro.py Normal file
View File

@ -0,0 +1,11 @@
import PySimpleGUI as sg
layout = [[sg.Text('What is your name?')],
[sg.InputText()],
[sg.Button('Ok')]]
window = sg.Window('Title of Window').Layout(layout)
button, values = window.Read()
sg.Popup('Hello {}'.format(values[0]))

View File

@ -15,6 +15,7 @@ else:
import tkFont import tkFont
import ScrolledText import ScrolledText
import types import types
import datetime import datetime
import textwrap import textwrap
@ -218,6 +219,7 @@ ELEM_TYPE_MENUBAR = 600
ELEM_TYPE_PROGRESS_BAR = 200 ELEM_TYPE_PROGRESS_BAR = 200
ELEM_TYPE_BLANK = 100 ELEM_TYPE_BLANK = 100
ELEM_TYPE_TABLE = 700 ELEM_TYPE_TABLE = 700
ELEM_TYPE_TREE = 800
ELEM_TYPE_ERROR = 666 ELEM_TYPE_ERROR = 666
# ------------------------- Popup Buttons Types ------------------------- # # ------------------------- Popup Buttons Types ------------------------- #
@ -2045,7 +2047,7 @@ class Menu(Element):
# Table # # Table #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
class Table(Element): class Table(Element):
def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, scrollable=None, font=None, justification='right', text_color=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None): def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, font=None, justification='right', text_color=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None):
self.Values = values self.Values = values
self.ColumnHeadings = headings self.ColumnHeadings = headings
self.ColumnsToDisplay = visible_column_map self.ColumnsToDisplay = visible_column_map
@ -2056,7 +2058,6 @@ class Table(Element):
self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.TextColor = text_color self.TextColor = text_color
self.Justification = justification self.Justification = justification
self.Scrollable = scrollable
self.InitialState = None self.InitialState = None
self.SelectMode = select_mode self.SelectMode = select_mode
self.DisplayRowNumbers = display_row_numbers self.DisplayRowNumbers = display_row_numbers
@ -2070,6 +2071,37 @@ class Table(Element):
super().__del__() super().__del__()
# ---------------------------------------------------------------------- #
# Tree #
# ---------------------------------------------------------------------- #
class Tree(Element):
def __init__(self, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, font=None, justification='right', text_color=None, background_color=None, num_rows=None, pad=None, key=None, tooltip=None):
self.ColumnHeadings = headings
self.ColumnsToDisplay = visible_column_map
self.ColumnWidths = col_widths
self.MaxColumnWidth = max_col_width
self.DefaultColumnWidth = def_col_width
self.AutoSizeColumns = auto_size_columns
self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.TextColor = text_color
self.Justification = justification
self.InitialState = None
self.SelectMode = select_mode
self.NumRows = num_rows
self.TKTreeview = None
super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, key=key, tooltip=tooltip)
return
def __del__(self):
super().__del__()
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
# Error Element # # Error Element #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
@ -2914,9 +2946,11 @@ else:
AddMenuItem(top_menu, item, element) AddMenuItem(top_menu, item, element)
i += 1 i += 1
# ------------------------------------------------------------------------------------------------------------------ #
# ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ #
# ===================================== TK CODE STARTS HERE ====================================================== # # ===================================== TK CODE STARTS HERE ====================================================== #
# ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ #
# ------------------------------------------------------------------------------------------------------------------ #
def PackFormIntoFrame(form, containing_frame, toplevel_form): def PackFormIntoFrame(form, containing_frame, toplevel_form):
def CharWidthInPixels(): def CharWidthInPixels():
@ -3560,6 +3594,48 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element.TKTreeview.pack(side=tk.LEFT,expand=True, padx=0, pady=0, fill='both') element.TKTreeview.pack(side=tk.LEFT,expand=True, padx=0, pady=0, fill='both')
if element.Tooltip is not None: if element.Tooltip is not None:
element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
# ------------------------- Tree element ------------------------- #
elif element_type == ELEM_TYPE_TREE:
width, height = element_size
if element.Justification == 'left': # justification
anchor = tk.W
elif element.Justification == 'right':
anchor = tk.E
else:
anchor = tk.CENTER
if element.ColumnsToDisplay is None: # Which cols to display
displaycolumns = element.ColumnHeadings
else:
displaycolumns = []
for i, should_display in enumerate(element.ColumnsToDisplay):
if should_display:
displaycolumns.append(element.ColumnHeadings[i])
column_headings= element.ColumnHeadings
# ------------- GET THE TREEVIEW WIDGET -------------
element.TKTreeview = ttk.Treeview(tk_row_frame, columns=column_headings,
displaycolumns=displaycolumns, show='headings', height=height, selectmode=element.SelectMode)
treeview = element.TKTreeview
for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings
treeview.heading(heading, text=heading)
if element.AutoSizeColumns:
width = min(element.MaxColumnWidth, len(heading))
else:
try:
width = element.ColumnWidths[i]
except:
width = element.DefaultColumnWidth
treeview.column(heading, width=width*CharWidthInPixels(), anchor=anchor)
# ----- configure colors -----
if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
ttk.Style().configure("Treeview", background=element.BackgroundColor, fieldbackground=element.BackgroundColor)
if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
ttk.Style().configure("Treeview", foreground=element.TextColor)
element.TKTreeview.pack(side=tk.LEFT,expand=True, padx=0, pady=0, fill='both')
if element.Tooltip is not None: # tooltip
element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
#............................DONE WITH ROW pack the row of widgets ..........................# #............................DONE WITH ROW pack the row of widgets ..........................#
# done with row, pack the row of widgets # done with row, pack the row of widgets
# tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0])
@ -4385,7 +4461,6 @@ def SetOptions(icon=None, button_color=None, element_size=(None,None), button_el
# of the elements. # # of the elements. #
############################################################## ##############################################################
LOOK_AND_FEEL_TABLE = {'SystemDefault': {'BACKGROUND' : COLOR_SYSTEM_DEFAULT, 'TEXT': COLOR_SYSTEM_DEFAULT, 'INPUT': COLOR_SYSTEM_DEFAULT,'TEXT_INPUT' : COLOR_SYSTEM_DEFAULT, 'SCROLL': COLOR_SYSTEM_DEFAULT, 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, 'PROGRESS': COLOR_SYSTEM_DEFAULT, 'BORDER': 1,'SLIDER_DEPTH':1, 'PROGRESS_DEPTH':0}, LOOK_AND_FEEL_TABLE = {'SystemDefault': {'BACKGROUND' : COLOR_SYSTEM_DEFAULT, 'TEXT': COLOR_SYSTEM_DEFAULT, 'INPUT': COLOR_SYSTEM_DEFAULT,'TEXT_INPUT' : COLOR_SYSTEM_DEFAULT, 'SCROLL': COLOR_SYSTEM_DEFAULT, 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, 'PROGRESS': COLOR_SYSTEM_DEFAULT, 'BORDER': 1,'SLIDER_DEPTH':1, 'PROGRESS_DEPTH':0},
# ∩(^-^)∩
'Topanga': {'BACKGROUND': '#282923', 'TEXT': '#E7DB74', 'INPUT': '#393a32', 'Topanga': {'BACKGROUND': '#282923', 'TEXT': '#E7DB74', 'INPUT': '#393a32',
'TEXT_INPUT': '#E7C855','SCROLL': '#E7C855', 'BUTTON': ('#E7C855', '#284B5A'), 'TEXT_INPUT': '#E7C855','SCROLL': '#E7C855', 'BUTTON': ('#E7C855', '#284B5A'),
'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0}, 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0},

View File

@ -27,6 +27,7 @@ else:
import tkinter.font import tkinter.font
import tkinter.scrolledtext import tkinter.scrolledtext
import types import types
import datetime import datetime
import textwrap import textwrap
@ -149,6 +150,14 @@ TITLE_LOCATION_TOP_RIGHT = tk.NE
TITLE_LOCATION_BOTTOM_LEFT = tk.SW TITLE_LOCATION_BOTTOM_LEFT = tk.SW
TITLE_LOCATION_BOTTOM_RIGHT = tk.SE TITLE_LOCATION_BOTTOM_RIGHT = tk.SE
THEME_DEFAULT = 'default'
THEME_WINNATIVE = 'winnative'
THEME_CLAM = 'clam'
THEME_ALT = 'alt'
THEME_CLASSIC = 'classic'
THEME_VISTA = 'vista'
THEME_XPNATIVE = 'xpnative'
# DEFAULT_METER_ORIENTATION = 'Vertical' # DEFAULT_METER_ORIENTATION = 'Vertical'
# ----====----====----==== Constants the user should NOT f-with ====----====----====----# # ----====----====----==== Constants the user should NOT f-with ====----====----====----#
@ -222,6 +231,7 @@ ELEM_TYPE_MENUBAR = 600
ELEM_TYPE_PROGRESS_BAR = 200 ELEM_TYPE_PROGRESS_BAR = 200
ELEM_TYPE_BLANK = 100 ELEM_TYPE_BLANK = 100
ELEM_TYPE_TABLE = 700 ELEM_TYPE_TABLE = 700
ELEM_TYPE_TREE = 800
ELEM_TYPE_ERROR = 666 ELEM_TYPE_ERROR = 666
# ------------------------- Popup Buttons Types ------------------------- # # ------------------------- Popup Buttons Types ------------------------- #
@ -623,7 +633,6 @@ class Listbox(Element):
self.Values = values self.Values = values
def SetValue(self, values): def SetValue(self, values):
for index, item in enumerate(self.Values): for index, item in enumerate(self.Values):
try: try:
@ -634,6 +643,9 @@ class Listbox(Element):
except: pass except: pass
self.DefaultValues = values self.DefaultValues = values
def GetListValues(self):
return self.Values
def __del__(self): def __del__(self):
try: try:
self.TKListBox.__del__() self.TKListBox.__del__()
@ -897,7 +909,7 @@ T = Text
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
class TKProgressBar(object): class TKProgressBar(object):
def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], style=DEFAULT_PROGRESS_BAR_STYLE, relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH, orientation='horizontal', BarColor=(None,None)): def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], style=DEFAULT_PROGRESS_BAR_STYLE, relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH, orientation='horizontal', BarColor=(None,None), key=None):
self.Length = length self.Length = length
self.Width = width self.Width = width
self.Max = max self.Max = max
@ -909,11 +921,11 @@ class TKProgressBar(object):
s = tkinter.ttk.Style() s = tkinter.ttk.Style()
s.theme_use(style) s.theme_use(style)
if BarColor != COLOR_SYSTEM_DEFAULT: if BarColor != COLOR_SYSTEM_DEFAULT:
s.configure(str(length)+str(width)+"my.Horizontal.TProgressbar", background=BarColor[0], troughcolor=BarColor[1], troughrelief=relief, borderwidth=border_width, thickness=width) s.configure(str(key)+"my.Horizontal.TProgressbar", background=BarColor[0], troughcolor=BarColor[1], troughrelief=relief, borderwidth=border_width, thickness=width)
else: else:
s.configure(str(length)+str(width)+"my.Horizontal.TProgressbar", troughrelief=relief, borderwidth=border_width, thickness=width) s.configure(str(key)+"my.Horizontal.TProgressbar", troughrelief=relief, borderwidth=border_width, thickness=width)
self.TKProgressBarForReal = tkinter.ttk.Progressbar(root, maximum=self.Max, style=str(length)+str(width)+'my.Horizontal.TProgressbar', length=length, orient=tk.HORIZONTAL, mode='determinate') self.TKProgressBarForReal = tkinter.ttk.Progressbar(root, maximum=self.Max, style=str(key)+'my.Horizontal.TProgressbar', length=length, orient=tk.HORIZONTAL, mode='determinate')
else: else:
s = tkinter.ttk.Style() s = tkinter.ttk.Style()
s.theme_use(style) s.theme_use(style)
@ -1154,8 +1166,7 @@ class Button(Element):
self.ParentForm.LastButtonClicked = self.ButtonText self.ParentForm.LastButtonClicked = self.ButtonText
self.ParentForm.FormRemainedOpen = True self.ParentForm.FormRemainedOpen = True
self.ParentForm.TKroot.quit() # kick the users out of the mainloop self.ParentForm.TKroot.quit() # kick the users out of the mainloop
elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # this is a return type button so GET RESULTS and destroy window elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop
# if the form is tabbed, must collect all form's results and destroy all forms
self.ParentForm._Close() self.ParentForm._Close()
if self.ParentForm.NonBlocking: if self.ParentForm.NonBlocking:
self.ParentForm.TKroot.destroy() self.ParentForm.TKroot.destroy()
@ -1494,7 +1505,7 @@ class Frame(Element):
# Tab # # Tab #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
class Tab(Element): class Tab(Element):
def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, border_width=None, key=None, tooltip=None): def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, disabled=False, border_width=None, key=None, tooltip=None):
self.UseDictionary = False self.UseDictionary = False
self.ReturnValues = None self.ReturnValues = None
@ -1506,6 +1517,9 @@ class Tab(Element):
self.TKFrame = None self.TKFrame = None
self.Title = title self.Title = title
self.BorderWidth = border_width self.BorderWidth = border_width
self.Disabled = disabled
self.ParentNotebook = None
self.TabID = None
self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.Layout(layout) self.Layout(layout)
@ -1531,6 +1545,15 @@ class Tab(Element):
def Layout(self, rows): def Layout(self, rows):
for row in rows: for row in rows:
self.AddRow(*row) self.AddRow(*row)
return self
def Update(self, disabled = None): # TODO Disable / enable of tabs is not complete
if disabled is None:
return
self.Disabled = disabled
state = 'disabled' if disabled is True else 'normal'
self.ParentNotebook.tab(self.TabID, state=state)
return self
def _GetElementAtLocation(self, location): def _GetElementAtLocation(self, location):
(row_num,col_num) = location (row_num,col_num) = location
@ -1551,7 +1574,7 @@ class Tab(Element):
# TabGroup # # TabGroup #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
class TabGroup(Element): class TabGroup(Element):
def __init__(self, layout, tab_location=None, title_color=None, background_color=None, font=None, change_submits=False, pad=None, border_width=None, key=None, tooltip=None): def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None, font=None, change_submits=False, pad=None, border_width=None, theme=None, key=None, tooltip=None):
self.UseDictionary = False self.UseDictionary = False
self.ReturnValues = None self.ReturnValues = None
@ -1559,9 +1582,12 @@ class TabGroup(Element):
self.ReturnValuesDictionary = {} self.ReturnValuesDictionary = {}
self.DictionaryKeyCounter = 0 self.DictionaryKeyCounter = 0
self.ParentWindow = None self.ParentWindow = None
self.SelectedTitleColor = selected_title_color
self.Rows = [] self.Rows = []
self.TKNotebook = None self.TKNotebook = None
self.TabCount = 0
self.BorderWidth = border_width self.BorderWidth = border_width
self.Theme = theme
self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.ChangeSubmits = change_submits self.ChangeSubmits = change_submits
self.TabLocation = tab_location self.TabLocation = tab_location
@ -2033,7 +2059,7 @@ class Menu(Element):
# Table # # Table #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
class Table(Element): class Table(Element):
def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, scrollable=None, font=None, justification='right', text_color=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None): def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, font=None, justification='right', text_color=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None):
self.Values = values self.Values = values
self.ColumnHeadings = headings self.ColumnHeadings = headings
self.ColumnsToDisplay = visible_column_map self.ColumnsToDisplay = visible_column_map
@ -2044,7 +2070,6 @@ class Table(Element):
self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.TextColor = text_color self.TextColor = text_color
self.Justification = justification self.Justification = justification
self.Scrollable = scrollable
self.InitialState = None self.InitialState = None
self.SelectMode = select_mode self.SelectMode = select_mode
self.DisplayRowNumbers = display_row_numbers self.DisplayRowNumbers = display_row_numbers
@ -2058,6 +2083,37 @@ class Table(Element):
super().__del__() super().__del__()
# ---------------------------------------------------------------------- #
# Tree #
# ---------------------------------------------------------------------- #
class Tree(Element):
def __init__(self, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, font=None, justification='right', text_color=None, background_color=None, num_rows=None, pad=None, key=None, tooltip=None):
self.ColumnHeadings = headings
self.ColumnsToDisplay = visible_column_map
self.ColumnWidths = col_widths
self.MaxColumnWidth = max_col_width
self.DefaultColumnWidth = def_col_width
self.AutoSizeColumns = auto_size_columns
self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR
self.TextColor = text_color
self.Justification = justification
self.InitialState = None
self.SelectMode = select_mode
self.NumRows = num_rows
self.TKTreeview = None
super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, key=key, tooltip=tooltip)
return
def __del__(self):
super().__del__()
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
# Error Element # # Error Element #
# ---------------------------------------------------------------------- # # ---------------------------------------------------------------------- #
@ -2078,11 +2134,9 @@ class ErrorElement(Element):
return self return self
def MenuItemChosenCallback(self, item_chosen): def Get(self):
# print('IN MENU ITEM CALLBACK', item_chosen) return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!'
self.ParentForm.LastButtonClicked = item_chosen
self.ParentForm.FormRemainedOpen = True
self.ParentForm.TKroot.quit() # kick the users out of the mainloop
def __del__(self): def __del__(self):
super().__del__() super().__del__()
@ -2227,9 +2281,12 @@ class Window(object):
else: else:
window = self window = self
if window: if window:
window._Close() if window.NonBlocking:
self.TKroot.quit() self.CloseNonBlockingForm()
self.RootNeedsDestroying = True else:
window._Close()
self.TKroot.quit()
self.RootNeedsDestroying = True
except: except:
pass pass
@ -2472,6 +2529,14 @@ class UberForm(object):
def __del__(self): def __del__(self):
return return
# ################################################################################
# ################################################################################
# END OF ELEMENT DEFINITIONS
# ################################################################################
# ################################################################################
# =========================================================================== # # =========================================================================== #
# Button Lazy Functions so the caller doesn't have to define a bunch of stuff # # Button Lazy Functions so the caller doesn't have to define a bunch of stuff #
# =========================================================================== # # =========================================================================== #
@ -2893,9 +2958,11 @@ else:
AddMenuItem(top_menu, item, element) AddMenuItem(top_menu, item, element)
i += 1 i += 1
# ------------------------------------------------------------------------------------------------------------------ #
# ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ #
# ===================================== TK CODE STARTS HERE ====================================================== # # ===================================== TK CODE STARTS HERE ====================================================== #
# ------------------------------------------------------------------------------------------------------------------ # # ------------------------------------------------------------------------------------------------------------------ #
# ------------------------------------------------------------------------------------------------------------------ #
def PackFormIntoFrame(form, containing_frame, toplevel_form): def PackFormIntoFrame(form, containing_frame, toplevel_form):
def CharWidthInPixels(): def CharWidthInPixels():
@ -3160,7 +3227,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
# ------------------------- LISTBOX element ------------------------- # # ------------------------- LISTBOX element ------------------------- #
elif element_type == ELEM_TYPE_INPUT_LISTBOX: elif element_type == ELEM_TYPE_INPUT_LISTBOX:
max_line_len = max([len(str(l)) for l in element.Values]) max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) != 0 else 0
if auto_size_text is False: width=element_size[0] if auto_size_text is False: width=element_size[0]
else: width = max_line_len else: width = max_line_len
listbox_frame = tk.Frame(tk_row_frame) listbox_frame = tk.Frame(tk_row_frame)
@ -3242,7 +3309,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
bar_color = element.BarColor bar_color = element.BarColor
else: else:
bar_color = DEFAULT_PROGRESS_BAR_COLOR bar_color = DEFAULT_PROGRESS_BAR_COLOR
element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width, orientation=direction, BarColor=bar_color, border_width=element.BorderWidth, relief=element.Relief, style=element.BarStyle ) element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width, orientation=direction, BarColor=bar_color, border_width=element.BorderWidth, relief=element.Relief, style=element.BarStyle, key=element.Key )
element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
# ------------------------- INPUT RADIO BUTTON element ------------------------- # # ------------------------- INPUT RADIO BUTTON element ------------------------- #
elif element_type == ELEM_TYPE_INPUT_RADIO: elif element_type == ELEM_TYPE_INPUT_RADIO:
@ -3383,15 +3450,27 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
elif element_type == ELEM_TYPE_TAB: elif element_type == ELEM_TYPE_TAB:
element.TKFrame = tk.Frame(form.TKNotebook) element.TKFrame = tk.Frame(form.TKNotebook)
PackFormIntoFrame(element, element.TKFrame, toplevel_form) PackFormIntoFrame(element, element.TKFrame, toplevel_form)
form.TKNotebook.add(element.TKFrame, text=element.Title) if element.Disabled:
form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled')
else:
form.TKNotebook.add(element.TKFrame, text=element.Title)
form.TKNotebook.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) form.TKNotebook.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1])
element.ParentNotebook = form.TKNotebook
element.TabID = form.TabCount
form.TabCount += 1
if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None:
element.TKFrame.configure(background=element.BackgroundColor, element.TKFrame.configure(background=element.BackgroundColor,
highlightbackground=element.BackgroundColor, highlightbackground=element.BackgroundColor,
highlightcolor=element.BackgroundColor) highlightcolor=element.BackgroundColor)
# if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None:
# element.TKFrame.configure(foreground=element.TextColor) # element.TKFrame.configure(foreground=element.TextColor)
# ttk.Style().configure("TNotebook", background='red')
# ttk.Style().map("TNotebook.Tab", background=[("selected", 'orange')],
# foreground=[("selected", 'green')])
# ttk.Style().configure("TNotebook.Tab", background='blue', foreground='yellow')
if element.BorderWidth is not None: if element.BorderWidth is not None:
element.TKFrame.configure(borderwidth=element.BorderWidth) element.TKFrame.configure(borderwidth=element.BorderWidth)
if element.Tooltip is not None: if element.Tooltip is not None:
@ -3400,20 +3479,37 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
# ------------------------- TabGroup element ------------------------- # # ------------------------- TabGroup element ------------------------- #
elif element_type == ELEM_TYPE_TAB_GROUP: elif element_type == ELEM_TYPE_TAB_GROUP:
custom_style = str(element.Key)+'customtab.TNotebook'
style = tkinter.ttk.Style(tk_row_frame)
if element.Theme is not None:
style.theme_use(element.Theme)
if element.TabLocation is not None: if element.TabLocation is not None:
style = tkinter.ttk.Style(tk_row_frame) position_dict = {'left':'w','right':'e', 'top':'n', 'bottom':'s', 'lefttop':'wn', 'leftbottom':'ws', 'righttop':'en', 'rightbottom':'es', 'bottomleft':'sw', 'bottomright':'se', 'topleft':'nw', 'topright':'ne'}
if element.TabLocation == 'left': try:
style.configure('customtab.TNotebook', tabposition='ws') tab_position = position_dict[element.TabLocation]
elif element.TabLocation == 'right': except:
style.configure('customtab.TNotebook', tabposition='es') tab_position = position_dict['top']
elif element.TabLocation == 'top': style.configure(custom_style, tabposition=tab_position)
style.configure('customtab.TNotebook', tabposition='nw')
elif element.TabLocation == 'bottom':
style.configure('customtab.TNotebook', tabposition='sw')
element.TKNotebook = tkinter.ttk.Notebook(tk_row_frame, style='customtab.TNotebook') if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
else: style.configure(custom_style, background=element.BackgroundColor, foreground='purple')
element.TKNotebook = tkinter.ttk.Notebook(tk_row_frame)
# style.theme_create("yummy", parent="alt", settings={
# "TNotebook": {"configure": {"tabmargins": [2, 5, 2, 0]}},
# "TNotebook.Tab": {
# "configure": {"padding": [5, 1], "background": mygreen},
# "map": {"background": [("selected", myred)],
# "expand": [("selected", [1, 1, 1, 0])]}}})
# style.configure(custom_style+'.Tab', background='red')
if element.SelectedTitleColor != None:
style.map(custom_style+'.Tab', foreground=[("selected",element.SelectedTitleColor)])
if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
style.configure(custom_style+'.Tab', foreground=element.TextColor)
# style.configure(custom_style, background='blue', foreground='yellow')
element.TKNotebook = tkinter.ttk.Notebook(tk_row_frame, style=custom_style)
PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form) PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form)
@ -3510,6 +3606,48 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
element.TKTreeview.pack(side=tk.LEFT,expand=True, padx=0, pady=0, fill='both') element.TKTreeview.pack(side=tk.LEFT,expand=True, padx=0, pady=0, fill='both')
if element.Tooltip is not None: if element.Tooltip is not None:
element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
# ------------------------- Tree element ------------------------- #
elif element_type == ELEM_TYPE_TREE:
width, height = element_size
if element.Justification == 'left': # justification
anchor = tk.W
elif element.Justification == 'right':
anchor = tk.E
else:
anchor = tk.CENTER
if element.ColumnsToDisplay is None: # Which cols to display
displaycolumns = element.ColumnHeadings
else:
displaycolumns = []
for i, should_display in enumerate(element.ColumnsToDisplay):
if should_display:
displaycolumns.append(element.ColumnHeadings[i])
column_headings= element.ColumnHeadings
# ------------- GET THE TREEVIEW WIDGET -------------
element.TKTreeview = tkinter.ttk.Treeview(tk_row_frame, columns=column_headings,
displaycolumns=displaycolumns, show='headings', height=height, selectmode=element.SelectMode)
treeview = element.TKTreeview
for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings
treeview.heading(heading, text=heading)
if element.AutoSizeColumns:
width = min(element.MaxColumnWidth, len(heading))
else:
try:
width = element.ColumnWidths[i]
except:
width = element.DefaultColumnWidth
treeview.column(heading, width=width*CharWidthInPixels(), anchor=anchor)
# ----- configure colors -----
if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
tkinter.ttk.Style().configure("Treeview", background=element.BackgroundColor, fieldbackground=element.BackgroundColor)
if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT:
tkinter.ttk.Style().configure("Treeview", foreground=element.TextColor)
element.TKTreeview.pack(side=tk.LEFT,expand=True, padx=0, pady=0, fill='both')
if element.Tooltip is not None: # tooltip
element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME)
#............................DONE WITH ROW pack the row of widgets ..........................# #............................DONE WITH ROW pack the row of widgets ..........................#
# done with row, pack the row of widgets # done with row, pack the row of widgets
# tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0])
@ -3961,7 +4099,7 @@ class DebugWin(object):
self.output_element = Output(size=win_size) self.output_element = Output(size=win_size)
self.form_rows = [[Text('EasyPrint Output')], self.form_rows = [[Text('EasyPrint Output')],
[self.output_element], [self.output_element],
[Quit()]] [DummyButton('Quit')]]
self.form.AddRows(self.form_rows) self.form.AddRows(self.form_rows)
self.form.Show(non_blocking=True) # Show a ;non-blocking form, returns immediately self.form.Show(non_blocking=True) # Show a ;non-blocking form, returns immediately
return return
@ -4406,13 +4544,10 @@ def SetOptions(icon=None, button_color=None, element_size=(None,None), button_el
# Predefined settings that will change the colors and styles # # Predefined settings that will change the colors and styles #
# of the elements. # # of the elements. #
############################################################## ##############################################################
def ChangeLookAndFeel(index): LOOK_AND_FEEL_TABLE = {'SystemDefault': {'BACKGROUND' : COLOR_SYSTEM_DEFAULT, 'TEXT': COLOR_SYSTEM_DEFAULT, 'INPUT': COLOR_SYSTEM_DEFAULT,'TEXT_INPUT' : COLOR_SYSTEM_DEFAULT, 'SCROLL': COLOR_SYSTEM_DEFAULT, 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, 'PROGRESS': COLOR_SYSTEM_DEFAULT, 'BORDER': 1,'SLIDER_DEPTH':1, 'PROGRESS_DEPTH':0},
if sys.platform == 'darwin': 'Topanga': {'BACKGROUND': '#282923', 'TEXT': '#E7DB74', 'INPUT': '#393a32',
print('*** Changing look and feel is not supported on Mac platform ***') 'TEXT_INPUT': '#E7C855','SCROLL': '#E7C855', 'BUTTON': ('#E7C855', '#284B5A'),
return 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0},
# look and feel table
look_and_feel = {'SystemDefault': {'BACKGROUND' : COLOR_SYSTEM_DEFAULT, 'TEXT': COLOR_SYSTEM_DEFAULT, 'INPUT': COLOR_SYSTEM_DEFAULT,'TEXT_INPUT' : COLOR_SYSTEM_DEFAULT, 'SCROLL': COLOR_SYSTEM_DEFAULT, 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, 'PROGRESS': COLOR_SYSTEM_DEFAULT, 'BORDER': 1,'SLIDER_DEPTH':1, 'PROGRESS_DEPTH':0},
'GreenTan': {'BACKGROUND' : '#9FB8AD', 'TEXT': COLOR_SYSTEM_DEFAULT, 'INPUT':'#F7F3EC','TEXT_INPUT' : 'black','SCROLL': '#F7F3EC', 'BUTTON': ('white', '#475841'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0}, 'GreenTan': {'BACKGROUND' : '#9FB8AD', 'TEXT': COLOR_SYSTEM_DEFAULT, 'INPUT':'#F7F3EC','TEXT_INPUT' : 'black','SCROLL': '#F7F3EC', 'BUTTON': ('white', '#475841'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0},
@ -4497,8 +4632,18 @@ def ChangeLookAndFeel(index):
'TealMono': {'BACKGROUND': '#a8cfdd', 'TEXT': 'black', 'INPUT': '#dfedf2','SCROLL': '#dfedf2', 'TEXT_INPUT' : 'black', 'BUTTON': ('white', '#183440'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0} 'TealMono': {'BACKGROUND': '#a8cfdd', 'TEXT': 'black', 'INPUT': '#dfedf2','SCROLL': '#dfedf2', 'TEXT_INPUT' : 'black', 'BUTTON': ('white', '#183440'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1,'SLIDER_DEPTH':0, 'PROGRESS_DEPTH':0}
} }
def ChangeLookAndFeel(index):
global LOOK_AND_FEEL_TABLE
if sys.platform == 'darwin':
print('*** Changing look and feel is not supported on Mac platform ***')
return
# look and feel table
try: try:
colors = look_and_feel[index] colors = LOOK_AND_FEEL_TABLE[index]
SetOptions(background_color=colors['BACKGROUND'], SetOptions(background_color=colors['BACKGROUND'],
text_element_background_color=colors['BACKGROUND'], text_element_background_color=colors['BACKGROUND'],
@ -4607,7 +4752,7 @@ def Popup(*args, **_3to2kwargs):
else: else:
local_line_width = MESSAGE_BOX_LINE_WIDTH local_line_width = MESSAGE_BOX_LINE_WIDTH
title = args_to_print[0] if args_to_print[0] is not None else 'None' title = args_to_print[0] if args_to_print[0] is not None else 'None'
form = Window(title, auto_size_text=True, background_color=background_color, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) window = Window(title, auto_size_text=True, background_color=background_color, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
max_line_total, total_lines = 0,0 max_line_total, total_lines = 0,0
for message in args_to_print: for message in args_to_print:
# fancy code to check if string and convert if not is not need. Just always convert to string :-) # fancy code to check if string and convert if not is not need. Just always convert to string :-)
@ -4623,34 +4768,32 @@ def Popup(*args, **_3to2kwargs):
max_line_total = max(max_line_total, width_used) max_line_total = max(max_line_total, width_used)
# height = _GetNumLinesNeeded(message, width_used) # height = _GetNumLinesNeeded(message, width_used)
height = message_wrapped_lines height = message_wrapped_lines
form.AddRow(Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) window.AddRow(Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color))
total_lines += height total_lines += height
pad = max_line_total-15 if max_line_total > 15 else 1
pad =1
if non_blocking: if non_blocking:
PopupButton = DummyButton PopupButton = DummyButton # important to use or else button will close other windows too!
else: else:
PopupButton = SimpleButton PopupButton = Button
# show either an OK or Yes/No depending on paramater # show either an OK or Yes/No depending on paramater
if button_type is POPUP_BUTTONS_YES_NO: if button_type is POPUP_BUTTONS_YES_NO:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True), PopupButton('No', button_color=button_color)) window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20,5),3)), PopupButton('No', button_color=button_color))
elif button_type is POPUP_BUTTONS_CANCELLED: elif button_type is POPUP_BUTTONS_CANCELLED:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True)) window.AddRow(PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20,0),3)))
elif button_type is POPUP_BUTTONS_ERROR: elif button_type is POPUP_BUTTONS_ERROR:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True)) window.AddRow(PopupButton('Error', size=(6,1), button_color=button_color, focus=True, bind_return_key=True, pad=((20,0),3)))
elif button_type is POPUP_BUTTONS_OK_CANCEL: elif button_type is POPUP_BUTTONS_OK_CANCEL:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True), window.AddRow(PopupButton('OK', size=(5,1), button_color=button_color, focus=True, bind_return_key=True),
PopupButton('Cancel', size=(5, 1), button_color=button_color)) PopupButton('Cancel', size=(5,1), button_color=button_color))
elif button_type is POPUP_BUTTONS_NO_BUTTONS: elif button_type is POPUP_BUTTONS_NO_BUTTONS:
pass pass
else: else:
form.AddRow(Text('', size=(pad, 1), auto_size_text=False, background_color=background_color), PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True)) window.AddRow(PopupButton('OK', size=(5,1), button_color=button_color, focus=True, bind_return_key=True, pad=((20,0),3)))
if non_blocking: if non_blocking:
button, values = form.ReadNonBlocking() button, values = window.ReadNonBlocking()
else: else:
button, values = form.Show() button, values = window.Show()
return button return button
@ -4773,6 +4916,61 @@ def PopupNonBlocking(*args, **_3to2kwargs):
PopupNoWait = PopupNonBlocking PopupNoWait = PopupNonBlocking
# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup ---------------------------
def PopupQuick(*args, **_3to2kwargs):
if 'location' in _3to2kwargs: location = _3to2kwargs['location']; del _3to2kwargs['location']
else: location = (None,None)
if 'keep_on_top' in _3to2kwargs: keep_on_top = _3to2kwargs['keep_on_top']; del _3to2kwargs['keep_on_top']
else: keep_on_top = False
if 'grab_anywhere' in _3to2kwargs: grab_anywhere = _3to2kwargs['grab_anywhere']; del _3to2kwargs['grab_anywhere']
else: grab_anywhere = False
if 'no_titlebar' in _3to2kwargs: no_titlebar = _3to2kwargs['no_titlebar']; del _3to2kwargs['no_titlebar']
else: no_titlebar = False
if 'font' in _3to2kwargs: font = _3to2kwargs['font']; del _3to2kwargs['font']
else: font = None
if 'line_width' in _3to2kwargs: line_width = _3to2kwargs['line_width']; del _3to2kwargs['line_width']
else: line_width = None
if 'icon' in _3to2kwargs: icon = _3to2kwargs['icon']; del _3to2kwargs['icon']
else: icon = DEFAULT_WINDOW_ICON
if 'non_blocking' in _3to2kwargs: non_blocking = _3to2kwargs['non_blocking']; del _3to2kwargs['non_blocking']
else: non_blocking = True
if 'auto_close_duration' in _3to2kwargs: auto_close_duration = _3to2kwargs['auto_close_duration']; del _3to2kwargs['auto_close_duration']
else: auto_close_duration = 1
if 'auto_close' in _3to2kwargs: auto_close = _3to2kwargs['auto_close']; del _3to2kwargs['auto_close']
else: auto_close = True
if 'text_color' in _3to2kwargs: text_color = _3to2kwargs['text_color']; del _3to2kwargs['text_color']
else: text_color = None
if 'background_color' in _3to2kwargs: background_color = _3to2kwargs['background_color']; del _3to2kwargs['background_color']
else: background_color = None
if 'button_color' in _3to2kwargs: button_color = _3to2kwargs['button_color']; del _3to2kwargs['button_color']
else: button_color = None
if 'button_type' in _3to2kwargs: button_type = _3to2kwargs['button_type']; del _3to2kwargs['button_type']
else: button_type = POPUP_BUTTONS_OK
"""
Show Popup box that doesn't block and closes itself
:param args:
:param button_type:
:param button_color:
:param background_color:
:param text_color:
:param auto_close:
:param auto_close_duration:
:param non_blocking:
:param icon:
:param line_width:
:param font:
:param no_titlebar:
:param grab_anywhere:
:param keep_on_top:
:param location:
:return:
"""
Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, button_type=button_type,
auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, line_width=line_width,
font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location)
# --------------------------- PopupNoTitlebar --------------------------- # --------------------------- PopupNoTitlebar ---------------------------
def PopupNoTitlebar(*args, **_3to2kwargs): def PopupNoTitlebar(*args, **_3to2kwargs):
if 'location' in _3to2kwargs: location = _3to2kwargs['location']; del _3to2kwargs['location'] if 'location' in _3to2kwargs: location = _3to2kwargs['location']; del _3to2kwargs['location']

View File

@ -21,9 +21,9 @@
## Now supports both Python 2.7 & 3 ## Now supports both Python 2.7 & 3
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.9.0-red.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.9.1-red.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.1.0-blue.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.1.2-blue.svg?longCache=true&style=for-the-badge)
[Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142)
@ -2774,6 +2774,8 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 03.08.04 | Sept 30, 2018 - See release notes | 03.08.04 | Sept 30, 2018 - See release notes
| 03.09.00 | Oct 1, 2018 | | 03.09.00 | Oct 1, 2018 |
| 2.7 01.01.00 | Oct 1, 2018 | 2.7 01.01.00 | Oct 1, 2018
| 2.7 01.01.02 | Oct 8, 2018
| 03.09.01 | Oct 8, 2018
@ -2905,6 +2907,20 @@ It's official. There is a 2.7 version of PySimpleGUI!
* Python 2.7 got a TON of features . Look back to 1.0 release for the list * Python 2.7 got a TON of features . Look back to 1.0 release for the list
* Tab locations - Can place Tabs on top, bottom, left, right now instead of only the top * Tab locations - Can place Tabs on top, bottom, left, right now instead of only the top
### 3.9.1 & 1.1.2
* Tab features
* Themes
* Enable / Disable
* Tab text colors
* Selected tab color
* New GetListValues method for Listbox
* Can now have multiple progress bars in 1 window
* Fix for closing debug-output window with other windows open
* Topanga Look and Feel setting
* User can create new look and feel settings / can access the look and feel table
* New PopupQuick call. Shows a non-blocking popup window with auto-close
* Tree Element partially done (don't use despite it showing up)
### Upcoming ### Upcoming
Make suggestions people! Future release features Make suggestions people! Future release features
@ -2943,6 +2959,9 @@ Want to view your form's results as a dictionary instead of a list... no problem
You can also look up elements using their keys. This is an excellent way to update elements in reaction to another element. Call `form.FindElement(key)` to get the Element. You can also look up elements using their keys. This is an excellent way to update elements in reaction to another element. Call `form.FindElement(key)` to get the Element.
**Named / Optional Parameters**
This is a language feature that is featured **heavily** in all of the API calls, both functions and classes. Elements are configured, in-place, by setting one or more optional parameters. For example, a Text element's color is chosen by setting the optional `text_color` parameter.
## Author ## Author
MikeTheWatchGuy MikeTheWatchGuy
@ -2970,7 +2989,7 @@ GNU Lesser General Public License (LGPL 3) +
* one of the most critical constructs in PySimpleGUI * one of the most critical constructs in PySimpleGUI
* [venim](https://github.com/venim) code to doing Alt-Selections in menus, updating Combobox using index, request to disable windows (a really good idea), checkbox and tab submits on change, returning keys for elements that have change_submits set, ... * [venim](https://github.com/venim) code to doing Alt-Selections in menus, updating Combobox using index, request to disable windows (a really good idea), checkbox and tab submits on change, returning keys for elements that have change_submits set, ...
* [rtrrtr](https://github.com/rtrrtr) Helped get the 2.7 and 3.x code unified (big damned deal) * [rtrrtr](https://github.com/rtrrtr) Helped get the 2.7 and 3.x code unified (big damned deal)
* Tony Crewe (anthony.crewe@gmail.com) Generously provided his classroom materials that he has written to teach a GUI course. If you're an educator and want to trade materials with Tony, he would like to hear from you.
## How Do I ## How Do I
Finally, I must thank the fine folks at How Do I. Finally, I must thank the fine folks at How Do I.

View File

@ -21,9 +21,9 @@
## Now supports both Python 2.7 & 3 ## Now supports both Python 2.7 & 3
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.9.0-red.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-3.9.1-red.svg?longCache=true&style=for-the-badge)
![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.1.0-blue.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-1.1.2-blue.svg?longCache=true&style=for-the-badge)
[Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142) [Announcements of Latest Developments](https://github.com/MikeTheWatchGuy/PySimpleGUI/issues/142)
@ -2774,6 +2774,8 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 03.08.04 | Sept 30, 2018 - See release notes | 03.08.04 | Sept 30, 2018 - See release notes
| 03.09.00 | Oct 1, 2018 | | 03.09.00 | Oct 1, 2018 |
| 2.7 01.01.00 | Oct 1, 2018 | 2.7 01.01.00 | Oct 1, 2018
| 2.7 01.01.02 | Oct 8, 2018
| 03.09.01 | Oct 8, 2018
@ -2905,6 +2907,20 @@ It's official. There is a 2.7 version of PySimpleGUI!
* Python 2.7 got a TON of features . Look back to 1.0 release for the list * Python 2.7 got a TON of features . Look back to 1.0 release for the list
* Tab locations - Can place Tabs on top, bottom, left, right now instead of only the top * Tab locations - Can place Tabs on top, bottom, left, right now instead of only the top
### 3.9.1 & 1.1.2
* Tab features
* Themes
* Enable / Disable
* Tab text colors
* Selected tab color
* New GetListValues method for Listbox
* Can now have multiple progress bars in 1 window
* Fix for closing debug-output window with other windows open
* Topanga Look and Feel setting
* User can create new look and feel settings / can access the look and feel table
* New PopupQuick call. Shows a non-blocking popup window with auto-close
* Tree Element partially done (don't use despite it showing up)
### Upcoming ### Upcoming
Make suggestions people! Future release features Make suggestions people! Future release features
@ -2943,6 +2959,9 @@ Want to view your form's results as a dictionary instead of a list... no problem
You can also look up elements using their keys. This is an excellent way to update elements in reaction to another element. Call `form.FindElement(key)` to get the Element. You can also look up elements using their keys. This is an excellent way to update elements in reaction to another element. Call `form.FindElement(key)` to get the Element.
**Named / Optional Parameters**
This is a language feature that is featured **heavily** in all of the API calls, both functions and classes. Elements are configured, in-place, by setting one or more optional parameters. For example, a Text element's color is chosen by setting the optional `text_color` parameter.
## Author ## Author
MikeTheWatchGuy MikeTheWatchGuy
@ -2970,7 +2989,7 @@ GNU Lesser General Public License (LGPL 3) +
* one of the most critical constructs in PySimpleGUI * one of the most critical constructs in PySimpleGUI
* [venim](https://github.com/venim) code to doing Alt-Selections in menus, updating Combobox using index, request to disable windows (a really good idea), checkbox and tab submits on change, returning keys for elements that have change_submits set, ... * [venim](https://github.com/venim) code to doing Alt-Selections in menus, updating Combobox using index, request to disable windows (a really good idea), checkbox and tab submits on change, returning keys for elements that have change_submits set, ...
* [rtrrtr](https://github.com/rtrrtr) Helped get the 2.7 and 3.x code unified (big damned deal) * [rtrrtr](https://github.com/rtrrtr) Helped get the 2.7 and 3.x code unified (big damned deal)
* Tony Crewe (anthony.crewe@gmail.com) Generously provided his classroom materials that he has written to teach a GUI course. If you're an educator and want to trade materials with Tony, he would like to hear from you.
## How Do I ## How Do I
Finally, I must thank the fine folks at How Do I. Finally, I must thank the fine folks at How Do I.