diff --git a/Demo_All_Widgets.py b/Demo_All_Widgets.py index d4cee3c3..ca10c88d 100644 --- a/Demo_All_Widgets.py +++ b/Demo_All_Widgets.py @@ -14,18 +14,21 @@ layout = [ [sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25))], [sg.Text('Here is some text.... and a place to enter text')], [sg.InputText('This is my text')], + + [sg.Frame([ [sg.Checkbox('Checkbox'), sg.Checkbox('My second checkbox!', default=True)], - [sg.Radio('My first Radio! ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")], + [sg.Radio('My first Radio! ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")]], title='Options',text_color='red', relief=sg.RELIEF_RAISED)], [sg.Multiline(default_text='This is the default Text should you decide not to type anything', size=(35, 3)), sg.Multiline(default_text='A second multi-line', size=(35, 3))], [sg.InputCombo(('Combobox 1', 'Combobox 2'), size=(20, 1)), sg.Slider(range=(1, 100), orientation='h', size=(34, 20), default_value=85)], [sg.InputOptionMenu(('Menu Option 1', 'Menu Option 2', 'Menu Option 3'))], [sg.Listbox(values=('Listbox 1', 'Listbox 2', 'Listbox 3'), size=(30, 3)), + sg.Frame([[ sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=25), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=75), sg.Slider(range=(1, 100), orientation='v', size=(5, 20), default_value=10), - sg.Column(column1, background_color='#F7F3EC')], + sg.Column(column1, background_color='#F7F3EC')]],'Labelled Group', text_color='purple')], [sg.Text('_' * 80)], [sg.Text('Choose A Folder', size=(35, 1))], [sg.Text('Your Folder', size=(15, 1), auto_size_text=False, justification='right'), @@ -35,6 +38,6 @@ layout = [ button, values = form.LayoutAndRead(layout) -sg.Popup('Title', 'The results of the form.', 'The button clicked was "{}"'.format(button), 'The values are', values) +sg.PopupAutoClose('Title', 'The results of the form.', 'The button clicked was "{}"'.format(button), 'The values are', values, auto_close_duration=1) diff --git a/Demo_Button_Click.py b/Demo_Button_Click.py index 2a6b89ec..4a4ba306 100644 --- a/Demo_Button_Click.py +++ b/Demo_Button_Click.py @@ -15,7 +15,7 @@ layout = [ form = sg.FlexForm("Button Click", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False, default_button_element_size=(12,1)) form.Layout(layout) -form.Finalize() +form.Finalize() # only needed if want to diable elements prior to showing form form.FindElement('submit').Update(disabled=True) diff --git a/Demo_Button_States.py b/Demo_Button_States.py index fa5d5d9f..0974fdec 100644 --- a/Demo_Button_States.py +++ b/Demo_Button_States.py @@ -11,10 +11,10 @@ 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))], [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.ReadFormButton('Start', button_color=('white', 'black'), key='start'), - sg.ReadFormButton('Stop', button_color=('gray34', 'black'), key='stop'), - sg.ReadFormButton('Reset', button_color=('gray', 'firebrick3'), key='reset'), - sg.ReadFormButton('Submit', button_color=('gray34', 'springgreen4'), key='submit')] + [sg.ReadFormButton('Start', button_color=('white', 'black'), key='Start'), + sg.ReadFormButton('Stop', button_color=('white', 'black'), disabled=True, key='Stop'), + sg.ReadFormButton('Reset', button_color=('gray', 'firebrick3'), key='Reset'), + sg.ReadFormButton('Submit', button_color=('gray34', 'springgreen4'), key='Submit')] ] form = sg.FlexForm("Time Tracker", default_element_size=(12,1), text_justification='r', auto_size_text=False, auto_size_buttons=False, @@ -23,30 +23,31 @@ form.Layout(layout) recording = have_data = False while True: button, values = form.Read() + print(button) if button is None: exit(69) if button is 'Start': - form.FindElement('start').Update(button_color=('gray34','black')) - form.FindElement('stop').Update(button_color=('white', 'black')) - form.FindElement('reset').Update(button_color=('white', 'firebrick3')) + form.FindElement('Start').Update(disabled=True) + form.FindElement('Stop').Update(disabled=False) + form.FindElement('Reset').Update(disabled=False) recording = True elif button is 'Stop' and recording: - form.FindElement('stop').Update(button_color=('gray34','black')) - form.FindElement('start').Update(button_color=('white', 'black')) - form.FindElement('submit').Update(button_color=('white', 'springgreen4')) + form.FindElement('Stop').Update(disabled=True) + form.FindElement('Start').Update(disabled=False) + form.FindElement('Submit').Update(disabled=False) recording = False have_data = True elif button is 'Reset': - form.FindElement('stop').Update(button_color=('gray34','black')) - form.FindElement('start').Update(button_color=('white', 'black')) - form.FindElement('submit').Update(button_color=('gray34', 'springgreen4')) - form.FindElement('reset').Update(button_color=('gray34', 'firebrick3')) + form.FindElement('Stop').Update(button_color=('gray34','black')) + form.FindElement('Start').Update(button_color=('white', 'black')) + form.FindElement('Submit').Update(button_color=('gray34', 'springgreen4')) + form.FindElement('Reset').Update(button_color=('gray34', 'firebrick3')) recording = False have_data = False elif button is 'Submit' and have_data: - form.FindElement('stop').Update(button_color=('gray34','black')) - form.FindElement('start').Update(button_color=('white', 'black')) - form.FindElement('submit').Update(button_color=('gray34', 'springgreen4')) - form.FindElement('reset').Update(button_color=('gray34', 'firebrick3')) + form.FindElement('Stop').Update(button_color=('gray34','black')) + form.FindElement('Start').Update(button_color=('white', 'black')) + form.FindElement('Submit').Update(button_color=('gray34', 'springgreen4')) + form.FindElement('Reset').Update(button_color=('gray34', 'firebrick3')) recording = False diff --git a/Demo_Canvas.py b/Demo_Canvas.py index a717c4a9..05156c7e 100644 --- a/Demo_Canvas.py +++ b/Demo_Canvas.py @@ -1,11 +1,12 @@ -import PySimpleGUI as gui +import PySimpleGUI as sg + layout = [ - [gui.Canvas(size=(100,100), background_color='red', key='canvas')], - [gui.T('Change circle color to:'), gui.ReadFormButton('Red'), gui.ReadFormButton('Blue')] + [sg.Canvas(size=(150, 150), background_color='red', key='canvas')], + [sg.T('Change circle color to:'), sg.ReadFormButton('Red'), sg.ReadFormButton('Blue')] ] -form = gui.FlexForm('Canvas test') +form = sg.FlexForm('Canvas test') form.Layout(layout) form.Finalize() diff --git a/Demo_Color.py b/Demo_Color.py index cfc22bee..ba481a39 100644 --- a/Demo_Color.py +++ b/Demo_Color.py @@ -1662,7 +1662,6 @@ GoodColors = [('#0e6251', sg.RGB(255, 246, 122)), (sg.RGB(0, 210, 87), sg.RGB(0, 74, 60)), (sg.RGB(0, 164, 73), sg.RGB(0, 74, 60)), (sg.RGB(0, 74, 60), sg.RGB(0, 74, 60)), - ] diff --git a/Demo_Desktop_Widget_Timer.py b/Demo_Desktop_Widget_Timer.py index c0221999..367e83f0 100644 --- a/Demo_Desktop_Widget_Timer.py +++ b/Demo_Desktop_Widget_Timer.py @@ -1,18 +1,6 @@ import PySimpleGUI as sg import time -""" - Timer Desktop Widget - Creates a floating timer that is always on top of other windows - You move it by grabbing anywhere on the window - Good example of how to do a non-blocking, polling program using PySimpleGUI - Can be used to poll hardware when running on a Pi - - NOTE - you will get a warning message printed when you exit using exit button. - It will look something like: - invalid command name "1616802625480StopMove" -""" - # ---------------- Create Form ---------------- sg.ChangeLookAndFeel('Black') sg.SetOptions(element_padding=(0, 0)) diff --git a/Demo_DuplicateFileFinder.py b/Demo_DuplicateFileFinder.py index 958e5f8f..1725fb4f 100644 --- a/Demo_DuplicateFileFinder.py +++ b/Demo_DuplicateFileFinder.py @@ -12,12 +12,12 @@ def FindDuplicatesFilesInFolder(path): small_count, dup_count, error_count = 0,0,0 pngdir = path if not os.path.exists(path): - sg.MsgBox('Duplicate Finder', '** Folder doesn\'t exist***', path) + sg.Popup('Duplicate Finder', '** Folder doesn\'t exist***', path) return pngfiles = os.listdir(pngdir) total_files = len(pngfiles) for idx, f in enumerate(pngfiles): - if not sg.EasyProgressMeter('Counting Duplicates', idx + 1, total_files, 'Counting Duplicate Files'): + if not sg.OneLineProgressMeter('Counting Duplicates', idx + 1, total_files, 'Counting Duplicate Files'): break total += 1 fname = os.path.join(pngdir, f) @@ -37,7 +37,7 @@ def FindDuplicatesFilesInFolder(path): shatab.append(f_sha) msg = '{} Files processed\n {} Duplicates found'.format(total_files, dup_count) - sg.MsgBox('Duplicate Finder Ended', msg) + sg.Popup('Duplicate Finder Ended', msg) # ====____====____==== Pseudo-MAIN program ====____====____==== # # This is our main-alike piece of code # @@ -48,9 +48,9 @@ def FindDuplicatesFilesInFolder(path): if __name__ == '__main__': source_folder = None - rc, source_folder = sg.GetPathBox('Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in') + rc, source_folder = sg.PopupGetFolder('Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in') if rc is True and source_folder is not None: FindDuplicatesFilesInFolder(source_folder) else: - sg.MsgBoxCancel('Cancelling', '*** Cancelling ***') + sg.PopupCancel('Cancelling', '*** Cancelling ***') exit(0) diff --git a/Demo_Graph__Element.py b/Demo_Graph__Element.py index e9547e55..174ce1fb 100644 --- a/Demo_Graph__Element.py +++ b/Demo_Graph__Element.py @@ -6,6 +6,7 @@ import PySimpleGUI as sg STEP_SIZE=1 SAMPLES = 6000 +CANVAS_SIZE = (6000,500) # globale used to communicate with thread.. yea yea... it's working fine g_exit = False @@ -17,20 +18,23 @@ def ping_thread(args): def main(): global g_exit, g_response_time + # start ping measurement thread thread = Thread(target=ping_thread, args=(None,)) thread.start() - # sg.ChangeLookAndFeel('Black') + sg.ChangeLookAndFeel('Black') sg.SetOptions(element_padding=(0,0)) - layout = [ [sg.T('Ping times to Google.com', font='Any 18')], - [sg.Graph((6000,200), (0,0), (SAMPLES,500),background_color='black', key='graph')], - [sg.Quit()]] + layout = [ [sg.T('Ping times to Google.com', font='Any 12'), sg.Quit(pad=((100,0), 0), button_color=('white', 'black'))], + [sg.Graph(CANVAS_SIZE, (0,0), (SAMPLES,500),background_color='black', key='graph')],] - form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black') + form = sg.FlexForm('Canvas test', grab_anywhere=True, background_color='black', no_titlebar=False, use_default_focus=False) form.Layout(layout) + form.Finalize() + graph = form.FindElement('graph') + prev_response_time = None i=0 prev_x, prev_y = 0, 0 @@ -40,7 +44,6 @@ def main(): button, values = form.ReadNonBlocking() if button == 'Quit' or values is None: break - graph = form.FindElement('graph') if g_response_time is None or prev_response_time == g_response_time: continue new_x, new_y = i, g_response_time[0] diff --git a/Demo_Machine_Learning.py b/Demo_Machine_Learning.py index 2ade40d5..cc26952f 100644 --- a/Demo_Machine_Learning.py +++ b/Demo_Machine_Learning.py @@ -24,9 +24,9 @@ def MachineLearningGUI(): [sg.Text('l', size=(8, 1)), sg.In(default_text='0.4', size=(8, 1)), sg.Text('Layers', size=(8, 1)), sg.Drop(values=('BatchNorm', 'other'), auto_size_text=True)],] - layout = [[sg.Frame('Command Line Parameteres', command_line_parms, text_color='green', font='Any 12')], - [sg.Frame('Flags', flags, font='Any 12', text_color='blue')], - [sg.Frame('Loss Functions', loss_functions, font='Any 12', text_color='red')], + layout = [[sg.Frame('Command Line Parameteres', command_line_parms, title_color='green', font='Any 12')], + [sg.Frame('Flags', flags, font='Any 12', title_color='blue')], + [sg.Frame('Loss Functions', loss_functions, font='Any 12', title_color='red')], [sg.Submit(), sg.Cancel()]] diff --git a/Demo_Menus.py b/Demo_Menus.py index 7b3c884f..7c0df18d 100644 --- a/Demo_Menus.py +++ b/Demo_Menus.py @@ -29,7 +29,8 @@ def TestMenus(): # ------ GUI Defintion ------ # layout = [ [sg.Menu(menu_def)], - [sg.Output(size=(60,20))] + [sg.Output(size=(60,20))], + [sg.In('Test', key='input', do_not_clear=True)] ] form = sg.FlexForm("Windows-like program", default_element_size=(12, 1), auto_size_text=False, auto_size_buttons=False, diff --git a/Demo_PDF_Viewer.py b/Demo_PDF_Viewer.py index 6fd5fb42..32889695 100644 --- a/Demo_PDF_Viewer.py +++ b/Demo_PDF_Viewer.py @@ -40,9 +40,9 @@ from binascii import hexlify sg.ChangeLookAndFeel('GreenTan') if len(sys.argv) == 1: - rc, fname = sg.GetFileBox('PDF Browser', 'PDF file to open', file_types=(("PDF Files", "*.pdf"),)) + rc, fname = sg.PopupGetFile('PDF Browser', 'PDF file to open', file_types=(("PDF Files", "*.pdf"),)) if rc is False: - sg.MsgBoxCancel('Cancelling') + sg.PopupCancel('Cancelling') exit(0) else: fname = sys.argv[1] diff --git a/Demo_Ping_Line_Graph.py b/Demo_Ping_Line_Graph.py index 36cd8267..1faa9754 100644 --- a/Demo_Ping_Line_Graph.py +++ b/Demo_Ping_Line_Graph.py @@ -61,7 +61,10 @@ while True: if g_response_time is None or prev_response_time == g_response_time: continue - new_x, new_y = convert_xy_to_canvas_xy(i, g_response_time[0]) + try: + new_x, new_y = convert_xy_to_canvas_xy(i, g_response_time[0]) + except: continue + prev_response_time = g_response_time canvas.create_line(prev_x, prev_y, new_x, new_y, width=1, fill='black') prev_x, prev_y = new_x, new_y diff --git a/Demo_Popups.py b/Demo_Popups.py index f5692b9f..f90a4105 100644 --- a/Demo_Popups.py +++ b/Demo_Popups.py @@ -1,17 +1,15 @@ import PySimpleGUI as sg +print (sg.PopupYesNo('Yes No')) - -print(sg.PopupGetFolder('Get text', background_color='blue', text_color='white')) -print(sg.PopupGetFile('Get text', background_color='blue', text_color='white')) -print(sg.PopupGetFolder('Get text', background_color='blue', text_color='white')) +print(sg.PopupGetText('Get text', background_color='blue', text_color='white', location=(1000,200))) +print(sg.PopupGetFile('Get file', background_color='blue', text_color='white')) +print(sg.PopupGetFolder('Get folder', background_color='blue', text_color='white')) sg.Popup('Simple popup') -sg.PopupNonBlocking('Non Blocking') -sg.PopupError('Error') -sg.PopupYesNo('Yes No') +sg.PopupNonBlocking('Non Blocking', location=(500,500)) sg.PopupNoTitlebar('No titlebar') sg.PopupNoBorder('No border') sg.PopupNoFrame('No frame') @@ -19,6 +17,3 @@ sg.PopupNoButtons('No Buttons') sg.PopupCancel('Cancel') sg.PopupOKCancel('OK Cancel') sg.PopupAutoClose('Autoclose') -print(sg.PopupGetText('Get text')) -print(sg.PopupGetFile('Get File')) -print(sg.PopupGetFolder('Get folder')) diff --git a/Demo_Progress_Meters.py b/Demo_Progress_Meters.py index 9b013e45..2b902fb7 100644 --- a/Demo_Progress_Meters.py +++ b/Demo_Progress_Meters.py @@ -2,7 +2,7 @@ from time import sleep import PySimpleGUI as sg """ - Demonstration of multiple OneLineProgressMeter's + Demonstration of simple and multiple OneLineProgressMeter's Shows how 2 progress meters can be running at the same time. Note -- If the user wants to cancel a meter, it's important to use the "Cancel" button, not the X @@ -10,7 +10,26 @@ import PySimpleGUI as sg calling OneLineProgresMeterCancel(key) will cancel the meter with the matching key """ -sg.ChangeLookAndFeel('Dark') +# sg.ChangeLookAndFeel('Dark') + + +""" + The simple case is that you want to add a single meter to your code. The one-line solution +""" + +import PySimpleGUI as sg + +# Display a progress meter in work loop. User is not allowed to break out of the loop +for i in range(10000): + if i % 5 == 0: sg.OneLineProgressMeter('My 1-line progress meter', i+1, 10000, 'single') + +# Display a progress meter. Allow user to break out of loop using cancel button +for i in range(10000): + if not sg.OneLineProgressMeter('My 1-line progress meter', i+1, 10000, 'single'): + break + + + layout = [ [sg.T('One-Line Progress Meter Demo', font=('Any 18'))], diff --git a/Demo_Script_Launcher.py b/Demo_Script_Launcher.py index 9260ff2c..5c72c8c1 100644 --- a/Demo_Script_Launcher.py +++ b/Demo_Script_Launcher.py @@ -41,7 +41,6 @@ def Launcher2(): namesonly.append(ntpath.basename(file)) layout = [ - [sg.Text('Script output....', size=(40, 1))], [sg.Listbox(values=namesonly, size=(30, 19), select_mode=sg.SELECT_MODE_EXTENDED, key='demolist'), sg.Output(size=(88, 20), font='Courier 10')], [sg.Checkbox('Wait for program to complete', default=False, key='wait')], [sg.ReadFormButton('Run'), sg.ReadFormButton('Shortcut 1'), sg.ReadFormButton('Fav Program'), sg.SimpleButton('EXIT')], diff --git a/Demo_Table_Element.py b/Demo_Table_Element.py index 19d21639..7a72088d 100644 --- a/Demo_Table_Element.py +++ b/Demo_Table_Element.py @@ -1,7 +1,8 @@ import csv import PySimpleGUI as sg -filename = sg.PopupGetFile('filename to open', no_window=True, file_types=(("CSV Files","*.csv"),)) +# filename = sg.PopupGetFile('filename to open', no_window=True, file_types=(("CSV Files","*.csv"),)) +filename = 'C:/Python/PycharmProjects/GooeyGUI/CSV/Gruen Movement Catalog V5.3 for Lucid less data 2017-08-30.csv' # --- populate table with file contents --- # data = [] if filename is not None: @@ -19,8 +20,11 @@ col_layout = [[sg.Table(values=data[1:][:], headings=[data[0][x] for x in range( auto_size_columns=True, display_row_numbers=True, justification='right', size=(None, len(data)))]] layout = [[sg.Column(col_layout, size=(1200,600), scrollable=True)],] - form = sg.FlexForm('Table', grab_anywhere=False) -b, v = form.LayoutAndRead(layout) +form.Layout(layout) + +form.Finalize() + +b, v = form.Read() exit(69) diff --git a/docs/index.md b/docs/index.md index 053c4553..637949aa 100644 --- a/docs/index.md +++ b/docs/index.md @@ -11,7 +11,7 @@ # PySimpleGUI - (Ver 3.3.0) + (Ver 3.4.0) @@ -107,6 +107,8 @@ The `PySimpleGUI` package is focused on the ***developer***. Create a custom GU Radio Buttons Listbox Slider + Graph + Frame with title Icons Multi-line Text Input Scroll-able Output @@ -2155,6 +2157,7 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it | 3.01.02 | Step 11, 2018 - All Element.Update functions have a `disabled` parameter so they can be disabled. Renamed some parameters in Update function (sorry if I broke your code), fix for bug in Image.Update. Wasn't setting size correctly, changed grab_anywhere logic again,added grab anywhere option to PupupGetText (assumes disabled) | 3.02.00 | Sept 14, 2018 - New Table Element (Beta release), MsgBox removed entirely, font setting for InputText Element, **packing change** risky change that allows some Elements to be resized,removed command parameter from Menu Element, new function names for ReadNonBlocking (Finalize, PreRead), change to text element autosizing and wrapping (yet again), lots of parameter additions to Popup functions (colors, etc). | 3.03.00 | New feature - One Line Progress Meters, new display_row_numbers for Table Element, fixed bug in EasyProgresssMeters (function will soon go away), OneLine and Easy progress meters set to grab anywhere but can be turned off. +{ 03,04.00 | New features - Graph Element, Frame Element, more settings exposed to Popup calls. See notes below for more. ### Release Notes @@ -2188,6 +2191,7 @@ Related to the Grab Anywhere feature is the no_titlebar option, again found in t 3.3.0 OneLineProgressMeter function added which gives you not only a one-line solution to progress meters, but it also gives you the ability to have more than 1 running at the same time, something not possible with the EasyProgressMeterCall +3.4.0 New Elements - Frame (a labelled frame for grouping elements. Similar to Column), Graph (like a Canvas element except uses the caller's coordinate system rather than tkinter's). Set an initial_folder for browsing type buttons (browse for file/folder). Buttons return key value rather than button text if a key is specified, OneLineProgressMeter! Replaced EasyProgressMeter (sorry folks that's the way progress works sometimes), changed ALL of the Popup calls to provide many more customization settings - changed PopupGetFolder, PopupGetFile, PopupGetText, Popup, PopupNoButtons, PopupNonBlocking, PopupNoTitlebar, PopupAutoClose, PopupCancel, PopupOK, PopupOKCancel, PopupYesNo ### Upcoming Make suggestions people! Future release features @@ -2263,7 +2267,7 @@ Here are the steps to run that application The pip command is all there is to the setup. -The way HowDoI works is that it uses your search term to look through stack overflow posts. It finds the best answer, gets the code from the answer, and presents it as a response. It gives you the correct answer OFTEN. It's a miracle that it work SO well. +The way HowDoI works is that it uses your search term to look through stack overflow posts. It finds the best answer, gets the code from the answer, and presents it as a response. It gives you the correct answer OFTEN. It's a miracle that it work SO well. For Python questions, I simply start my query with 'Python'. Let's say you forgot how to reverse a list in Python. When you run HowDoI and ask this question, this is what you'll see. ![howdoiwithhistory](https://user-images.githubusercontent.com/13696193/45064009-5fd61180-b07f-11e8-8ead-eb0d1ff3a6be.jpg) diff --git a/readme.md b/readme.md index 053c4553..637949aa 100644 --- a/readme.md +++ b/readme.md @@ -11,7 +11,7 @@ # PySimpleGUI - (Ver 3.3.0) + (Ver 3.4.0) @@ -107,6 +107,8 @@ The `PySimpleGUI` package is focused on the ***developer***. Create a custom GU Radio Buttons Listbox Slider + Graph + Frame with title Icons Multi-line Text Input Scroll-able Output @@ -2155,6 +2157,7 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it | 3.01.02 | Step 11, 2018 - All Element.Update functions have a `disabled` parameter so they can be disabled. Renamed some parameters in Update function (sorry if I broke your code), fix for bug in Image.Update. Wasn't setting size correctly, changed grab_anywhere logic again,added grab anywhere option to PupupGetText (assumes disabled) | 3.02.00 | Sept 14, 2018 - New Table Element (Beta release), MsgBox removed entirely, font setting for InputText Element, **packing change** risky change that allows some Elements to be resized,removed command parameter from Menu Element, new function names for ReadNonBlocking (Finalize, PreRead), change to text element autosizing and wrapping (yet again), lots of parameter additions to Popup functions (colors, etc). | 3.03.00 | New feature - One Line Progress Meters, new display_row_numbers for Table Element, fixed bug in EasyProgresssMeters (function will soon go away), OneLine and Easy progress meters set to grab anywhere but can be turned off. +{ 03,04.00 | New features - Graph Element, Frame Element, more settings exposed to Popup calls. See notes below for more. ### Release Notes @@ -2188,6 +2191,7 @@ Related to the Grab Anywhere feature is the no_titlebar option, again found in t 3.3.0 OneLineProgressMeter function added which gives you not only a one-line solution to progress meters, but it also gives you the ability to have more than 1 running at the same time, something not possible with the EasyProgressMeterCall +3.4.0 New Elements - Frame (a labelled frame for grouping elements. Similar to Column), Graph (like a Canvas element except uses the caller's coordinate system rather than tkinter's). Set an initial_folder for browsing type buttons (browse for file/folder). Buttons return key value rather than button text if a key is specified, OneLineProgressMeter! Replaced EasyProgressMeter (sorry folks that's the way progress works sometimes), changed ALL of the Popup calls to provide many more customization settings - changed PopupGetFolder, PopupGetFile, PopupGetText, Popup, PopupNoButtons, PopupNonBlocking, PopupNoTitlebar, PopupAutoClose, PopupCancel, PopupOK, PopupOKCancel, PopupYesNo ### Upcoming Make suggestions people! Future release features @@ -2263,7 +2267,7 @@ Here are the steps to run that application The pip command is all there is to the setup. -The way HowDoI works is that it uses your search term to look through stack overflow posts. It finds the best answer, gets the code from the answer, and presents it as a response. It gives you the correct answer OFTEN. It's a miracle that it work SO well. +The way HowDoI works is that it uses your search term to look through stack overflow posts. It finds the best answer, gets the code from the answer, and presents it as a response. It gives you the correct answer OFTEN. It's a miracle that it work SO well. For Python questions, I simply start my query with 'Python'. Let's say you forgot how to reverse a list in Python. When you run HowDoI and ask this question, this is what you'll see. ![howdoiwithhistory](https://user-images.githubusercontent.com/13696193/45064009-5fd61180-b07f-11e8-8ead-eb0d1ff3a6be.jpg)