From 0076b461f5cb9c022459efc65688ceab2b73bbfb Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Thu, 7 May 2020 06:22:59 -0400 Subject: [PATCH] WIN_CLOSED bulk update. No more test for event is None, use WIN_CLOSED instead --- DemoPrograms/Demo_All_Widgets.py | 11 +- DemoPrograms/Demo_Animated_GIFs.py | 4 +- DemoPrograms/Demo_Bar_Chart.py | 2 +- DemoPrograms/Demo_Borderless_Window.py | 2 +- DemoPrograms/Demo_Button_Click.py | 2 +- .../Demo_Button_Events_From_Browse.py | 2 +- DemoPrograms/Demo_Button_Func_Calls.py | 2 +- DemoPrograms/Demo_Button_States.py | 2 +- DemoPrograms/Demo_Button_Toggle.py | 2 +- DemoPrograms/Demo_Buttons_Base64_Simple.py | 2 +- DemoPrograms/Demo_Buttons_Mac.py | 2 +- DemoPrograms/Demo_Calendar.py | 6 +- DemoPrograms/Demo_Canvas.py | 2 +- DemoPrograms/Demo_Change_Submits_InputText.py | 2 +- DemoPrograms/Demo_Chat.py | 2 +- DemoPrograms/Demo_Chat_With_History.py | 2 +- DemoPrograms/Demo_Color.py | 2 +- DemoPrograms/Demo_Color_Chooser_Custom.py | 6 +- DemoPrograms/Demo_Color_Names.py | 2 +- DemoPrograms/Demo_Color_Names_Smaller_List.py | 2 +- DemoPrograms/Demo_Column_And_Frames.py | 6 +- .../Demo_Column_Elem_Swap_Entire_Window.py | 2 +- DemoPrograms/Demo_Columns.py | 6 +- DemoPrograms/Demo_Conways_Game_of_Life.py | 6 +- DemoPrograms/Demo_Crossword_Puzzle.py | 2 +- DemoPrograms/Demo_Cursor_Changed_To_Hand.py | 2 +- DemoPrograms/Demo_DOC_Viewer_PIL.py | 2 +- DemoPrograms/Demo_Date_Chooser.py | 3 +- DemoPrograms/Demo_Debugger_Built_Into_PSG.py | 2 +- DemoPrograms/Demo_Debugger_Button.py | 2 +- DemoPrograms/Demo_Debugger_ImWatchingYou.py | 2 +- .../Demo_Design_Pattern_Multiple_Windows.py | 4 +- .../Demo_Design_Pattern_Multiple_Windows3.py | 4 +- .../Demo_Design_Pattern_Persistent_Window.py | 2 +- DemoPrograms/Demo_Design_Patterns.py | 56 +++++---- DemoPrograms/Demo_Desktop_Floating_Toolbar.py | 2 +- .../Demo_Desktop_Widget_CPU_Dashboard.py | 53 +++++---- DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py | 4 +- .../Demo_Desktop_Widget_CPU_Utilization.py | 4 +- ...o_Desktop_Widget_CPU_Utilization_Simple.py | 4 +- DemoPrograms/Demo_Desktop_Widget_Timer.py | 2 +- .../Demo_Desktop_Widget_psutil_Dashboard.py | 2 +- DemoPrograms/Demo_Disable_Elements.py | 2 +- DemoPrograms/Demo_EXE_Maker.py | 2 +- DemoPrograms/Demo_Email_Send.py | 2 +- DemoPrograms/Demo_Event_Binding.py | 2 +- DemoPrograms/Demo_Font_Previewer.py | 2 +- DemoPrograms/Demo_Font_Sizer.py | 2 +- DemoPrograms/Demo_Font_String.py | 2 +- DemoPrograms/Demo_Game_Frontend_Battleship.py | 2 +- ...ntend_Battleship_No_List_Comprehensions.py | 2 +- ...nd_Battleship_Single_List_Comprehension.py | 2 +- DemoPrograms/Demo_Google_TTS.py | 2 +- DemoPrograms/Demo_Graph_Ball_Game.py | 2 +- DemoPrograms/Demo_Graph_Drag_Rectangle.py | 2 +- DemoPrograms/Demo_Graph_Drawing.py | 6 +- ...Demo_Graph_Drawing_And_Dragging_Figures.py | 23 ++-- DemoPrograms/Demo_Graph_Element.py | 2 +- DemoPrograms/Demo_Graph_Element_Sine_Wave.py | 2 +- DemoPrograms/Demo_Graph_Noise.py | 4 +- DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py | 2 +- DemoPrograms/Demo_IP_Address_Entry.py | 2 +- DemoPrograms/Demo_Img_Viewer.py | 2 +- DemoPrograms/Demo_Input_Auto_Complete.py | 5 +- DemoPrograms/Demo_Input_Validation.py | 2 +- DemoPrograms/Demo_Invisible_Elements.py | 2 +- .../Demo_Keyboard_ENTER_Presses_Button.py | 2 +- DemoPrograms/Demo_Keyboard_Realtime.py | 2 +- DemoPrograms/Demo_Keypad.py | 2 +- DemoPrograms/Demo_LED_Clock_Weather.py | 2 +- DemoPrograms/Demo_LED_Indicators.py | 2 +- DemoPrograms/Demo_Layout_Extend.py | 2 +- DemoPrograms/Demo_Layout_Generation.py | 2 +- DemoPrograms/Demo_Listbox_Search_Filter.py | 2 +- DemoPrograms/Demo_MIDI_Player.py | 43 ++++--- DemoPrograms/Demo_Matplotlib.py | 111 +++++++++--------- DemoPrograms/Demo_Matplotlib_Browser.py | 2 +- DemoPrograms/Demo_Matplotlib_Browser_Paned.py | 2 +- .../Demo_Matplotlib_Embedded_Toolbar.py | 2 +- DemoPrograms/Demo_Matplotlib_PyLab.py | 1 - DemoPrograms/Demo_Matplotlib_Two_Windows.py | 2 +- DemoPrograms/Demo_Media_Player.py | 2 +- DemoPrograms/Demo_Media_Player_VLC_Based.py | 2 +- DemoPrograms/Demo_Menus.py | 2 +- .../Demo_Multiline_Multicolored_Text.py | 16 +-- .../Demo_Multiple_Windows_Experimental.py | 6 +- ...mo_Multithreaded_Animated_Shell_Command.py | 4 +- .../Demo_Multithreaded_Different_Threads.py | 2 +- ...ithreaded_Long_Shell_Operation_Animated.py | 2 + .../Demo_Multithreaded_Long_Task_Simple.py | 2 +- DemoPrograms/Demo_Multithreaded_Long_Tasks.py | 2 +- .../Demo_Multithreaded_Multiple_Threads.py | 2 +- ...emo_Notification_Window_Multiprocessing.py | 24 ++-- DemoPrograms/Demo_OpenCV_7_Line_Program.py | 2 +- DemoPrograms/Demo_OpenCV_Webcam.py | 2 +- DemoPrograms/Demo_OpenCV_Webcam_ASCII.py | 2 +- DemoPrograms/Demo_PDF_Viewer.py | 2 +- DemoPrograms/Demo_PNG_Thumbnail_Viewer.py | 2 +- DemoPrograms/Demo_PNG_Viewer.py | 2 +- DemoPrograms/Demo_Paned_Window.py | 2 +- DemoPrograms/Demo_Password_Login.py | 2 +- DemoPrograms/Demo_Pi_LEDs.py | 2 +- DemoPrograms/Demo_Pi_Robotics.py | 2 +- DemoPrograms/Demo_Ping_Line_Graph.py | 2 +- DemoPrograms/Demo_Pong.py | 2 +- DemoPrograms/Demo_Pong_Multiple_Platforms.py | 2 +- DemoPrograms/Demo_Progress_Meters.py | 10 +- DemoPrograms/Demo_PyGame_Integration.py | 2 +- DemoPrograms/Demo_PyGame_Snake_Game.py | 2 +- DemoPrograms/Demo_Reddit_Search.py | 8 +- DemoPrograms/Demo_Save_Window_As_Image.py | 2 +- .../Demo_Script_Launcher_ANSI_Color_Output.py | 2 +- .../Demo_Script_Launcher_Realtime_Output.py | 2 +- DemoPrograms/Demo_Settings_Save_Load.py | 7 +- DemoPrograms/Demo_Sort_Visualizer.py | 2 +- DemoPrograms/Demo_Spinner_Compound_Element.py | 2 +- DemoPrograms/Demo_Stdout.py | 2 +- DemoPrograms/Demo_Sudoku.py | 50 ++++---- DemoPrograms/Demo_Super_Simple_Form.py | 9 +- DemoPrograms/Demo_Table_Element.py | 11 +- DemoPrograms/Demo_Table_Simulation.py | 2 +- .../Demo_Table_Simulation_Arrow_Keys.py | 2 +- DemoPrograms/Demo_Tabs.py | 17 +-- DemoPrograms/Demo_Tabs_Nested.py | 2 +- DemoPrograms/Demo_Tabs_Simple.py | 2 +- DemoPrograms/Demo_Template.py | 2 +- DemoPrograms/Demo_Theme_Browser.py | 2 +- DemoPrograms/Demo_Timer.py | 2 +- DemoPrograms/Demo_Touch_Keyboard.py | 2 +- DemoPrograms/Demo_Tree_Element.py | 4 +- DemoPrograms/Demo_Turtle.py | 2 +- DemoPrograms/Demo_Unicode_Characters.py | 2 +- DemoPrograms/Demo_Uno_Card_Game.py | 4 +- DemoPrograms/Demo_Window_Disappear.py | 2 +- DemoPrograms/Demo_psutil_Kill_Processes.py | 6 +- 135 files changed, 395 insertions(+), 349 deletions(-) diff --git a/DemoPrograms/Demo_All_Widgets.py b/DemoPrograms/Demo_All_Widgets.py index 86d94945..98681e3f 100644 --- a/DemoPrograms/Demo_All_Widgets.py +++ b/DemoPrograms/Demo_All_Widgets.py @@ -5,8 +5,8 @@ Example of (almost) all widgets, that you can use in PySimpleGUI. import PySimpleGUI as sg -# sg.theme('Dark Red') -# sg.theme('Default1') + +sg.theme('Dark Red') # sg.set_options(text_color='black', background_color='#A6B2BE', text_element_background_color='#A6B2BE') # ------ Menu Definition ------ # menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']], @@ -17,7 +17,7 @@ menu_def = [['&File', ['&Open', '&Save', 'E&xit', 'Properties']], column1 = [[sg.Text('Column 1', justification='center', size=(10, 1))], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 1')], - [sg.Spin(values=('Spin Box 1', '2', '3'), + [sg.Spin(values=['Spin Box 1', '2', '3'], initial_value='Spin Box 2')], [sg.Spin(values=('Spin Box 1', '2', '3'), initial_value='Spin Box 3')]] @@ -50,10 +50,9 @@ layout = [ sg.InputText('Default Folder'), sg.FolderBrowse()], [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]] -window = sg.Window('Everything bagel', layout, no_titlebar=True, - default_element_size=(40, 1), grab_anywhere=False) +window = sg.Window('Everything bagel', layout) -event, values = window.read() +event, values = window.read(close=True) sg.popup('Title', 'The results of the window.', 'The button clicked was "{}"'.format(event), diff --git a/DemoPrograms/Demo_Animated_GIFs.py b/DemoPrograms/Demo_Animated_GIFs.py index 6e082df4..2c3cf287 100644 --- a/DemoPrograms/Demo_Animated_GIFs.py +++ b/DemoPrograms/Demo_Animated_GIFs.py @@ -30,7 +30,7 @@ gifs = [ring_blue, red_dots_ring, ring_black_dots, ring_gray_segments, ring_line # first show how to use popup_animated using built-in GIF image for i in range(100000): - sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, background_color='white', time_between_frames=100) + sg.popup_animated(sg.DEFAULT_BASE64_LOADING_GIF, no_titlebar=False, background_color='white', time_between_frames=100) sg.popup_animated(None) # close all Animated Popups # Next demo is to show how to create custom windows with animations @@ -49,7 +49,7 @@ offset = 0 gif = gifs[0] while True: # Event Loop event, values = window.read(timeout=10) # loop every 10 ms to show that the 100 ms value below is used for animation - if event in (None, 'Exit', 'Cancel'): + if event in (sg.WIN_CLOSED, 'Exit', 'Cancel'): break elif event == '-IMAGE-': # if clicked on the image diff --git a/DemoPrograms/Demo_Bar_Chart.py b/DemoPrograms/Demo_Bar_Chart.py index ff5c2beb..5eea9f42 100644 --- a/DemoPrograms/Demo_Bar_Chart.py +++ b/DemoPrograms/Demo_Bar_Chart.py @@ -37,7 +37,7 @@ window = sg.Window('Window Title', layout) while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break graph.erase() diff --git a/DemoPrograms/Demo_Borderless_Window.py b/DemoPrograms/Demo_Borderless_Window.py index c8e4062c..6ff2c7f8 100644 --- a/DemoPrograms/Demo_Borderless_Window.py +++ b/DemoPrograms/Demo_Borderless_Window.py @@ -30,5 +30,5 @@ window = sg.Window("Borderless Window", while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break diff --git a/DemoPrograms/Demo_Button_Click.py b/DemoPrograms/Demo_Button_Click.py index f770595a..63ef6900 100644 --- a/DemoPrograms/Demo_Button_Click.py +++ b/DemoPrograms/Demo_Button_Click.py @@ -12,7 +12,7 @@ window = sg.Window('Temperature Manager', layout, font='Default -24', return_key while True: # Event Loop event, values = window.read(timeout=500) # returns every 500 ms print(event, values) if event != sg.TIMEOUT_KEY else None # a debug print - if event in (None, 'Quit'): + if event in (sg.WIN_CLOSED, 'Quit'): break if event == 'Set': print('setting temperature to ', values['-IN-']) diff --git a/DemoPrograms/Demo_Button_Events_From_Browse.py b/DemoPrograms/Demo_Button_Events_From_Browse.py index bbae8ebc..cd74e707 100644 --- a/DemoPrograms/Demo_Button_Events_From_Browse.py +++ b/DemoPrograms/Demo_Button_Events_From_Browse.py @@ -24,7 +24,7 @@ window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # When choice has been made, then fill in the listbox with the choices if event == '-IN-': diff --git a/DemoPrograms/Demo_Button_Func_Calls.py b/DemoPrograms/Demo_Button_Func_Calls.py index af25aa9a..e6d71587 100644 --- a/DemoPrograms/Demo_Button_Func_Calls.py +++ b/DemoPrograms/Demo_Button_Func_Calls.py @@ -32,7 +32,7 @@ window = sg.Window('Button Callback Simulation', layout) while True: # Event Loop event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break elif event == 'Button 1': callback_function1() # call the "Callback" function diff --git a/DemoPrograms/Demo_Button_States.py b/DemoPrograms/Demo_Button_States.py index f9553cb7..161eadf6 100644 --- a/DemoPrograms/Demo_Button_States.py +++ b/DemoPrograms/Demo_Button_States.py @@ -36,7 +36,7 @@ recording = have_data = False while True: event, values = window.read() print(event) - if event is None: + if event == sg.WIN_CLOSED: break if event == '-Start-': for key, state in {'-Start-': True, '-Stop-': False, '-Reset-': False, '-Submit-': True}.items(): diff --git a/DemoPrograms/Demo_Button_Toggle.py b/DemoPrograms/Demo_Button_Toggle.py index 1d35482a..782ecd8d 100644 --- a/DemoPrograms/Demo_Button_Toggle.py +++ b/DemoPrograms/Demo_Button_Toggle.py @@ -31,7 +31,7 @@ graphic_off = True while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == '-B-': # if the normal button that changes color and text down = not down diff --git a/DemoPrograms/Demo_Buttons_Base64_Simple.py b/DemoPrograms/Demo_Buttons_Base64_Simple.py index 8d2beebd..87e893fd 100644 --- a/DemoPrograms/Demo_Buttons_Base64_Simple.py +++ b/DemoPrograms/Demo_Buttons_Base64_Simple.py @@ -24,7 +24,7 @@ window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() # type: str, dict print(event, values) - if event in (None, 'Exit'): # If the user exits + if event in (sg.WIN_CLOSED, 'Exit'): # If the user exits break window['-OUT-'].Update(event) # Output the event to the window window.close(); del window # Exiting so clean up diff --git a/DemoPrograms/Demo_Buttons_Mac.py b/DemoPrograms/Demo_Buttons_Mac.py index 035ef8b1..27e18b6b 100644 --- a/DemoPrograms/Demo_Buttons_Mac.py +++ b/DemoPrograms/Demo_Buttons_Mac.py @@ -30,7 +30,7 @@ def show_win(): while True: # Event Loop event, values = window.read() - if event is None or event == '-exit-': + if event == sg.WIN_CLOSED or event == '-exit-': break if event == '-minimize-': # window.Minimize() # cannot minimize a window with no titlebar diff --git a/DemoPrograms/Demo_Calendar.py b/DemoPrograms/Demo_Calendar.py index decbada7..f6a4fa84 100644 --- a/DemoPrograms/Demo_Calendar.py +++ b/DemoPrograms/Demo_Calendar.py @@ -4,11 +4,11 @@ import PySimpleGUI as sg """ Simple test harness to demonstate how to use the CalendarButton and the get date popup """ -sg.theme('Dark Red') +# sg.theme('Dark Red') layout = [[sg.Text('Date Chooser Test Harness', key='-TXT-')], [sg.Input(key='-IN-', size=(20,1)), sg.CalendarButton('Cal US No Buttons Location (0,0)', close_when_date_chosen=True, target='-IN-', location=(0,0), no_titlebar=False, )], [sg.Input(key='-IN3-', size=(20,1)), sg.CalendarButton('Cal Monday', title='Pick a date any date', no_titlebar=True, close_when_date_chosen=False, target='-IN3-', begin_at_sunday_plus=1, month_names=('студзень', 'люты', 'сакавік', 'красавік', 'май', 'чэрвень', 'ліпень', 'жнівень', 'верасень', 'кастрычнік', 'лістапад', 'снежань'), day_abbreviations=('Дш', 'Шш', 'Шр', 'Бш', 'Жм', 'Иш', 'Жш'))], - [sg.Input(key='-IN2-', size=(20,1)), sg.CalendarButton('Cal German Feb 2020', target='-IN2-', default_date_m_d_y=(2,None,2020), locale='de DE', begin_at_sunday_plus=1 )], + [sg.Input(key='-IN2-', size=(20,1)), sg.CalendarButton('Cal German Feb 2020', target='-IN2-', default_date_m_d_y=(2,None,2020), locale='de_DE', begin_at_sunday_plus=1 )], [sg.Input(key='-IN4-', size=(20,1)), sg.CalendarButton('Cal Format %m-%d Jan 2020', target='-IN4-', format='%m-%d', default_date_m_d_y=(1,None,2020), )], [sg.Button('Read'), sg.Button('Date Popup'), sg.Exit()]] @@ -17,7 +17,7 @@ window = sg.Window('window', layout) while True: event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Date Popup': sg.popup('You chose:', sg.popup_get_date()) diff --git a/DemoPrograms/Demo_Canvas.py b/DemoPrograms/Demo_Canvas.py index 74b63a06..9cf20a83 100644 --- a/DemoPrograms/Demo_Canvas.py +++ b/DemoPrograms/Demo_Canvas.py @@ -12,7 +12,7 @@ cir = window['canvas'].TKCanvas.create_oval(50, 50, 100, 100) while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break if event in ('Blue', 'Red'): window['canvas'].TKCanvas.itemconfig(cir, fill=event) diff --git a/DemoPrograms/Demo_Change_Submits_InputText.py b/DemoPrograms/Demo_Change_Submits_InputText.py index f64914c0..d54c2cfc 100644 --- a/DemoPrograms/Demo_Change_Submits_InputText.py +++ b/DemoPrograms/Demo_Change_Submits_InputText.py @@ -40,7 +40,7 @@ window = sg.Window('Demonstration of InputText with change_submits', while True: # Event Loop event, values = window.read() print(event, values) - if event is None: + if event == sg.WIN_CLOSED: break window.close() diff --git a/DemoPrograms/Demo_Chat.py b/DemoPrograms/Demo_Chat.py index 54cf0f1f..398553eb 100644 --- a/DemoPrograms/Demo_Chat.py +++ b/DemoPrograms/Demo_Chat.py @@ -18,7 +18,7 @@ window = sg.Window('Chat window', layout, font=('Helvetica', ' 13'), default_but while True: # The Event Loop event, value = window.read() - if event in (None, 'EXIT'): # quit if exit button or X + if event in (sg.WIN_CLOSED, 'EXIT'): # quit if exit button or X break if event == 'SEND': query = value['-QUERY-'].rstrip() diff --git a/DemoPrograms/Demo_Chat_With_History.py b/DemoPrograms/Demo_Chat_With_History.py index 94827e7e..f7bade05 100644 --- a/DemoPrograms/Demo_Chat_With_History.py +++ b/DemoPrograms/Demo_Chat_With_History.py @@ -48,7 +48,7 @@ def ChatBotWithHistory(): window['query'].update('') window['history'].update('\n'.join(command_history[-3:])) - elif event in (None, 'EXIT'): # quit if exit event or X + elif event in (sg.WIN_CLOSED, 'EXIT'): # quit if exit event or X break elif 'Up' in event and len(command_history): diff --git a/DemoPrograms/Demo_Color.py b/DemoPrograms/Demo_Color.py index 43b67354..f1a950a5 100644 --- a/DemoPrograms/Demo_Color.py +++ b/DemoPrograms/Demo_Color.py @@ -1687,7 +1687,7 @@ def main(): event, values = sg.Window('Color Demo', layout, auto_size_buttons=False).read() # ------- OUTPUT results portion ------- # - if event == 'Quit' or event is None: + if event == 'Quit' or event == sg.WIN_CLOSED: exit(0) elif event == 'Many buttons': show_all_colors_on_buttons() diff --git a/DemoPrograms/Demo_Color_Chooser_Custom.py b/DemoPrograms/Demo_Color_Chooser_Custom.py index 23ca3d89..3a998853 100644 --- a/DemoPrograms/Demo_Color_Chooser_Custom.py +++ b/DemoPrograms/Demo_Color_Chooser_Custom.py @@ -689,8 +689,8 @@ def popup_color_chooser(look_and_feel=None): color_chosen = None while True: # Event Loop event, values = window.read() - if event in (None, 'OK'): - if event is None: + if event in (sg.WIN_CLOSED, 'OK'): + if event == sg.WIN_CLOSED: color_chosen = None break window['-OUT-'](f'You chose {event[0]} : {event[1]}') @@ -708,7 +708,7 @@ if __name__ == '__main__': window = sg.Window('My application', layout) while True: event, values = window.read() - if event in (None, 'Cancel'): + if event in (sg.WIN_CLOSED, 'Cancel'): break if event.startswith('Color'): window.hide() diff --git a/DemoPrograms/Demo_Color_Names.py b/DemoPrograms/Demo_Color_Names.py index 5fc654ad..3d1d8229 100644 --- a/DemoPrograms/Demo_Color_Names.py +++ b/DemoPrograms/Demo_Color_Names.py @@ -696,7 +696,7 @@ window = sg.Window('Color Viewer', layout, font='Any 9', element_padding=(0,0), # -- Event loop -- while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break # -- Create a secondary window that shows white and black text on chosen color layout2 = [[ diff --git a/DemoPrograms/Demo_Color_Names_Smaller_List.py b/DemoPrograms/Demo_Color_Names_Smaller_List.py index 12f86376..dacd1a30 100644 --- a/DemoPrograms/Demo_Color_Names_Smaller_List.py +++ b/DemoPrograms/Demo_Color_Names_Smaller_List.py @@ -114,7 +114,7 @@ window = sg.Window('Color Viewer', layout, grab_anywhere=False, font=('any 9')) # -- Event loop -- while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break # -- Create a secondary window that shows white and black text on chosen color layout2 = [[sg.DummyButton(event, button_color=('white', event)), diff --git a/DemoPrograms/Demo_Column_And_Frames.py b/DemoPrograms/Demo_Column_And_Frames.py index 95b57696..c7a62be7 100644 --- a/DemoPrograms/Demo_Column_And_Frames.py +++ b/DemoPrograms/Demo_Column_And_Frames.py @@ -19,10 +19,10 @@ col2 = Column([[Frame('Accounts:', [[Column([[Listbox(['Account '+str(i) for i i col1 = Column([ # Categories frame - [Frame('Categories:', [[Radio('Websites', 'radio1', default=True, key='-WEBSITES-', size=(10, 1)), + [Frame('Categories:', [[ Radio('Websites', 'radio1', default=True, key='-WEBSITES-', size=(10, 1)), Radio('Software', 'radio1', key='-SOFTWARE-', size=(10, 1))]],)], # Information frame - [Frame('Information:', [[Column([[Text('Account:')], + [Frame('Information:', [[Text(), Column([[Text('Account:')], [Input(key='-ACCOUNT-IN-', size=(19, 1))], [Text('User Id:')], [Input(key='-USERID-IN-', size=(19, 1)), @@ -47,7 +47,7 @@ window = Window('Passwords', layout) while True: event, values = window.read() print(event, values) - if event is None: + if event == sg.WIN_CLOSED: break window.close() diff --git a/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py b/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py index 08d5905f..087a1cf1 100644 --- a/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py +++ b/DemoPrograms/Demo_Column_Elem_Swap_Entire_Window.py @@ -32,7 +32,7 @@ layout = 1 # The currently visible layout while True: event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Cycle Layout': window[f'-COL{layout}-'].update(visible=False) diff --git a/DemoPrograms/Demo_Columns.py b/DemoPrograms/Demo_Columns.py index 77e45586..eb657435 100644 --- a/DemoPrograms/Demo_Columns.py +++ b/DemoPrograms/Demo_Columns.py @@ -1,6 +1,6 @@ #!/usr/bin/env python import PySimpleGUI as sg - +print(sg.version, sg) ''' Usage of Column Element ''' @@ -9,7 +9,7 @@ sg.theme('BlueMono') # Column layout col = [[sg.Text('col Row 1', text_color='white', background_color='blue')], - [sg.Text('col Row 2', text_color='white', background_color='blue'), sg.Input('col input 1')], + [sg.Text('col Row 2', text_color='white', background_color='blue', pad=(0,(25,0))),sg.T('Another item'), sg.T('another'), sg.Input('col input 1')], [sg.Text('col Row 3', text_color='white', background_color='blue'), sg.Input('col input 2')]] # Window layout layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item 3'), @@ -19,7 +19,7 @@ layout = [[sg.Listbox(values=('Listbox Item 1', 'Listbox Item 2', 'Listbox Item [sg.OK()]] # Display the window and get values -window = sg.Window('Compact 1-line form with column', layout) +window = sg.Window('Compact 1-line form with column', layout, margins=(0,0), element_padding=(0,0)) event, values = window.read() sg.popup(event, values, line_width=200) diff --git a/DemoPrograms/Demo_Conways_Game_of_Life.py b/DemoPrograms/Demo_Conways_Game_of_Life.py index 49944075..b1462119 100644 --- a/DemoPrograms/Demo_Conways_Game_of_Life.py +++ b/DemoPrograms/Demo_Conways_Game_of_Life.py @@ -141,7 +141,7 @@ class GameOfLife: j * (BOX_SIZE) + BOX_SIZE), line_color='black', fill_color='yellow') event, values = self.window.read(timeout=self.delay) - if event in (None, '-DONE-'): + if event in (sg.WIN_CLOSED, '-DONE-'): sg.popup('Click OK to exit the program...') self.window.close() exit() @@ -159,7 +159,7 @@ class GameOfLife: ids[i].append(0) while True: # Event Loop event, values = self.window.read() - if event is None or event == '-DONE-': + if event == sg.WIN_CLOSED or event == '-DONE-': break self.window['-S1-OUT-'].update(values['-SLIDER-']) self.window['-S2-OUT-'].update(values['-SLIDER2-']) @@ -181,7 +181,7 @@ class GameOfLife: line_color='black', fill_color='yellow') ids[box_x][box_y] = id_val self.old_grid[box_x][box_y] = 1 - if event is None: + if event == sg.WIN_CLOSED: self.window.close() else: self.window['-DONE-'].update(text='Exit') diff --git a/DemoPrograms/Demo_Crossword_Puzzle.py b/DemoPrograms/Demo_Crossword_Puzzle.py index c01d78e4..593686bd 100644 --- a/DemoPrograms/Demo_Crossword_Puzzle.py +++ b/DemoPrograms/Demo_Crossword_Puzzle.py @@ -35,7 +35,7 @@ for row in range(16): while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break mouse = values['-GRAPH-'] diff --git a/DemoPrograms/Demo_Cursor_Changed_To_Hand.py b/DemoPrograms/Demo_Cursor_Changed_To_Hand.py index d3ecbe65..61da1d6f 100644 --- a/DemoPrograms/Demo_Cursor_Changed_To_Hand.py +++ b/DemoPrograms/Demo_Cursor_Changed_To_Hand.py @@ -35,7 +35,7 @@ window['Exit'].set_cursor(cursor='no') while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == '-LINK-': # if the text was clicked, open a browser using the text as the address diff --git a/DemoPrograms/Demo_DOC_Viewer_PIL.py b/DemoPrograms/Demo_DOC_Viewer_PIL.py index ae24bad5..617ae8e4 100644 --- a/DemoPrograms/Demo_DOC_Viewer_PIL.py +++ b/DemoPrograms/Demo_DOC_Viewer_PIL.py @@ -168,7 +168,7 @@ old_zoom = False while True: event, value = window.read() - if event is None and (value is None or value['-PageNumber-'] is None): + if event == sg.WIN_CLOSED and (value is None or value['-PageNumber-'] is None): break if event in quit_buttons: break diff --git a/DemoPrograms/Demo_Date_Chooser.py b/DemoPrograms/Demo_Date_Chooser.py index fb5ecd90..723e2623 100644 --- a/DemoPrograms/Demo_Date_Chooser.py +++ b/DemoPrograms/Demo_Date_Chooser.py @@ -13,7 +13,6 @@ import itertools Copyright 2020 PySimpleGUI """ -sg.theme('Dark Red') def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sunday_plus=0, no_titlebar=True, title='Choose Date', keep_on_top=True, location=(None, None), close_when_chosen=False, icon=None, locale=None, month_names=None, day_abbreviations=None): """ @@ -129,7 +128,7 @@ def popup_get_date(start_mon=None, start_day=None, start_year=None, begin_at_sun while True: # Event Loop event, values = window.read() - if event in (None, 'Cancel'): + if event in (sg.WIN_CLOSED, 'Cancel'): chosen_mon_day_year = None break if event == 'Ok': diff --git a/DemoPrograms/Demo_Debugger_Built_Into_PSG.py b/DemoPrograms/Demo_Debugger_Built_Into_PSG.py index 79764b3c..f95b21a1 100644 --- a/DemoPrograms/Demo_Debugger_Built_Into_PSG.py +++ b/DemoPrograms/Demo_Debugger_Built_Into_PSG.py @@ -40,7 +40,7 @@ sg.show_debugger_popout_window() while True: # Your Event Loop event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Enable': window.enable_debugger() diff --git a/DemoPrograms/Demo_Debugger_Button.py b/DemoPrograms/Demo_Debugger_Button.py index 2f56ec43..4593346c 100644 --- a/DemoPrograms/Demo_Debugger_Button.py +++ b/DemoPrograms/Demo_Debugger_Button.py @@ -37,7 +37,7 @@ counter = 0 while True: # Your Event Loop event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Enable': window.enable_debugger() diff --git a/DemoPrograms/Demo_Debugger_ImWatchingYou.py b/DemoPrograms/Demo_Debugger_ImWatchingYou.py index ce59c1df..00f86b04 100644 --- a/DemoPrograms/Demo_Debugger_ImWatchingYou.py +++ b/DemoPrograms/Demo_Debugger_ImWatchingYou.py @@ -39,7 +39,7 @@ counter = 0 while True: # Your Event Loop event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Ok': print('You clicked Ok.... this is where print output goes') diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py index 6838e426..5bdb6687 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows.py @@ -23,7 +23,7 @@ while True: # Event Loop event, values = window.read(timeout=100) if event != sg.TIMEOUT_KEY: print(i, event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Popup': sg.popup('This is a BLOCKING popup','all windows remain inactive while popup active') @@ -44,7 +44,7 @@ while True: # Event Loop # print("win2 ", event) if event != sg.TIMEOUT_KEY: print("win2 ", event) - if event == 'Exit' or event is None: + if event == 'Exit' or event == sg.WIN_CLOSED: # print("Closing window 2", event) win2_active = False window2.close() diff --git a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py index 4ce575b7..58ce5f10 100644 --- a/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py +++ b/DemoPrograms/Demo_Design_Pattern_Multiple_Windows3.py @@ -29,7 +29,7 @@ while True: if window2_active: event2 = window2.read()[0] - if event2 in (None, 'Exit', '< Prev'): + if event2 in (sg.WIN_CLOSED, 'Exit', '< Prev'): window2_active = False window2.close() window.un_hide() @@ -48,7 +48,7 @@ while True: window3_active = False window2_active = True window2.un_hide() - elif ev3 in (None, 'Exit'): + elif ev3 in (sg.WIN_CLOSED, 'Exit'): break window.close() diff --git a/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py b/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py index 45fa657d..1ac36088 100644 --- a/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py +++ b/DemoPrograms/Demo_Design_Pattern_Persistent_Window.py @@ -12,7 +12,7 @@ window = sg.Window('Window Title', layout) while True: event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Show': # change the "output" element to be the value of "input" element diff --git a/DemoPrograms/Demo_Design_Patterns.py b/DemoPrograms/Demo_Design_Patterns.py index 4a922453..ac4f2db0 100644 --- a/DemoPrograms/Demo_Design_Patterns.py +++ b/DemoPrograms/Demo_Design_Patterns.py @@ -3,59 +3,69 @@ When creating a new PySimpleGUI program from scratch, start here. These are the accepted design patterns that cover the two primary use cases 1. A "One Shot" window -2. A persistent window that stays open after button clicks (uses an event loop) -3. A persistent window that need to perform update of an element before the window.read +2. A "One Shot" window in 1 line of code +3. A persistent window that stays open after button clicks (uses an event loop) +4. A persistent window that need to perform update of an element before the window.read """ -# ---------------------------------# -# DESIGN PATTERN 1 - Simple Window # -# ---------------------------------# +# -----------------------------------# +# DESIGN PATTERN 1 - One-shot Window # +# -----------------------------------# import PySimpleGUI as sg -sg.theme('Dark Blue 3') - layout = [[ sg.Text('My Oneshot') ], + [ sg.Input(key='-IN-') ], [ sg.Button('OK') ]] -window = sg.Window('My Oneshot', layout) +window = sg.Window('Design Pattern 1', layout) event, values = window.read() window.close() +# ---------------------------------------------# +# DESIGN PATTERN 2 - One-shot Window in 1 line # +# ---------------------------------------------# +import PySimpleGUI as sg + +event, values = sg.Window('Design Pattern 2', [[sg.Text('My Oneshot')],[sg.Input(key='-IN-')], [ sg.Button('OK') ]]).read(close=True) + + + # -------------------------------------# -# DESIGN PATTERN 2 - Persistent Window # +# DESIGN PATTERN 3 - Persistent Window # # -------------------------------------# import PySimpleGUI as sg -sg.theme('Dark Blue 3') +layout = [[sg.Text('My layout')], + [sg.Input(key='-INPUT-')], + [sg.Button('OK'), sg.Button('Cancel')] ] -layout = [[ sg.Text('My layout', text_color='red') ], - [ sg.Input(key='-INPUT-')], - [ sg.Button('OK'), sg.Button('Cancel') ]] - -window = sg.Window('Design Pattern 2 - Persistent Window', layout) +window = sg.Window('Design Pattern 3 - Persistent Window', layout) while True: # Event Loop event, values = window.read() - if event in (None, 'Cancel'): + if event == sg.WIN_CLOSED or event == 'Cancel': break window.close() # ------------------------------------------------------------------# -# DESIGN PATTERN 3 - Persistent Window with "early update" required # +# DESIGN PATTERN 4 - Persistent Window with "early update" required # # ------------------------------------------------------------------# import PySimpleGUI as sg -sg.theme('Dark Blue 3') - -layout = [[ sg.Text('My layout', key='-TEXT-KEY-') ], +layout = [[ sg.Text('My layout') ], + [sg.Input(key='-INPUT-')], + [sg.Text('Some text will be output here', key='-TEXT-KEY-')], [ sg.Button('OK'), sg.Button('Cancel') ]] -window = sg.Window('Design Pattern 3', layout, finalize=True) +window = sg.Window('Design Pattern 4', layout, finalize=True) -window['-TEXT-KEY-'].update('NEW Text') # Change the text field. Finalize allows us to do this +# Change the text field. Finalize allows us to do this +window['-TEXT-KEY-'].update('Modified before event loop') while True: # Event Loop event, values = window.read() - if event in (None, 'Cancel'): + if event == sg.WIN_CLOSED or event == 'Cancel': break + if event == 'OK': + window['-TEXT-KEY-'].update(values['-INPUT-']) window.close() diff --git a/DemoPrograms/Demo_Desktop_Floating_Toolbar.py b/DemoPrograms/Demo_Desktop_Floating_Toolbar.py index 658dfac1..377be986 100644 --- a/DemoPrograms/Demo_Desktop_Floating_Toolbar.py +++ b/DemoPrograms/Demo_Desktop_Floating_Toolbar.py @@ -46,7 +46,7 @@ def Launcher(): # ---===--- Loop taking in user input and executing appropriate program --- # while True: event, values = window.read() - if event == 'EXIT' or event is None: + if event == 'EXIT' or event == sg.WIN_CLOSED: break # exit button clicked if event == 'Program 1': print('Run your program 1 here!') diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py index e0d1216a..2c69f503 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Dashboard.py @@ -5,15 +5,21 @@ import psutil """ Desktop floating widget - CPU Cores Uses psutil to display: - CPU usage on each individual core - Information is updated once a second and is shown as an area graph that scrolls + CPU usage of each individual core + CPU utilization is updated every 500 ms by default + Utiliziation is shown as a scrolling area graph + To achieve a "rainmeter-style" of window, these featurees were used: + An alpha-channel setting of 0.8 to give a little transparency + No titlebar + Grab anywhere, making window easy to move around + Copyright 2020 PySimpleGUI """ GRAPH_WIDTH = 120 # each individual graph size in pixels GRAPH_HEIGHT = 40 TRANSPARENCY = .8 # how transparent the window looks. 0 = invisible, 1 = normal window NUM_COLS = 4 -POLL_FREQUENCY = 500 # how often to update graphs in milliseconds +POLL_FREQUENCY = 1500 # how often to update graphs in milliseconds colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29') @@ -21,19 +27,22 @@ colors = ('#23a0a0', '#56d856', '#be45be', '#5681d8', '#d34545', '#BE7C29') class DashGraph(object): def __init__(self, graph_elem, text_elem, starting_count, color): self.graph_current_item = 0 - self.graph_elem = graph_elem + self.graph_elem = graph_elem # type: sg.Graph self.text_elem = text_elem self.prev_value = starting_count self.max_sent = 1 self.color = color + self.line_list = [] # list of currently visible lines. Used to delete oild figures def graph_percentage_abs(self, value): - self.graph_elem.draw_line( + self.line_list.append(self.graph_elem.draw_line( # draw a line and add to list of lines (self.graph_current_item, 0), (self.graph_current_item, value), - color=self.color) + color=self.color)) if self.graph_current_item >= GRAPH_WIDTH: self.graph_elem.move(-1,0) + self.graph_elem.delete_figure(self.line_list[0]) # delete the oldest line + self.line_list = self.line_list[1:] # remove line id from list of lines else: self.graph_current_item += 1 @@ -41,16 +50,13 @@ class DashGraph(object): self.text_elem.update(text) def main(): - # A couple of "Uber Elements" that combine several elements and enable bulk edits + # A couple of "User defined elements" that combine several elements and enable bulk edits def Txt(text, **kwargs): return(sg.Text(text, font=('Helvetica 8'), **kwargs)) def GraphColumn(name, key): - col = sg.Col([[Txt(name, key=key+'_TXT_'), ], - [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black', - key=key+'_GRAPH_')]], pad=(2, 2)) - return col - + return sg.Column([[Txt(name, size=(10,1), key=key+'_TXT_'), ], + [sg.Graph((GRAPH_WIDTH, GRAPH_HEIGHT), (0, 0), (GRAPH_WIDTH, 100), background_color='black', key=key+'_GRAPH_')]], pad=(2, 2)) num_cores = len(psutil.cpu_percent(percpu=True)) # get the number of cores in the CPU @@ -59,15 +65,13 @@ def main(): # the clever Red X graphic red_x = "R0lGODlhEAAQAPeQAIsAAI0AAI4AAI8AAJIAAJUAAJQCApkAAJoAAJ4AAJkJCaAAAKYAAKcAAKcCAKcDA6cGAKgAAKsAAKsCAKwAAK0AAK8AAK4CAK8DAqUJAKULAKwLALAAALEAALIAALMAALMDALQAALUAALYAALcEALoAALsAALsCALwAAL8AALkJAL4NAL8NAKoTAKwbAbEQALMVAL0QAL0RAKsREaodHbkQELMsALg2ALk3ALs+ALE2FbgpKbA1Nbc1Nb44N8AAAMIWAMsvAMUgDMcxAKVABb9NBbVJErFYEq1iMrtoMr5kP8BKAMFLAMxKANBBANFCANJFANFEB9JKAMFcANFZANZcANpfAMJUEMZVEc5hAM5pAMluBdRsANR8AM9YOrdERMpIQs1UVMR5WNt8X8VgYMdlZcxtYtx4YNF/btp9eraNf9qXXNCCZsyLeNSLd8SSecySf82kd9qqc9uBgdyBgd+EhN6JgtSIiNuJieGHhOGLg+GKhOKamty1ste4sNO+ueenp+inp+HHrebGrefKuOPTzejWzera1O7b1vLb2/bl4vTu7fbw7ffx7vnz8f///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAJAALAAAAAAQABAAAAjUACEJHEiwYEEABniQKfNFgQCDkATQwAMokEU+PQgUFDAjjR09e/LUmUNnh8aBCcCgUeRmzBkzie6EeQBAoAAMXuA8ciRGCaJHfXzUMCAQgYooWN48anTokR8dQk4sELggBhQrU9Q8evSHiJQgLCIIfMDCSZUjhbYuQkLFCRAMAiOQGGLE0CNBcZYmaRIDLqQFGF60eTRoSxc5jwjhACFWIAgMLtgUocJFy5orL0IQRHAiQgsbRZYswbEhBIiCCH6EiJAhAwQMKU5DjHCi9gnZEHMTDAgAOw==" - layout = [[ sg.Button('', image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'), + layout = [[ sg.Button(image_data=red_x, button_color=('black', 'black'), key='Exit', tooltip='Closes window'), sg.Text(' CPU Core Usage')] ] # add on the graphs for rows in range(num_cores//NUM_COLS+1): - row = [] - for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)): - row.append(GraphColumn('CPU '+str(rows*NUM_COLS+cols), '_CPU_'+str(rows*NUM_COLS+cols))) - layout.append(row) + # for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS)): + layout += [[GraphColumn('CPU '+str(rows*NUM_COLS+cols), '_CPU_'+str(rows*NUM_COLS+cols)) for cols in range(min(num_cores-rows*NUM_COLS, NUM_COLS))]] # ---------------- Create Window ---------------- window = sg.Window('PSG System Dashboard', layout, @@ -82,28 +86,25 @@ def main(): finalize=True) # setup graphs & initial values - graphs = [] - for i in range(num_cores): - graphs.append(DashGraph(window['_CPU_'+str(i)+'_GRAPH_'], + graphs = [DashGraph(window['_CPU_'+str(i)+'_GRAPH_'], window['_CPU_'+str(i) + '_TXT_'], - 0, colors[i%6])) + 0, colors[i%6]) for i in range(num_cores) ] # ---------------- main loop ---------------- while True : # --------- Read and update window once every Polling Frequency -------- event, values = window.read(timeout=POLL_FREQUENCY) - if event in (None, 'Exit'): # Be nice and give an exit + if event in (sg.WIN_CLOSED, 'Exit'): # Be nice and give an exit break # read CPU for each core stats = psutil.cpu_percent(percpu=True) # update each graph - for i in range(num_cores): - graphs[i].graph_percentage_abs(stats[i]) - graphs[i].text_display('{} CPU {:2.0f}'.format(i, stats[i])) + for i, util in enumerate(stats): + graphs[i].graph_percentage_abs(util) + graphs[i].text_display('{} CPU {:2.0f}'.format(i, util)) window.close() if __name__ == "__main__": - main() diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py index 5baf7130..8e853f4e 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Graph.py @@ -1,6 +1,5 @@ #!/usr/bin/env python import PySimpleGUI as sg -import time import random import psutil from threading import Thread @@ -57,8 +56,7 @@ def main(): last_cpu = i = 0 prev_x, prev_y = 0, 0 while True: # the Event Loop - time.sleep(.5) - event, values = window.read(timeout=0) + event, values = window.read(timeout=500) if event in ('Quit', None): # always give ths user a way out break # do CPU measurement and graph it diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py index 70357bac..3cff8792 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization.py @@ -50,7 +50,7 @@ def main(): sg.Spin([x+1 for x in range(10)], 3, key='spin')] ] - window = sg.Window('CPU Utilization', layout + window = sg.Window('CPU Utilization', layout, no_titlebar=True, keep_on_top=True, alpha_channel=.8, grab_anywhere=True) # start cpu measurement thread @@ -63,7 +63,7 @@ def main(): # --------- Read and update window -------- event, values = window.read(timeout=timeout_value, timeout_key='Timeout') # --------- Do Button Operations -------- - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break timeout_value = int(values['spin']) * 1000 diff --git a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py index b1f9b579..3169bf2d 100644 --- a/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py +++ b/DemoPrograms/Demo_Desktop_Widget_CPU_Utilization_Simple.py @@ -26,7 +26,7 @@ while True: # --------- Read and update window -------- event, values = window.read(timeout=interval) # --------- Do Button Operations -------- - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break interval = int(values['-spin-'])*1000 @@ -38,4 +38,4 @@ while True: window['-text-'].update(f'CPU {cpu_percent:02.0f}%') # Broke out of main loop. Close the window. -window.CloseNonBlocking() +window.close() diff --git a/DemoPrograms/Demo_Desktop_Widget_Timer.py b/DemoPrograms/Demo_Desktop_Widget_Timer.py index 53ebe2c7..d4cede91 100644 --- a/DemoPrograms/Demo_Desktop_Widget_Timer.py +++ b/DemoPrograms/Demo_Desktop_Widget_Timer.py @@ -47,7 +47,7 @@ while True: else: event, values = window.read() # --------- Do Button Operations -------- - if event in (None, 'Exit'): # ALWAYS give a way out of program + if event in (sg.WIN_CLOSED, 'Exit'): # ALWAYS give a way out of program break if event == '-RESET-': paused_time = start_time = time_as_int() diff --git a/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py b/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py index e82d91ac..1e22edba 100644 --- a/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py +++ b/DemoPrograms/Demo_Desktop_Widget_psutil_Dashboard.py @@ -115,7 +115,7 @@ def main(): # --------- Read and update window once a second-------- event, values = window.read(timeout=1000) # Be nice and give an exit, expecially since there is no titlebar - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # ----- Network Graphs ----- netio = psutil.net_io_counters() diff --git a/DemoPrograms/Demo_Disable_Elements.py b/DemoPrograms/Demo_Disable_Elements.py index d113f6bc..9003fd9e 100644 --- a/DemoPrograms/Demo_Disable_Elements.py +++ b/DemoPrograms/Demo_Disable_Elements.py @@ -52,7 +52,7 @@ for key in key_list: while True: event, values = window.read() - if event in (None, 'exit'): + if event in (sg.WIN_CLOSED, 'exit'): break elif event == 'Disable': for key in key_list: diff --git a/DemoPrograms/Demo_EXE_Maker.py b/DemoPrograms/Demo_EXE_Maker.py index c5eb0530..5cc8cfb9 100644 --- a/DemoPrograms/Demo_EXE_Maker.py +++ b/DemoPrograms/Demo_EXE_Maker.py @@ -46,7 +46,7 @@ def Launcher(): folder_to_remove = os.path.join(source_path, source_filename[:-3]) file_to_remove = os.path.join( source_path, source_filename[:-3]+'.spec') - command_line = 'pyinstaller -wF "{}" {} {} {} {}'.format( + command_line = 'pyinstaller -wF --clean "{}" {} {} {} {}'.format( source_file, icon_option, workpath_option, dispath_option, specpath_option) if event == 'Make EXE': diff --git a/DemoPrograms/Demo_Email_Send.py b/DemoPrograms/Demo_Email_Send.py index 64399ccc..9d443f3a 100644 --- a/DemoPrograms/Demo_Email_Send.py +++ b/DemoPrograms/Demo_Email_Send.py @@ -76,7 +76,7 @@ def main(): while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Send': if sg.__name__ != 'PySimpleGUIWeb': # auto close popups not yet supported in PySimpleGUIWeb diff --git a/DemoPrograms/Demo_Event_Binding.py b/DemoPrograms/Demo_Event_Binding.py index b6f039cd..c67bfbd6 100644 --- a/DemoPrograms/Demo_Event_Binding.py +++ b/DemoPrograms/Demo_Event_Binding.py @@ -30,6 +30,6 @@ window['-IN-'].bind('', '+INPUT FOCUS+') while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break window.close() diff --git a/DemoPrograms/Demo_Font_Previewer.py b/DemoPrograms/Demo_Font_Previewer.py index 9f372a00..82fd33e1 100644 --- a/DemoPrograms/Demo_Font_Previewer.py +++ b/DemoPrograms/Demo_Font_Previewer.py @@ -34,7 +34,7 @@ window = sg.Window('My new window', layout) while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break text_elem = window['-text-'] print(event, values) diff --git a/DemoPrograms/Demo_Font_Sizer.py b/DemoPrograms/Demo_Font_Sizer.py index 84b56b57..716c587e 100644 --- a/DemoPrograms/Demo_Font_Sizer.py +++ b/DemoPrograms/Demo_Font_Sizer.py @@ -17,7 +17,7 @@ sz = fontSize window = sg.Window("Font size selector", layout, grab_anywhere=False) while True: event, values = window.read() - if event is None or event == 'Quit': + if event == sg.WIN_CLOSED or event == 'Quit': break sz_spin = int(values['spin']) sz_slider = int(values['slider']) diff --git a/DemoPrograms/Demo_Font_String.py b/DemoPrograms/Demo_Font_String.py index 831839a0..57c6d2fc 100644 --- a/DemoPrograms/Demo_Font_String.py +++ b/DemoPrograms/Demo_Font_String.py @@ -20,7 +20,7 @@ window = sg.Window('Font string builder', layout) text_elem = window['-text-'] while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break font_string = 'Helvitica ' font_string += str(values['-slider-']) diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship.py b/DemoPrograms/Demo_Game_Frontend_Battleship.py index a2b00405..e7e8cc0b 100644 --- a/DemoPrograms/Demo_Game_Frontend_Battleship.py +++ b/DemoPrograms/Demo_Game_Frontend_Battleship.py @@ -19,7 +19,7 @@ def Battleship(): while True: # The Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if randint(1,10) < 5: # simulate a hit or a miss window[event].update('H', button_color=('white','red')) diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py b/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py index ed87a44d..933d696d 100644 --- a/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py +++ b/DemoPrograms/Demo_Game_Frontend_Battleship_No_List_Comprehensions.py @@ -28,7 +28,7 @@ def Battleship(): while True: # The Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if randint(1,10) < 5: # simulate a hit or a miss window[event].update('H', button_color=('white','red')) diff --git a/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py b/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py index f3d0a74c..650dbae6 100644 --- a/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py +++ b/DemoPrograms/Demo_Game_Frontend_Battleship_Single_List_Comprehension.py @@ -22,7 +22,7 @@ def Battleship(): while True: # The Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if randint(1,10) < 5: # simulate a hit or a miss window[event].update('H', button_color=('white','red')) diff --git a/DemoPrograms/Demo_Google_TTS.py b/DemoPrograms/Demo_Google_TTS.py index 279d066c..1c850d73 100644 --- a/DemoPrograms/Demo_Google_TTS.py +++ b/DemoPrograms/Demo_Google_TTS.py @@ -24,7 +24,7 @@ i = 0 mixer.init() while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # Get the text and convert to mp3 file tts = gTTS(text=values[0], lang='en',slow=False) diff --git a/DemoPrograms/Demo_Graph_Ball_Game.py b/DemoPrograms/Demo_Graph_Ball_Game.py index 355083b7..9a2f9ad3 100644 --- a/DemoPrograms/Demo_Graph_Ball_Game.py +++ b/DemoPrograms/Demo_Graph_Ball_Game.py @@ -94,7 +94,7 @@ graph_elem.draw_line((0,300),(300,300)) while True: # Event Loop event, values = window.read(timeout=10) # print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break area.space.step(0.01) diff --git a/DemoPrograms/Demo_Graph_Drag_Rectangle.py b/DemoPrograms/Demo_Graph_Drag_Rectangle.py index b7fa91de..6c062f42 100644 --- a/DemoPrograms/Demo_Graph_Drag_Rectangle.py +++ b/DemoPrograms/Demo_Graph_Drag_Rectangle.py @@ -33,7 +33,7 @@ start_point = end_point = prior_rect = None while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break # exit if event == "-GRAPH-": # if there's a "Graph" event, then it's a mouse diff --git a/DemoPrograms/Demo_Graph_Drawing.py b/DemoPrograms/Demo_Graph_Drawing.py index 22082f7b..3778748e 100644 --- a/DemoPrograms/Demo_Graph_Drawing.py +++ b/DemoPrograms/Demo_Graph_Drawing.py @@ -8,17 +8,18 @@ layout = [[sg.Graph(canvas_size=(400, 400), graph_bottom_left=(0, 0), graph_top_ window = sg.Window('Graph test', layout, finalize=True) -graph = window['graph'] +graph = window['graph'] # type: sg.Graph circle = graph.draw_circle((75, 75), 25, fill_color='black', line_color='white') point = graph.draw_point((75, 75), 10, color='green') oval = graph.draw_oval((25, 300), (100, 280), fill_color='purple', line_color='purple') rectangle = graph.draw_rectangle((25, 300), (100, 280), line_color='purple') line = graph.draw_line((0, 0), (100, 100)) arc = graph.draw_arc((0, 0), (400, 400), 160, 10, style='arc', arc_color='blue') +poly = graph.draw_polygon(((10,10), (20,0), (40,200), (10,10)), fill_color='green') while True: event, values = window.read() print(event, values) - if event is None: + if event == sg.WIN_CLOSED: break if event in ('Blue', 'Red'): graph.TKCanvas.itemconfig(circle, fill=event) @@ -28,5 +29,6 @@ while True: graph.MoveFigure(oval, 10, 10) graph.MoveFigure(rectangle, 10, 10) graph.MoveFigure(arc, 10, 10) + graph.MoveFigure(poly, 10, 10) window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py index ead5d2f1..81c9a755 100644 --- a/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py +++ b/DemoPrograms/Demo_Graph_Drawing_And_Dragging_Figures.py @@ -29,7 +29,7 @@ def main(): [sg.R('Draw Rectangles', 1, key='-RECT-', enable_events=True)], [sg.R('Draw Circle', 1, key='-CIRCLE-', enable_events=True)], [sg.R('Draw Line', 1, key='-LINE-', enable_events=True)], - [sg.R('Draw point', 1, key='-POINT-', enable_events=True)], + [sg.R('Draw points', 1, key='-POINT-', enable_events=True)], [sg.R('Erase item', 1, key='-ERASE-', enable_events=True)], [sg.R('Erase all', 1, key='-CLEAR-', enable_events=True)], [sg.R('Send to back', 1, key='-BACK-', enable_events=True)], @@ -40,14 +40,14 @@ def main(): ] layout = [[sg.Graph( - canvas_size=(400, 400), - graph_bottom_left=(0, 0), - graph_top_right=(400, 400), - key="-GRAPH-", - change_submits=True, # mouse click events - background_color='lightblue', - drag_submits=True), sg.Col(col) ], - [sg.Text(key='info', size=(60, 1))]] + canvas_size=(400, 400), + graph_bottom_left=(0, 0), + graph_top_right=(800, 800), + key="-GRAPH-", + enable_events=True, + background_color='lightblue', + drag_submits=True), sg.Col(col) ], + [sg.Text(key='info', size=(60, 1))]] window = sg.Window("Drawing and Moving Stuff Around", layout, finalize=True) @@ -60,7 +60,8 @@ def main(): graph.bind('', '+RIGHT+') while True: event, values = window.read() - if event is None: + print(event, values) + if event == sg.WIN_CLOSED: break # exit if event in ('-MOVE-', '-MOVEALL-'): graph.Widget.config(cursor='fleur') @@ -94,7 +95,7 @@ def main(): elif values['-LINE-']: prior_rect = graph.draw_line(start_point, end_point, width=4) elif values['-POINT-']: - prior_rect = graph.draw_point(start_point, size=1) + graph.draw_point((x,y), size=8) elif values['-ERASE-']: for figure in drag_figures: graph.delete_figure(figure) diff --git a/DemoPrograms/Demo_Graph_Element.py b/DemoPrograms/Demo_Graph_Element.py index d3ee69c6..0eeb2bb2 100644 --- a/DemoPrograms/Demo_Graph_Element.py +++ b/DemoPrograms/Demo_Graph_Element.py @@ -48,7 +48,7 @@ def main(): while True: event, values = window.read(timeout=200) - if event == 'Quit' or event is None: + if event == 'Quit' or event == sg.WIN_CLOSED: break if g_response_time is None or prev_response_time == g_response_time: continue diff --git a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py index d5660d4d..0f8daed6 100644 --- a/DemoPrograms/Demo_Graph_Element_Sine_Wave.py +++ b/DemoPrograms/Demo_Graph_Element_Sine_Wave.py @@ -43,7 +43,7 @@ window = sg.Window('Graph of Sine Function', layout) while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break graph.erase() draw_axis() diff --git a/DemoPrograms/Demo_Graph_Noise.py b/DemoPrograms/Demo_Graph_Noise.py index 131b7c0e..388c6733 100644 --- a/DemoPrograms/Demo_Graph_Noise.py +++ b/DemoPrograms/Demo_Graph_Noise.py @@ -24,7 +24,7 @@ def main(): window = sg.Window('Enter graph size', layout) event, values = window.read() - if event is None or event == 'Cancel': + if event == sg.WIN_CLOSED or event == 'Cancel': return CANVAS_SIZE = int(values['w']), int(values['h']) @@ -54,7 +54,7 @@ def main(): figures = [] while True: event, values = window.read(timeout=0) - if event == 'Quit' or event is None: + if event == 'Quit' or event == sg.WIN_CLOSED: break graph_offset = random.randint(-10, 10) diff --git a/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py b/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py index 625095c6..8950f484 100644 --- a/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py +++ b/DemoPrograms/Demo_Graph_pymunk_2D_Graphics.py @@ -74,7 +74,7 @@ area.add_balls() while True: # Event Loop event, values = window.read(timeout=0) # print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break area.space.step(0.02) diff --git a/DemoPrograms/Demo_IP_Address_Entry.py b/DemoPrograms/Demo_IP_Address_Entry.py index ee9c731a..9033d2aa 100644 --- a/DemoPrograms/Demo_IP_Address_Entry.py +++ b/DemoPrograms/Demo_IP_Address_Entry.py @@ -24,7 +24,7 @@ window = sg.Window('Window Title', layout, return_keyboard_events=True) while True: # Event Loop event, values = window.read() print(event) - if event is None or event == 'Exit': + if event == sg.WIN_CLOSED or event == 'Exit': break elem = window.find_element_with_focus() diff --git a/DemoPrograms/Demo_Img_Viewer.py b/DemoPrograms/Demo_Img_Viewer.py index 2b97972f..9df35c40 100644 --- a/DemoPrograms/Demo_Img_Viewer.py +++ b/DemoPrograms/Demo_Img_Viewer.py @@ -88,7 +88,7 @@ while True: event, values = window.read() print(event, values) # perform button and keyboard operations - if event is None: + if event == sg.WIN_CLOSED: break elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34'): i += 1 diff --git a/DemoPrograms/Demo_Input_Auto_Complete.py b/DemoPrograms/Demo_Input_Auto_Complete.py index 22a87362..435bb311 100644 --- a/DemoPrograms/Demo_Input_Auto_Complete.py +++ b/DemoPrograms/Demo_Input_Auto_Complete.py @@ -5,12 +5,12 @@ import re Demo of using a borderless window to show possible matches for autocomplete feature ''' + def autocomplete_popup_show(text_list): layout = [[ sg.Listbox(values=text_list, size=(15, len(text_list)), change_submits=True, bind_return_key=True, key='-FLOATING-LISTBOX-', enable_events=True) ]] - return sg.Window("Borderless Window", layout, default_element_size=(12, 1), @@ -22,7 +22,6 @@ def autocomplete_popup_show(text_list): default_button_element_size=(12, 1), location=(1320, 622), finalize=True) - def predict_text(input, lista): pattern = re.compile('.*' + input + '.*') return [w for w in lista if re.match(pattern, w)] @@ -43,7 +42,7 @@ def main(): while True: # Event Loop event, values = window.read(timeout=500) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event != sg.TIMEOUT_KEY: diff --git a/DemoPrograms/Demo_Input_Validation.py b/DemoPrograms/Demo_Input_Validation.py index 4376ed69..35ba8926 100644 --- a/DemoPrograms/Demo_Input_Validation.py +++ b/DemoPrograms/Demo_Input_Validation.py @@ -14,7 +14,7 @@ window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # if last char entered not a digit if len(values['-INPUT-']) and values['-INPUT-'][-1] not in ('0123456789'): diff --git a/DemoPrograms/Demo_Invisible_Elements.py b/DemoPrograms/Demo_Invisible_Elements.py index 4d5c5668..b605781d 100644 --- a/DemoPrograms/Demo_Invisible_Elements.py +++ b/DemoPrograms/Demo_Invisible_Elements.py @@ -17,7 +17,7 @@ window = sg.Window('Window Title', layout) while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Invisible': window['-COL-'].update(visible=False) diff --git a/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py b/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py index afbc91b6..2e7e5fc7 100644 --- a/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py +++ b/DemoPrograms/Demo_Keyboard_ENTER_Presses_Button.py @@ -29,7 +29,7 @@ window = sg.Window('My new window', layout, return_keyboard_events=True) while True: # Event Loop event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break if event in ('\r', QT_ENTER_KEY1, QT_ENTER_KEY2): # Check for ENTER key # go find element with Focus diff --git a/DemoPrograms/Demo_Keyboard_Realtime.py b/DemoPrograms/Demo_Keyboard_Realtime.py index bc362784..dd76c5e8 100644 --- a/DemoPrograms/Demo_Keyboard_Realtime.py +++ b/DemoPrograms/Demo_Keyboard_Realtime.py @@ -18,7 +18,7 @@ while True: print('%s - %s' % (event, ord(event))) else: print(event) - elif event is None: + elif event == sg.WIN_CLOSED: break window.close() diff --git a/DemoPrograms/Demo_Keypad.py b/DemoPrograms/Demo_Keypad.py index a48a7848..dc9c3751 100644 --- a/DemoPrograms/Demo_Keypad.py +++ b/DemoPrograms/Demo_Keypad.py @@ -29,7 +29,7 @@ window = sg.Window('Keypad', layout, keys_entered = '' while True: event, values = window.read() # read the form - if event is None: # if the X button clicked, just exit + if event == sg.WIN_CLOSED: # if the X button clicked, just exit break if event == 'Clear': # clear keys if clear button keys_entered = '' diff --git a/DemoPrograms/Demo_LED_Clock_Weather.py b/DemoPrograms/Demo_LED_Clock_Weather.py index 9b9ff698..59686011 100644 --- a/DemoPrograms/Demo_LED_Clock_Weather.py +++ b/DemoPrograms/Demo_LED_Clock_Weather.py @@ -128,7 +128,7 @@ def led_clock(): while True: # Wake up once a second to update the clock and weather event, values = gui.window.read(timeout=1000) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # update clock gui.update_clock() diff --git a/DemoPrograms/Demo_LED_Indicators.py b/DemoPrograms/Demo_LED_Indicators.py index 4f44b907..2aba8150 100644 --- a/DemoPrograms/Demo_LED_Indicators.py +++ b/DemoPrograms/Demo_LED_Indicators.py @@ -35,7 +35,7 @@ window = sg.Window('My new window', layout, default_element_size=(12, 1), auto_s i = 0 while True: # Event Loop event, value = window.read(timeout=400) - if event == 'Exit' or event is None: + if event == 'Exit' or event == sg.WIN_CLOSED: break if value is None: break diff --git a/DemoPrograms/Demo_Layout_Extend.py b/DemoPrograms/Demo_Layout_Extend.py index bd006955..bacbfa62 100644 --- a/DemoPrograms/Demo_Layout_Extend.py +++ b/DemoPrograms/Demo_Layout_Extend.py @@ -22,7 +22,7 @@ i = 0 while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == '-B1-': window.extend_layout(window['-COL1-'], [[sg.T('A New Input Line'), sg.I(key=f'-IN-{i}-')]]) diff --git a/DemoPrograms/Demo_Layout_Generation.py b/DemoPrograms/Demo_Layout_Generation.py index 7ac1702f..f794f874 100644 --- a/DemoPrograms/Demo_Layout_Generation.py +++ b/DemoPrograms/Demo_Layout_Generation.py @@ -297,7 +297,7 @@ def layout8(): while True: # Event Loop event, values = window.read() - if event in (None, 'SUBMIT'): + if event in (sg.WIN_CLOSED, 'SUBMIT'): break sg.popup('The answers submitted were', values) window.close() diff --git a/DemoPrograms/Demo_Listbox_Search_Filter.py b/DemoPrograms/Demo_Listbox_Search_Filter.py index 3db24890..6504e749 100644 --- a/DemoPrograms/Demo_Listbox_Search_Filter.py +++ b/DemoPrograms/Demo_Listbox_Search_Filter.py @@ -13,7 +13,7 @@ window = sg.Window('Listbox with Search', layout) # Event Loop while True: event, values = window.read() - if event in (None, 'Exit'): # always check for closed window + if event in (sg.WIN_CLOSED, 'Exit'): # always check for closed window break if values['-INPUT-'] != '': # if a keystroke entered in search field search = values['-INPUT-'] diff --git a/DemoPrograms/Demo_MIDI_Player.py b/DemoPrograms/Demo_MIDI_Player.py index d58f08e0..a66c41d5 100644 --- a/DemoPrograms/Demo_MIDI_Player.py +++ b/DemoPrograms/Demo_MIDI_Player.py @@ -12,6 +12,7 @@ PLAYER_COMMAND_RESTART_SONG = 4 helv15 = 'Helvetica 15' + # ---------------------------------------------------------------------- # # PlayerGUI CLASS # # ---------------------------------------------------------------------- # @@ -49,45 +50,37 @@ class PlayerGUI(): sg.FolderBrowse(size=(10, 1))], [sg.Text('_' * 250, auto_size_text=False, size=(100, 1))], [sg.Text('Choose MIDI Output Device', size=(22, 1)), - sg.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), key='device')], + sg.Listbox(values=self.PortList, size=(30, len(self.PortList) + 1), default_values=(self.PortList[0],), key='device')], [sg.Text('_' * 250, auto_size_text=False, size=(100, 1))], [sg.SimpleButton('PLAY', size=(12, 2), button_color=('red', 'white'), font=helv15, bind_return_key=True), sg.Text(' ' * 2, size=(4, 1)), sg.Cancel(size=(8, 2), font=helv15)]] - window = sg.Window('MIDI File Player', layout, auto_size_text=False, - default_element_size=(30, 1), font=helv) + window = sg.Window('MIDI File Player', layout, auto_size_text=False, default_element_size=(30, 1), font=helv) self.Window = window return window.read() def PlayerPlaybackGUIStart(self, NumFiles=1): # ------- Make a new FlexForm ------- # - image_pause = './ButtonGraphics/Pause.png' - image_restart = './ButtonGraphics/Restart.png' - image_next = './ButtonGraphics/Next.png' - image_exit = './ButtonGraphics/Exit.png' - self.TextElem = sg.Text('Song loading....', size=(70, 5 + NumFiles), font=("Helvetica", 14), auto_size_text=False) self.SliderElem = sg.Slider(range=(1, 100), size=(50, 8), orientation='h', text_color='#f0f0f0') - css = { - 'image_size': (50, 50), - 'image_subsample': 2, - 'border_width': 0, - 'button_color': sg.TRANSPARENT_BUTTON - } + + def pbutton(image_data, key): + return sg.Button(image_data=image_data, key=key, image_size=(50,50), image_subsample=2, border_width=0, button_color=(sg.theme_background_color(), sg.theme_background_color())) + layout = [ [sg.Text('MIDI File Player', size=(30, 1), font=("Helvetica", 25))], [self.TextElem], [self.SliderElem], - [sg.Button('', image_filename=image_pause, **css, key='PAUSE'), sg.Text(' '), - sg.Button('', image_filename=image_next, **css, key='NEXT'), sg.Text(' '), - sg.Button('', image_filename=image_restart, **css, key='Restart Song'), sg.Text(' '), - sg.Button('', image_filename=image_exit, **css, key='EXIT')] + [pbutton(image_pause,'PAUSE'), sg.Text(' '), + pbutton(image_next, 'NEXT'), sg.Text(' '), + pbutton(image_restart, key='Restart Song'), sg.Text(' '), + pbutton(image_exit, 'EXIT')] ] window = sg.Window('MIDI File Player', layout, default_element_size=( @@ -106,7 +99,7 @@ class PlayerGUI(): return PLAYER_COMMAND_EXIT self.TextElem.update(DisplayString) event, (values) = window.read(timeout=0) - if event is None: + if event == sg.WIN_CLOSED: return PLAYER_COMMAND_EXIT if event == 'PAUSE': return PLAYER_COMMAND_PAUSE @@ -247,5 +240,17 @@ def main(): # ---------------------------------------------------------------------- # # LAUNCH POINT -- program starts and ends here # # ---------------------------------------------------------------------- # + +image_exit = b'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' + + +image_next = b'iVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAYAAABw4pVUAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAACxIAAAsSAdLdfvwAAB8WSURBVHhezZ17sJZVvccfN8ZFASER2GyQ5KLizgtC4x3MQjPUtJS0qaYxm2aOnVNNnZrKM+lMTae/Ujs459SMWmraTsyOIaOmJ0jykopIXFS2RggbNijiVm6Fnt9n8X5ff/vHet797s3e4HfmO2s961nPb631/T3r8lze5z2oeA+jqalpUENDw5jx48c3jhw5ctKQIUOOPeaYY462XaOMQxwHG8Gbxg7Hjc8///wLHR0dq9rb21evWbOm7e23316/bt267bbvPYn3jEMOOuig4n3ve1//iRMnjm5ubp5hzjjniCOOONUc0mi7hxobUkbDO++8U4nVBjYd3ja+YQ5p27Rp0+PmlEeWL1++qLW1dcM//vGPXfXa7GsccIeMGDGi36RJk44/7rjj5pgzZltSs7Ef+6JIPRUtOMZv7zYuN6fMX7FiRcvq1auXbd68mbQDhgPikIMPPvggc8IYc8InrDd8bsCAASdY8iHs86LXE68F74g64tt27tz5nPWa28w5vzPnrP/nP//ZszNgH7DfHTJlypTJM2fOvNqGpM/b5nDScmLXG5ZBQtcbAhffYkPaLxcuXDh35cqVL1bS9gverU0fwnpEg/WIKTNmzPi6OeJSa/hhpOdEFuN2TFM8By92jJeladuHZn+rOebuRYsW/cR6zErrMcxDfYo9JfchzBHDPvrRj17b2Nh4pW2yIioVF9qkW43XSoM6zsOLGmkLhJpp/jjFK+hoa2u7+Q9/+MO15pjXK2l9gj5zyPvf//7+1iPmnHjiiT+who0nLQrpiehirW1/DMxBooqILuEVL9v29LaAlbdm6dKl11iPaXnttdd2pcReRq87hMofddRRE+bMmXODTdbnW1I/CeeFhF50cffu3dm4qONkIweJmBMd9uvXLxv3lA1Rdg27bfJf0NLS8tWXX375pbI69BS96hBrSMMFF1zwqZNOOum/bHMkaV44L6iI6LWoPIg0cODAYtCgQcVhhx2WQrtuKfr3759CYNcTxa5du1K4ffv2YuvWrSncsWNHsiPxCWuRPCJOIATeOYb2Z5999iu///3v55ntXptbes0hdj0x+OKL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' + +image_pause = b'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' + +image_restart = b'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' + + + if __name__ == '__main__': main() diff --git a/DemoPrograms/Demo_Matplotlib.py b/DemoPrograms/Demo_Matplotlib.py index 0f76faa3..4a281a4d 100644 --- a/DemoPrograms/Demo_Matplotlib.py +++ b/DemoPrograms/Demo_Matplotlib.py @@ -23,78 +23,81 @@ Basic steps are: # ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE ------------------------------- - -# Fixing random state for reproducibility -np.random.seed(19680801) - -# make up some data in the interval ]0, 1[ -y = np.random.normal(loc=0.5, scale=0.4, size=1000) -y = y[(y > 0) & (y < 1)] -y.sort() -x = np.arange(len(y)) - -# plot with various axes scales -plt.figure(1) - -# linear -plt.subplot(221) -plt.plot(x, y) -plt.yscale('linear') -plt.title('linear') -plt.grid(True) +# +# # Goal is to have your plot contained in the variable "fig" +# +# # Fixing random state for reproducibility +# np.random.seed(19680801) +# +# # make up some data in the interval ]0, 1[ +# y = np.random.normal(loc=0.5, scale=0.4, size=1000) +# y = y[(y > 0) & (y < 1)] +# y.sort() +# x = np.arange(len(y)) +# +# # plot with various axes scales +# plt.figure(1) +# +# # linear +# plt.subplot(221) +# plt.plot(x, y) +# plt.yscale('linear') +# plt.title('linear') +# plt.grid(True) +# +# # log +# plt.subplot(222) +# plt.plot(x, y) +# plt.yscale('log') +# plt.title('log') +# plt.grid(True) +# +# # symmetric log +# plt.subplot(223) +# plt.plot(x, y - y.mean()) +# plt.yscale('symlog', linthreshy=0.01) +# plt.title('symlog') +# plt.grid(True) +# +# # logit +# plt.subplot(224) +# plt.plot(x, y) +# plt.yscale('logit') +# plt.title('logit') +# plt.grid(True) +# plt.gca().yaxis.set_minor_formatter(NullFormatter()) +# plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, +# wspace=0.35) +# fig = plt.gcf() +# -# log -plt.subplot(222) -plt.plot(x, y) -plt.yscale('log') -plt.title('log') -plt.grid(True) - - -# symmetric log -plt.subplot(223) -plt.plot(x, y - y.mean()) -plt.yscale('symlog', linthreshy=0.01) -plt.title('symlog') -plt.grid(True) - -# logit -plt.subplot(224) -plt.plot(x, y) -plt.yscale('logit') -plt.title('logit') -plt.grid(True) -plt.gca().yaxis.set_minor_formatter(NullFormatter()) -plt.subplots_adjust(top=0.92, bottom=0.08, left=0.10, right=0.95, hspace=0.25, - wspace=0.35) -fig = plt.gcf() # if using Pyplot then get the figure from the plot -figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds +fig = matplotlib.figure.Figure(figsize=(5, 4), dpi=100) +t = np.arange(0, 3, .01) +fig.add_subplot(111).plot(t, 2 * np.sin(2 * np.pi * t)) # ------------------------------- END OF YOUR MATPLOTLIB CODE ------------------------------- # ------------------------------- Beginning of Matplotlib helper code ----------------------- - -def draw_figure(canvas, figure, loc=(0, 0)): +def draw_figure(canvas, figure): figure_canvas_agg = FigureCanvasTkAgg(figure, canvas) figure_canvas_agg.draw() figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1) return figure_canvas_agg + # ------------------------------- Beginning of GUI CODE ------------------------------- - # define the window layout -layout = [[sg.Text('Plot test', font='Any 18')], - [sg.Canvas(size=(figure_w, figure_h), key='canvas')], - [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]] +layout = [[sg.Text('Plot test')], + [sg.Canvas(key='-CANVAS-')], + [sg.Button('Ok')]] # create the form and show it without the plot -window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', - layout, finalize=True) +window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True, element_justification='center', font='Helvetica 18') # add the plot to the window -fig_canvas_agg = draw_figure(window['canvas'].TKCanvas, fig) +fig_canvas_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) event, values = window.read() diff --git a/DemoPrograms/Demo_Matplotlib_Browser.py b/DemoPrograms/Demo_Matplotlib_Browser.py index 98fb8b40..85c51c48 100644 --- a/DemoPrograms/Demo_Matplotlib_Browser.py +++ b/DemoPrograms/Demo_Matplotlib_Browser.py @@ -865,7 +865,7 @@ figure_agg = None while True: event, values = window.read() # print(event, values) # helps greatly when debugging - if event in (None, 'Exit'): # if user closed window or clicked Exit button + if event in (sg.WIN_CLOSED, 'Exit'): # if user closed window or clicked Exit button break if figure_agg: # ** IMPORTANT ** Clean up previous drawing before drawing again diff --git a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py index 228daf77..6344e89d 100644 --- a/DemoPrograms/Demo_Matplotlib_Browser_Paned.py +++ b/DemoPrograms/Demo_Matplotlib_Browser_Paned.py @@ -890,7 +890,7 @@ figure_agg = None while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if figure_agg: diff --git a/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py b/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py index d593a22c..2ba9f2b7 100644 --- a/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py +++ b/DemoPrograms/Demo_Matplotlib_Embedded_Toolbar.py @@ -57,7 +57,7 @@ window = sg.Window('Graph with controls', layout) while True: event, values = window.read() print(event, values) - if event in (None, 'Exit'): # always, always give a way out! + if event in (sg.WIN_CLOSED, 'Exit'): # always, always give a way out! break elif event is 'Plot': # ------------------------------- PASTE YOUR MATPLOTLIB CODE HERE diff --git a/DemoPrograms/Demo_Matplotlib_PyLab.py b/DemoPrograms/Demo_Matplotlib_PyLab.py index 4a09e6da..f12e17af 100644 --- a/DemoPrograms/Demo_Matplotlib_PyLab.py +++ b/DemoPrograms/Demo_Matplotlib_PyLab.py @@ -16,7 +16,6 @@ from numpy import cos x = pylab.linspace(-3, 3, 30) y = x**2 - pylab.plot(x, sin(x)) pylab.plot(x, cos(x), 'r-') pylab.plot(x, -sin(x), 'g--') diff --git a/DemoPrograms/Demo_Matplotlib_Two_Windows.py b/DemoPrograms/Demo_Matplotlib_Two_Windows.py index d5eb05cf..ffb71c14 100644 --- a/DemoPrograms/Demo_Matplotlib_Two_Windows.py +++ b/DemoPrograms/Demo_Matplotlib_Two_Windows.py @@ -20,7 +20,7 @@ window = sg.Window('Have some Matplotlib....', layout) while True: event, values = window.read() - if event in (None, 'Cancel'): + if event in (sg.WIN_CLOSED, 'Cancel'): break elif event == 'Plot': draw_plot() diff --git a/DemoPrograms/Demo_Media_Player.py b/DemoPrograms/Demo_Media_Player.py index 89814502..cfd845c6 100644 --- a/DemoPrograms/Demo_Media_Player.py +++ b/DemoPrograms/Demo_Media_Player.py @@ -33,7 +33,7 @@ def MediaPlayerGUI(): while True: event, values = window.read(timeout=100) - if event == 'Exit' or event is None: + if event == 'Exit' or event == sg.WIN_CLOSED: break # If a button was pressed, display it on the GUI by updating the text element if event != sg.TIMEOUT_KEY: diff --git a/DemoPrograms/Demo_Media_Player_VLC_Based.py b/DemoPrograms/Demo_Media_Player_VLC_Based.py index 268308cf..9fa5aec8 100644 --- a/DemoPrograms/Demo_Media_Player_VLC_Based.py +++ b/DemoPrograms/Demo_Media_Player_VLC_Based.py @@ -41,7 +41,7 @@ else: #------------ The Event Loop ------------# while True: event, values = window.read(timeout=1000) # run with a timeout so that current location can be updated - if event is None: + if event == sg.WIN_CLOSED: break if event == 'play': diff --git a/DemoPrograms/Demo_Menus.py b/DemoPrograms/Demo_Menus.py index 03d6b730..cc545376 100644 --- a/DemoPrograms/Demo_Menus.py +++ b/DemoPrograms/Demo_Menus.py @@ -49,7 +49,7 @@ def test_menus(): # ------ Loop & Process button menu choices ------ # while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break print(event, values) # ------ Process menu choices ------ # diff --git a/DemoPrograms/Demo_Multiline_Multicolored_Text.py b/DemoPrograms/Demo_Multiline_Multicolored_Text.py index 0766f429..8c902e9c 100644 --- a/DemoPrograms/Demo_Multiline_Multicolored_Text.py +++ b/DemoPrograms/Demo_Multiline_Multicolored_Text.py @@ -1,12 +1,12 @@ import PySimpleGUI as sg # import PySimpleGUIQt as sg +print(sg.version) + """ Demonstration of how to work with multiple colors when outputting text to a multiline element """ -sg.theme('Dark Blue 3') - MLINE_KEY = '-MLINE-'+sg.WRITE_ONLY_KEY layout = [ [sg.Text('Demonstration of Multiline Element\'s ability to show multiple colors ')], [sg.Multiline(size=(60,20), key=MLINE_KEY)], @@ -15,19 +15,21 @@ layout = [ [sg.Text('Demonstration of Multiline Element\'s ability to show mult window = sg.Window('Demonstration of Multicolored Multline Text', layout) +# print = lambda *args, **kwargs: window[MLINE_KEY].print(*args, **kwargs, text_color='red') + while True: event, values = window.read() # type: (str, dict) print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if 'Text Blue' in event: - window[MLINE_KEY].update('This is blue text', text_color_for_value='blue', append=True) + window[MLINE_KEY].update('This is blue text\n', text_color_for_value='blue', append=True) if 'Text Green' in event: - window[MLINE_KEY].update('This is green text', text_color_for_value='green', append=True) + window[MLINE_KEY].update('This is green text\n', text_color_for_value='green', append=True) if 'Background Blue' in event: - window[MLINE_KEY].update('This is Blue Background', background_color_for_value='blue', append=True) + window[MLINE_KEY].update('This is Blue Background\n', background_color_for_value='blue', append=True) if 'Background Green' in event: - window[MLINE_KEY].update('This is Green Backgroundt', background_color_for_value='green', append=True) + window[MLINE_KEY].update('This is Green Background\n', background_color_for_value='green', append=True) if 'White on Green' in event: window[MLINE_KEY].update('This is white text on a green background', text_color_for_value='white', background_color_for_value='green', append=True) if event == 'Plain': diff --git a/DemoPrograms/Demo_Multiple_Windows_Experimental.py b/DemoPrograms/Demo_Multiple_Windows_Experimental.py index e8c20ca1..43f931b7 100644 --- a/DemoPrograms/Demo_Multiple_Windows_Experimental.py +++ b/DemoPrograms/Demo_Multiple_Windows_Experimental.py @@ -28,19 +28,19 @@ window3 = sg.Window('My new window', layout3, location=(800,750), return_keyboar while True: # Event Loop event, values = window1.read(timeout=0) - if event is None: + if event == sg.WIN_CLOSED: break elif event != '__timeout__': print(event, values) event, values = window2.read(timeout=0) - if event is None: + if event == sg.WIN_CLOSED: break elif event != '__timeout__': print(event, values) event, values = window3.read(timeout=0) - if event is None: + if event == sg.WIN_CLOSED: break elif event != '__timeout__': print(event, values) diff --git a/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py b/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py index 3b3ea9e4..b0978f6b 100644 --- a/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py +++ b/DemoPrograms/Demo_Multithreaded_Animated_Shell_Command.py @@ -2,6 +2,7 @@ import subprocess import PySimpleGUI as sg import threading + """ Demo - Run a shell command while displaying an animated GIF to inform the user the program is still running. @@ -32,5 +33,6 @@ while True: sg.popup_animated(None) output = proc.__str__().replace('\\r\\n', '\n') -sg.popup_scrolled(output) +sg.popup_scrolled(output, font='Courier 10') + diff --git a/DemoPrograms/Demo_Multithreaded_Different_Threads.py b/DemoPrograms/Demo_Multithreaded_Different_Threads.py index 937d5965..998fb0c1 100644 --- a/DemoPrograms/Demo_Multithreaded_Different_Threads.py +++ b/DemoPrograms/Demo_Multithreaded_Different_Threads.py @@ -115,7 +115,7 @@ def the_gui(gui_queue): while True: # wait for up to 100 ms for a GUI event event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # --------------- Loop through all messages coming in from threads --------------- while True: # loop executes until runs out of messages in Queue diff --git a/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py b/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py index 52f82a04..4146d9d1 100644 --- a/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py +++ b/DemoPrograms/Demo_Multithreaded_Long_Shell_Operation_Animated.py @@ -13,6 +13,8 @@ import PySimpleGUI as sg # Here we're running a simple "pip list" command and using the built-in animated GIF. output = sg.shell_with_animation('pip', ('list',), message='Loading...', font='Helvetica 15') +sg.popup_scrolled(output, font='Courier 10') +output = sg.shell_with_animation('dir', message='Loading...', font='Helvetica 15') # output = sg.shell_with_animation(r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", message='Loading...', font='Helvetica 15') sg.popup_scrolled(output, font='Courier 10') diff --git a/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py b/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py index ca8808f9..8107b9a9 100644 --- a/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py +++ b/DemoPrograms/Demo_Multithreaded_Long_Task_Simple.py @@ -64,7 +64,7 @@ def the_gui(): # --------------------- EVENT LOOP --------------------- while True: event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event.startswith('Do') and not thread: print('Thread Starting! Long work....sending value of {} seconds'.format(float(values['-SECONDS-']))) diff --git a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py index 85585691..367e2e43 100644 --- a/DemoPrograms/Demo_Multithreaded_Long_Tasks.py +++ b/DemoPrograms/Demo_Multithreaded_Long_Tasks.py @@ -58,7 +58,7 @@ def the_gui(): # --------------------- EVENT LOOP --------------------- while True: event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event.startswith('Do'): try: diff --git a/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py b/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py index 00c0b602..40e0a892 100644 --- a/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py +++ b/DemoPrograms/Demo_Multithreaded_Multiple_Threads.py @@ -72,7 +72,7 @@ def the_gui(): while True: # wait for up to 100 ms for a GUI event event, values = window.read(timeout=100) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Go': # clicking "Go" starts a long running work item by starting thread window['-OUTPUT-'].update('Starting long work %s' % work_id) diff --git a/DemoPrograms/Demo_Notification_Window_Multiprocessing.py b/DemoPrograms/Demo_Notification_Window_Multiprocessing.py index 27953999..e70ebef0 100644 --- a/DemoPrograms/Demo_Notification_Window_Multiprocessing.py +++ b/DemoPrograms/Demo_Notification_Window_Multiprocessing.py @@ -3,17 +3,19 @@ import textwrap from multiprocessing import Process ''' - Notification Window Demo Program - Shamelessly stolen from PySimpleGUI user ncotrb + Multiprocessing based Notification Window Demo Program + + The PySimpleGUI code for showing the windows themselves ovolved from code supplied by PySimpleGUI user ncotrb Displays a small informational window with an Icon and a message in the lower right corner of the display Option to fade in/out or immediatealy display. - You can click on the notification window to speed things along. The idea is that if you click while fading in, you should immediately see the info. If - you click while info is displaying or while fading out, the window closes immediately. + You can click on the notification window to speed things along. The idea is that if you click while fading in, you should immediately see the info. If you click while info is displaying or while fading out, the window closes immediately. Note - In order to import and use these calls, you must make the call from a "main program". - + + Copyright 2020 PySimpleGUI + ''' @@ -37,10 +39,12 @@ image64_success = b'iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAAA3NCSVQICAjb def _display_notification(title, message, icon=image64_success, display_duration_in_ms=DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS, fade_in_duration=DEFAULT_FADE_IN_DURATION, alpha=0.9, location=None): """ + The PROCESS that is started when a toaster message is to be displayed. + Note that this is not a user callable function. + It does the actual work of creating and showing the window on the screen + Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message - The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For - example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It - a way for the user to quickly dismiss the window. + The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window. :param title: (str) Text to be shown at the top of the window in a larger font :param message: (str) Text message that makes up the majority of the window :param icon: (base64) A base64 encoded PNG/GIF image that will be displayed in the window @@ -94,9 +98,7 @@ def _display_notification(title, message, icon=image64_success, display_duration def display_notification(title, message, icon=image64_success, display_duration_in_ms=DEFAULT_DISPLAY_DURATION_IN_MILLISECONDS, fade_in_duration=DEFAULT_FADE_IN_DURATION, alpha=0.9, location=None): """ Displays a "notification window", usually in the bottom right corner of your display. Has an icon, a title, and a message - The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For - example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It - a way for the user to quickly dismiss the window. + The window will slowly fade in and out if desired. Clicking on the window will cause it to move through the end the current "phase". For example, if the window was fading in and it was clicked, then it would immediately stop fading in and instead be fully visible. It's a way for the user to quickly dismiss the window. :param title: (str) Text to be shown at the top of the window in a larger font :param message: (str) Text message that makes up the majority of the window :param icon: (base64) A base64 encoded PNG/GIF image that will be displayed in the window diff --git a/DemoPrograms/Demo_OpenCV_7_Line_Program.py b/DemoPrograms/Demo_OpenCV_7_Line_Program.py index d3d97453..765c8fe6 100644 --- a/DemoPrograms/Demo_OpenCV_7_Line_Program.py +++ b/DemoPrograms/Demo_OpenCV_7_Line_Program.py @@ -4,7 +4,7 @@ window = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename= cap = cv2.VideoCapture(0) # Setup the camera as a capture device while True: # The PSG "Event Loop" event, values = window.read(timeout=20, timeout_key='timeout') # get events for the window with 20ms max wait - if event is None: break # if user closed window, quit + if event == sg.WIN_CLOSED: break # if user closed window, quit window['image'].update(data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) # Update image in window """ diff --git a/DemoPrograms/Demo_OpenCV_Webcam.py b/DemoPrograms/Demo_OpenCV_Webcam.py index 002986f9..cc999569 100644 --- a/DemoPrograms/Demo_OpenCV_Webcam.py +++ b/DemoPrograms/Demo_OpenCV_Webcam.py @@ -29,7 +29,7 @@ def main(): while True: event, values = window.read(timeout=20) - if event == 'Exit' or event is None: + if event == 'Exit' or event == sg.WIN_CLOSED: return elif event == 'Record': diff --git a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py index 131adfd2..4798c5d7 100644 --- a/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py +++ b/DemoPrograms/Demo_OpenCV_Webcam_ASCII.py @@ -59,7 +59,7 @@ cap = cv2.VideoCapture(0) while True: event, values = window.read(timeout=0) - if event in ('Exit', None): + if event in ('Exit', sg.WIN_CLOSED): break # Read image from capture device (camera) ret, frame = cap.read() diff --git a/DemoPrograms/Demo_PDF_Viewer.py b/DemoPrograms/Demo_PDF_Viewer.py index 50af928e..52a82bf8 100644 --- a/DemoPrograms/Demo_PDF_Viewer.py +++ b/DemoPrograms/Demo_PDF_Viewer.py @@ -123,7 +123,7 @@ while True: event, values = window.read(timeout=100) zoom = 0 force_page = False - if event is None: + if event == sg.WIN_CLOSED: break if event in ("Escape:27",): # this spares me a 'Quit' button! diff --git a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py index 61a24ad7..1c21cedb 100644 --- a/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py +++ b/DemoPrograms/Demo_PNG_Thumbnail_Viewer.py @@ -98,7 +98,7 @@ while True: event, values = window.read() display_index = values['-slider-'] # --------------------- Button & Keyboard --------------------- - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event in ('MouseWheel:Down', 'Down:40',) and display_index < len(png_files)-1: display_index += 4 diff --git a/DemoPrograms/Demo_PNG_Viewer.py b/DemoPrograms/Demo_PNG_Viewer.py index f23c14a1..3604ec6e 100644 --- a/DemoPrograms/Demo_PNG_Viewer.py +++ b/DemoPrograms/Demo_PNG_Viewer.py @@ -46,7 +46,7 @@ def main(): event, values = window.read() # --------------------- Button & Keyboard --------------------- - if event is None: + if event == sg.WIN_CLOSED: break elif event in ('Next', 'MouseWheel:Down', 'Down:40', 'Next:34') and i < len(png_files)-1: i += 1 diff --git a/DemoPrograms/Demo_Paned_Window.py b/DemoPrograms/Demo_Paned_Window.py index aa987117..13b8b005 100644 --- a/DemoPrograms/Demo_Paned_Window.py +++ b/DemoPrograms/Demo_Paned_Window.py @@ -39,7 +39,7 @@ window = sg.Window('Window Title', layout, border_depth=5, while True: # Event Loop event, values = window.read() print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Remove': window['-COL2-'].update(visible=False) diff --git a/DemoPrograms/Demo_Password_Login.py b/DemoPrograms/Demo_Password_Login.py index 2da788d8..ec66c779 100644 --- a/DemoPrograms/Demo_Password_Login.py +++ b/DemoPrograms/Demo_Password_Login.py @@ -33,7 +33,7 @@ def main(): while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break password = values['-password-'] diff --git a/DemoPrograms/Demo_Pi_LEDs.py b/DemoPrograms/Demo_Pi_LEDs.py index 23e28109..b516d806 100644 --- a/DemoPrograms/Demo_Pi_LEDs.py +++ b/DemoPrograms/Demo_Pi_LEDs.py @@ -64,7 +64,7 @@ window = sg.Window('Raspberry Pi GUI', layout, grab_anywhere=False) while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event == 'Switch LED': diff --git a/DemoPrograms/Demo_Pi_Robotics.py b/DemoPrograms/Demo_Pi_Robotics.py index a3124872..a1ec9d3a 100644 --- a/DemoPrograms/Demo_Pi_Robotics.py +++ b/DemoPrograms/Demo_Pi_Robotics.py @@ -83,7 +83,7 @@ def RemoteControlExample_NoGraphics(): else: window['status'].update('') # if user clicked quit button OR closed the form using the X, then break out of loop - if event in (None, 'Quit'): + if event in (sg.WIN_CLOSED, 'Quit'): break window.close() diff --git a/DemoPrograms/Demo_Ping_Line_Graph.py b/DemoPrograms/Demo_Ping_Line_Graph.py index f3b0b829..732a2d59 100644 --- a/DemoPrograms/Demo_Ping_Line_Graph.py +++ b/DemoPrograms/Demo_Ping_Line_Graph.py @@ -642,7 +642,7 @@ while True: time.sleep(.2) event, values = window.read(timeout=0) - if event == 'Quit' or event is None: + if event == 'Quit' or event == sg.WIN_CLOSED: break if g_response_time is None or prev_response_time == g_response_time: diff --git a/DemoPrograms/Demo_Pong.py b/DemoPrograms/Demo_Pong.py index a0f55e7b..bbf61145 100644 --- a/DemoPrograms/Demo_Pong.py +++ b/DemoPrograms/Demo_Pong.py @@ -156,7 +156,7 @@ def pong(): # ------------- Read the form, get keypresses ------------- event, values = window.read(timeout=0) # ------------- If quit ------------- - if event is None or event == 'Quit': + if event == sg.WIN_CLOSED or event == 'Quit': break # ------------- Keypresses ------------- if event is not None: diff --git a/DemoPrograms/Demo_Pong_Multiple_Platforms.py b/DemoPrograms/Demo_Pong_Multiple_Platforms.py index de9a6332..1be3ec7a 100644 --- a/DemoPrograms/Demo_Pong_Multiple_Platforms.py +++ b/DemoPrograms/Demo_Pong_Multiple_Platforms.py @@ -167,7 +167,7 @@ def pong(): event, values = window.read( timeout=sleep_time) # type: str, str - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event.startswith('Up') or event.endswith('Up'): bat_2.up(5) diff --git a/DemoPrograms/Demo_Progress_Meters.py b/DemoPrograms/Demo_Progress_Meters.py index 7ec5579d..9722b51f 100644 --- a/DemoPrograms/Demo_Progress_Meters.py +++ b/DemoPrograms/Demo_Progress_Meters.py @@ -2,6 +2,8 @@ import PySimpleGUI as sg from time import sleep +from docutils.nodes import title + sg.theme('Dark Blue 3') """ @@ -36,6 +38,8 @@ def demo_one_line_progress_meter(): 'MY MESSAGE1', 'MY MESSAGE 2', orientation='h', + no_titlebar=True, + grab_anywhere=True, bar_color=('white', 'red')): print('Hit the break') break @@ -68,7 +72,7 @@ def demo_one_line_progress_meter(): while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break if event == 'Show': max_outer = int(values['CountOuter']) @@ -203,12 +207,12 @@ def demo_iterable_progress_bar(): # first form takes an iterable and a key and will return a value from your iterable # and bump the progress meter at the same time - for value in progress_bar('bar1', my_list, ): + for value in progress_bar('bar1', my_list, title='First bar Test'): # do something useful with value, a value from your list. print(value) # Since the progress_bar is an iterator, you can use it within a list comprehension - my_list = [x for x in progress_bar('bar1', my_list)] + my_list = [x for x in progress_bar('bar1', my_list, title='Second bar Test')] demo_iterable_progress_bar() diff --git a/DemoPrograms/Demo_PyGame_Integration.py b/DemoPrograms/Demo_PyGame_Integration.py index e9f6c5ba..7b689940 100644 --- a/DemoPrograms/Demo_PyGame_Integration.py +++ b/DemoPrograms/Demo_PyGame_Integration.py @@ -34,7 +34,7 @@ pygame.display.update() while True: event, values = window.read(timeout=10) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Draw': pygame.draw.circle(screen, (0, 0, 0), (250, 250), 125) diff --git a/DemoPrograms/Demo_PyGame_Snake_Game.py b/DemoPrograms/Demo_PyGame_Snake_Game.py index 227518f7..80b723ab 100644 --- a/DemoPrograms/Demo_PyGame_Snake_Game.py +++ b/DemoPrograms/Demo_PyGame_Snake_Game.py @@ -89,7 +89,7 @@ clock = pygame.time.Clock() while True: event, values = window.read(timeout=10) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break pygame.display.update() diff --git a/DemoPrograms/Demo_Reddit_Search.py b/DemoPrograms/Demo_Reddit_Search.py index 0257e6cd..e8b73378 100644 --- a/DemoPrograms/Demo_Reddit_Search.py +++ b/DemoPrograms/Demo_Reddit_Search.py @@ -54,7 +54,7 @@ reddit = praw.Reddit(**reddit_praw_parameters) while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break subs_to_read = values['-SUBS-'] search_string = values['-SEARCH STRING-'] @@ -94,14 +94,14 @@ while True: # Event Loop non_blocking=True) window.refresh() event, values = window.read(timeout=0) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): window['-OUT SUB-'].update('*** Aborted ***') break else: window['-OUT SUB-'].update('*** Done! ***') - if event is None: + if event == sg.WIN_CLOSED: break window.close() diff --git a/DemoPrograms/Demo_Save_Window_As_Image.py b/DemoPrograms/Demo_Save_Window_As_Image.py index d42df1f9..38c31f30 100644 --- a/DemoPrograms/Demo_Save_Window_As_Image.py +++ b/DemoPrograms/Demo_Save_Window_As_Image.py @@ -37,7 +37,7 @@ def main(): while True: event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # exit elif event == 'Save': filename = sg.popup_get_file('Choose file (PNG, JPG, GIF) to save to', save_as=True) diff --git a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py index 43d5a2ed..352fddbf 100644 --- a/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py +++ b/DemoPrograms/Demo_Script_Launcher_ANSI_Color_Output.py @@ -94,7 +94,7 @@ def main(): while True: # Event Loop event, values = window.read() # print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Run': runCommand(cmd=values['-IN-'], window=window) diff --git a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py index 8b060daf..cd6d547c 100644 --- a/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py +++ b/DemoPrograms/Demo_Script_Launcher_Realtime_Output.py @@ -21,7 +21,7 @@ def main(): while True: # Event Loop event, values = window.read() # print(event, values) - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'Run': runCommand(cmd=values['-IN-'], window=window) diff --git a/DemoPrograms/Demo_Settings_Save_Load.py b/DemoPrograms/Demo_Settings_Save_Load.py index f3923f93..c67fa72b 100644 --- a/DemoPrograms/Demo_Settings_Save_Load.py +++ b/DemoPrograms/Demo_Settings_Save_Load.py @@ -71,8 +71,7 @@ def create_settings_window(settings): def create_main_window(settings): sg.theme(settings['theme']) - layout = [ - [sg.Menu([['File', ['Open']], ['Edit', ['Settings'], ],['Help', 'About...'],])], + layout = [[sg.Menu([['&File', []], ['&Edit', ['&Settings'], ],['&Help', '&About...'],])], [sg.T('This is my main application')], [sg.T('Add your primary window stuff in here')], [sg.B('Ok'), sg.B('Exit'), sg.B('Change Settings')]] @@ -89,7 +88,7 @@ def main(): event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break if event in ('Change Settings', 'Settings'): event, values = create_settings_window(settings).read(close=True) @@ -98,4 +97,6 @@ def main(): window = None save_settings(SETTINGS_FILE, settings, values) window.close() + + main() \ No newline at end of file diff --git a/DemoPrograms/Demo_Sort_Visualizer.py b/DemoPrograms/Demo_Sort_Visualizer.py index cca30459..ff1f6955 100644 --- a/DemoPrograms/Demo_Sort_Visualizer.py +++ b/DemoPrograms/Demo_Sort_Visualizer.py @@ -50,7 +50,7 @@ def main(): timeout = 10 # start with 10ms delays between draws while True: # ----- The event loop ----- event, values = window.read(timeout=timeout) - if event is None: + if event == sg.WIN_CLOSED: break try: partially_sorted_list = bsort.__next__() diff --git a/DemoPrograms/Demo_Spinner_Compound_Element.py b/DemoPrograms/Demo_Spinner_Compound_Element.py index f8059fee..1669aa32 100644 --- a/DemoPrograms/Demo_Spinner_Compound_Element.py +++ b/DemoPrograms/Demo_Spinner_Compound_Element.py @@ -22,7 +22,7 @@ window = sg.Window('Spinner simulation', layout, use_default_focus=False) while True: event, values = window.read() - if event == 'Ok' or event is None: # be nice to your user, always have an exit from your form + if event == 'Ok' or event == sg.WIN_CLOSED: # be nice to your user, always have an exit from your form break counter = int(values['-SPIN-']) # --- do spinner stuff --- # diff --git a/DemoPrograms/Demo_Stdout.py b/DemoPrograms/Demo_Stdout.py index 3f5847bb..811657dd 100644 --- a/DemoPrograms/Demo_Stdout.py +++ b/DemoPrograms/Demo_Stdout.py @@ -22,7 +22,7 @@ window = sg.Window('Reroute stdout', layout) while True: # Event Loop event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break print('You typed: ', values[0]) window.close() diff --git a/DemoPrograms/Demo_Sudoku.py b/DemoPrograms/Demo_Sudoku.py index eef6c939..7e6ba67b 100644 --- a/DemoPrograms/Demo_Sudoku.py +++ b/DemoPrograms/Demo_Sudoku.py @@ -82,6 +82,21 @@ def check_progress(window, solution): return solved +def create_and_show_puzzle(window): + # create and display a puzzle by updating the Input elements + rate = DEFAULT_MASK_RATE + if window['-RATE-'].get(): + try: + rate = float(window['-RATE-'].get()) + except: + pass + puzzle, solution = generate_sudoku(mask_rate=rate) + for r, row in enumerate(puzzle): + for c, col in enumerate(row): + window[r, c].update(puzzle[r][c] if puzzle[r][c] else '', background_color=sg.theme_input_background_color()) + return puzzle, solution + + def main(mask_rate=0.7): """" The Main GUI - It does it all. @@ -90,19 +105,7 @@ def main(mask_rate=0.7): addressing of the individual squares is via a key that's a tuple (0,0) to (8,8) """ - def create_and_show_puzzle(): - # create and display a puzzle by updating the Input elements - rate = mask_rate - if window['-RATE-'].get(): - try: - rate = float(window['-RATE-'].get()) - except: - pass - puzzle, solution = generate_sudoku(mask_rate=rate) - for r, row in enumerate(puzzle): - for c, col in enumerate(row): - window[r, c].update(puzzle[r][c] if puzzle[r][c] else '', background_color=sg.theme_input_background_color()) - return puzzle, solution + # It's 1 line of code to make a Sudoku board. If you don't like it, then replace it. @@ -111,16 +114,16 @@ def main(mask_rate=0.7): # Get an input element for a position using: window[row, col] # To get a better understanding, take it apart. Spread it out. You'll learn in the process. window = sg.Window('Sudoku', - [[sg.Frame('', [[sg.I(random.randint(1,9), justification='r', size=(3,1), key=(fr*3+r,fc*3+c)) for c in range(3)] for r in range(3)]) for fc in range(3)] for fr in range(3)] + + [[sg.Frame('', [[sg.I(random.randint(1,9), justification='r', size=(3,1),enable_events=True, key=(fr*3+r,fc*3+c)) for c in range(3)] for r in range(3)]) for fc in range(3)] for fr in range(3)] + [[sg.B('Solve'), sg.B('Check'), sg.B('Hint'), sg.B('New Game'), sg.T('Mask rate (0-1)'), sg.In(str(mask_rate), size=(3,1),key='-RATE-')],], finalize=True) # create and display a puzzle by updating the Input elements - puzzle, solution = create_and_show_puzzle() - + puzzle, solution = create_and_show_puzzle(window) + check_showing = False while True: # The Event Loop event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break if event == 'Solve': @@ -128,6 +131,7 @@ def main(mask_rate=0.7): for c, col in enumerate(row): window[r, c].update(solution[r][c], background_color=sg.theme_input_background_color()) elif event == 'Check': + check_showing = True solved = check_progress(window, solution) if solved: sg.popup('Solved! You have solved the puzzle correctly.') @@ -138,11 +142,15 @@ def main(mask_rate=0.7): except: pass # Likely because an input element didn't have focus elif event == 'New Game': - puzzle, solution = create_and_show_puzzle() - + puzzle, solution = create_and_show_puzzle(window) + elif check_showing: # an input was changed, so clear any background colors from prior hints + check_showing = False + for r, row in enumerate(solution): + for c, col in enumerate(row): + window[r, c].update(background_color=sg.theme_input_background_color()) window.close() if __name__ == "__main__": - mask_rate = 0.7 # % Of cells to hide - main(mask_rate) + DEFAULT_MASK_RATE = 0.7 # % Of cells to hide + main(DEFAULT_MASK_RATE) diff --git a/DemoPrograms/Demo_Super_Simple_Form.py b/DemoPrograms/Demo_Super_Simple_Form.py index 34c493ea..77010ee6 100644 --- a/DemoPrograms/Demo_Super_Simple_Form.py +++ b/DemoPrograms/Demo_Super_Simple_Form.py @@ -1,5 +1,10 @@ import PySimpleGUI as sg +event, values = sg.Window('Window Title', [[sg.Text('Enter Something')], [sg.Input(key='-IN-'),],[sg.Button('OK'), sg.Button('Cancel')]]).read(close=True) + +sg.popup(event, values) + + # Basic Example layout = [[sg.Text('Please enter your Name, Address, Phone')], @@ -9,7 +14,7 @@ layout = [[sg.Text('Please enter your Name, Address, Phone')], [sg.Button('Submit'), sg.Button('Cancel')]] window = sg.Window('Simple Data Entry Window', layout) -event, values = window.read() +event, values = window.read(close=True) print(event, values['-NAME-'], values['-ADDRESS-'], values['-PHONE-']) - +sg.popup('test') window.close() diff --git a/DemoPrograms/Demo_Table_Element.py b/DemoPrograms/Demo_Table_Element.py index c5daf6db..54b8add2 100644 --- a/DemoPrograms/Demo_Table_Element.py +++ b/DemoPrograms/Demo_Table_Element.py @@ -24,7 +24,7 @@ def make_table(num_rows, num_cols): # ------ Make the Table Data ------ data = make_table(num_rows=15, num_cols=6) -headings = [str(data[0][x]) for x in range(len(data[0]))] +headings = [str(data[0][x])+' ..' for x in range(len(data[0]))] # ------ Window Layout ------ layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, @@ -33,8 +33,9 @@ layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, display_row_numbers=True, justification='right', num_rows=20, - # alternating_row_color='lightyellow', + alternating_row_color='lightyellow', key='-TABLE-', + row_height=35, tooltip='This is a table')], [sg.Button('Read'), sg.Button('Double'), sg.Button('Change Colors')], [sg.Text('Read = read which rows are selected')], @@ -42,13 +43,15 @@ layout = [[sg.Table(values=data[1:][:], headings=headings, max_col_width=25, [sg.Text('Change Colors = Changes the colors of rows 8 and 9')]] # ------ Create Window ------ -window = sg.Window('The Table Element', layout) +window = sg.Window('The Table Element', layout, + # font='Helvetica 25', + ) # ------ Event Loop ------ while True: event, values = window.read() print(event, values) - if event is None: + if event == sg.WIN_CLOSED: break if event == 'Double': for i in range(len(data)): diff --git a/DemoPrograms/Demo_Table_Simulation.py b/DemoPrograms/Demo_Table_Simulation.py index 3c0cadf4..f631e544 100644 --- a/DemoPrograms/Demo_Table_Simulation.py +++ b/DemoPrograms/Demo_Table_Simulation.py @@ -33,7 +33,7 @@ def TableSimulation(): while True: event, values = window.read() # --- Process buttons --- # - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break elif event == 'About...': sg.popup('Demo of table capabilities') diff --git a/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py b/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py index 014ac4d5..0e7aaba4 100644 --- a/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py +++ b/DemoPrograms/Demo_Table_Simulation_Arrow_Keys.py @@ -28,7 +28,7 @@ window = sg.Window('A Table Simulation', layout, default_element_size=(12, 1), e current_cell = (0, 0) while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): # If user closed the window + if event in (sg.WIN_CLOSED, 'Exit'): # If user closed the window break elem = window.find_element_with_focus() current_cell = elem.Key if elem and type(elem.Key) is tuple else (0, 0) diff --git a/DemoPrograms/Demo_Tabs.py b/DemoPrograms/Demo_Tabs.py index c4cb2158..87b8b96a 100644 --- a/DemoPrograms/Demo_Tabs.py +++ b/DemoPrograms/Demo_Tabs.py @@ -1,6 +1,7 @@ #!/usr/bin/env python import sys import PySimpleGUI as sg +# import PySimpleGUIWeb as sg # Usage of Tabs in PSG # @@ -34,13 +35,13 @@ layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslat selected_title_color='green', tab_location='right'), sg.TabGroup([[sg.Tab('Tab 4', tab4_layout, background_color='darkseagreen', key='-mykey-'), sg.Tab('Tab 5', tab5_layout)]], key='-group1-', tab_location='top', selected_title_color='purple')], - [sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='-mykey-'), - sg.Tab('Tab 2', tab2_layout, background_color='tan1'), - sg.Tab('Tab 3', tab3_layout)]], - key='-group3-', title_color='red', - selected_title_color='green', tab_location='left'), - sg.TabGroup([[sg.Tab('Tab 4', tab4_layout, background_color='darkseagreen', key='-mykey-'), - sg.Tab('Tab 5', tab5_layout)]], key='-group4-', tab_location='bottom', selected_title_color='purple')], + # [sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='-mykey-'), + # sg.Tab('Tab 2', tab2_layout, background_color='tan1'), + # sg.Tab('Tab 3', tab3_layout)]], + # key='-group3-', title_color='red', + # selected_title_color='green', tab_location='left'), + # sg.TabGroup([[sg.Tab('Tab 4', tab4_layout, background_color='darkseagreen', key='-mykey-'), + # sg.Tab('Tab 5', tab5_layout)]], key='-group4-', tab_location='bottom', selected_title_color='purple')], [sg.Button('Read')]] window = sg.Window('My window with tabs', layout, @@ -51,6 +52,6 @@ while True: event, values = window.read() sg.popup_non_blocking(event, values) print(event, values) - if event is None: # always, always give a way out! + if event == sg.WIN_CLOSED: # always, always give a way out! break window.close() diff --git a/DemoPrograms/Demo_Tabs_Nested.py b/DemoPrograms/Demo_Tabs_Nested.py index 9e82fbcb..f8e00eb9 100644 --- a/DemoPrograms/Demo_Tabs_Nested.py +++ b/DemoPrograms/Demo_Tabs_Nested.py @@ -33,7 +33,7 @@ print('Are there enough tabs for you?') while True: event, values = window.read() print(event, values) - if event is None: # always, always give a way out! + if event == sg.WIN_CLOSED: # always, always give a way out! break window.close() \ No newline at end of file diff --git a/DemoPrograms/Demo_Tabs_Simple.py b/DemoPrograms/Demo_Tabs_Simple.py index 930b8cf0..ac7a843a 100644 --- a/DemoPrograms/Demo_Tabs_Simple.py +++ b/DemoPrograms/Demo_Tabs_Simple.py @@ -32,7 +32,7 @@ tab_keys = ('-TAB1-','-TAB2-','-TAB3-', '-TAB4-') # map from an input va while True: event, values = window.read() # type: str, dict print(event, values) - if event is None: + if event == sg.WIN_CLOSED: break # handle button clicks if event == 'Invisible': diff --git a/DemoPrograms/Demo_Template.py b/DemoPrograms/Demo_Template.py index 6af2b7b3..ffa551e1 100644 --- a/DemoPrograms/Demo_Template.py +++ b/DemoPrograms/Demo_Template.py @@ -27,7 +27,7 @@ window = sg.Window('My Window Title', layout) while True: # Event Loop event, values = window.read() - if event is None: # if window closed with X + if event == sg.WIN_CLOSED: # if window closed with X break print(event, values) diff --git a/DemoPrograms/Demo_Theme_Browser.py b/DemoPrograms/Demo_Theme_Browser.py index 28c2b29e..f9336b37 100644 --- a/DemoPrograms/Demo_Theme_Browser.py +++ b/DemoPrograms/Demo_Theme_Browser.py @@ -19,7 +19,7 @@ window = sg.Window('Look and Feel Browser', layout) while True: # Event Loop event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break sg.theme(values['-LIST-'][0]) sg.popup_get_text('This is {}'.format(values['-LIST-'][0]), default_text=values['-LIST-'][0]) diff --git a/DemoPrograms/Demo_Timer.py b/DemoPrograms/Demo_Timer.py index b5be0efe..9f10eab5 100644 --- a/DemoPrograms/Demo_Timer.py +++ b/DemoPrograms/Demo_Timer.py @@ -19,7 +19,7 @@ def Timer(): while True: # This is the code that reads and updates your window - button, values = window.read(timeout=0) + button, values = window.read(timeout=10) window['text'].update('{:02d}:{:02d}.{:02d}'.format( (i // 100) // 60, (i // 100) % 60, i % 100)) diff --git a/DemoPrograms/Demo_Touch_Keyboard.py b/DemoPrograms/Demo_Touch_Keyboard.py index 48abb711..1426e66b 100644 --- a/DemoPrograms/Demo_Touch_Keyboard.py +++ b/DemoPrograms/Demo_Touch_Keyboard.py @@ -88,7 +88,7 @@ class GUI(): self.keyboard.update(self.focus) if event == 'keyboard': self.keyboard.togglevis() - elif event == 'close' or event is None: + elif event == 'close' or event == sg.WIN_CLOSED: break self.keyboard.close() self.mainWindow.Close() diff --git a/DemoPrograms/Demo_Tree_Element.py b/DemoPrograms/Demo_Tree_Element.py index 554477ec..4875d7d2 100644 --- a/DemoPrograms/Demo_Tree_Element.py +++ b/DemoPrograms/Demo_Tree_Element.py @@ -44,7 +44,7 @@ layout = [[sg.Text('File and folder browser Test')], headings=['Size', ], auto_size_columns=True, num_rows=20, - col0_width=30, + col0_width=40, key='-TREE-', show_expanded=False, enable_events=True), @@ -56,7 +56,7 @@ window = sg.Window('Tree Element Test', layout) while True: # Event Loop event, values = window.read() - if event in (None, 'Cancel'): + if event in (sg.WIN_CLOSED, 'Cancel'): break print(event, values) window.close() diff --git a/DemoPrograms/Demo_Turtle.py b/DemoPrograms/Demo_Turtle.py index 3c778061..d982a8c0 100644 --- a/DemoPrograms/Demo_Turtle.py +++ b/DemoPrograms/Demo_Turtle.py @@ -28,7 +28,7 @@ a_turtle.pendown() while True: # Event Loop event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break if event == 'F': diff --git a/DemoPrograms/Demo_Unicode_Characters.py b/DemoPrograms/Demo_Unicode_Characters.py index 7b54fa7a..3a3af78a 100644 --- a/DemoPrograms/Demo_Unicode_Characters.py +++ b/DemoPrograms/Demo_Unicode_Characters.py @@ -43,7 +43,7 @@ multiline_font_size = 18 while True: event, values = window.read(timeout=200) print(f'{event} - {values}') if event != sg.TIMEOUT_KEY else None - if event in (None, 'Exit'): # always, always give a way out! + if event in (sg.WIN_CLOSED, 'Exit'): # always, always give a way out! break elif event == RIGHT: window['-OUT2-'](text_color='blue') diff --git a/DemoPrograms/Demo_Uno_Card_Game.py b/DemoPrograms/Demo_Uno_Card_Game.py index 2b2ed974..874c3b19 100644 --- a/DemoPrograms/Demo_Uno_Card_Game.py +++ b/DemoPrograms/Demo_Uno_Card_Game.py @@ -1423,7 +1423,7 @@ def mainMenu(): while True: # Event Loop event, values = window.read() # print(event, values) - if event is None or event == 'Exit': + if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Begin': window.Hide() @@ -2945,7 +2945,7 @@ def mainMenu(): while True: # Event Loop event, values = window.read() # print(event, values) - if event is None or event == 'Exit': + if event == sg.WIN_CLOSED or event == 'Exit': break if event == 'Begin': window.Hide() diff --git a/DemoPrograms/Demo_Window_Disappear.py b/DemoPrograms/Demo_Window_Disappear.py index 32ac9b82..cdf48aec 100644 --- a/DemoPrograms/Demo_Window_Disappear.py +++ b/DemoPrograms/Demo_Window_Disappear.py @@ -11,7 +11,7 @@ window = sg.Window('My window', layout) while True: event, values = window.read() - if event is None: + if event == sg.WIN_CLOSED: break if event == 'Disappear': window.disappear() diff --git a/DemoPrograms/Demo_psutil_Kill_Processes.py b/DemoPrograms/Demo_psutil_Kill_Processes.py index efc5fb10..521d0f49 100644 --- a/DemoPrograms/Demo_psutil_Kill_Processes.py +++ b/DemoPrograms/Demo_psutil_Kill_Processes.py @@ -71,7 +71,7 @@ def main(): while True: # --------- Read and update window -------- event, values = window.read() - if event in (None, 'Exit'): + if event in (sg.WIN_CLOSED, 'Exit'): break # skip mouse, control key and shift key events entirely @@ -97,7 +97,7 @@ def main(): try: kill_proc_tree(pid=pid) except: - sg.popup_no_wait('Error killing process', auto_close_duration=1, auto_close=True) + sg.popup_no_wait('Error killing process', auto_close_duration=2, auto_close=True, keep_on_top=True) elif event == 'Sort by % CPU': psutil.cpu_percent(interval=.1) procs = psutil.process_iter() @@ -114,7 +114,7 @@ def main(): if values['-filter-'] in line.lower(): new_output.append(line) window['-processes-'].update(new_output) - window.close() + window.close() if __name__ == "__main__":