Renamed demo files, new demo of tabbed forms
Changed filenames to remove spaces so will be easier to work with on Linux.
This commit is contained in:
		
							parent
							
								
									13d99dcd75
								
							
						
					
					
						commit
						2109bdbc97
					
				
					 10 changed files with 2427 additions and 0 deletions
				
			
		
							
								
								
									
										1729
									
								
								Demo_Color.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1729
									
								
								Demo_Color.py
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										33
									
								
								Demo_Compare_Files.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								Demo_Compare_Files.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,33 @@ | |||
| import PySimpleGUI as sg | ||||
| 
 | ||||
| def GetFilesToCompare(): | ||||
|     with sg.FlexForm('File Compare', auto_size_text=True) as form: | ||||
|         form_rows = [[sg.Text('Enter 2 files to comare')], | ||||
|                      [sg.Text('File 1', size=(15, 1)), sg.InputText(), sg.FileBrowse()], | ||||
|                      [sg.Text('File 2', size=(15, 1)), sg.InputText(), sg.FileBrowse()], | ||||
|                      [sg.Submit(), sg.Cancel()]] | ||||
|         rc = form.LayoutAndShow(form_rows) | ||||
|     return rc | ||||
| 
 | ||||
| def main(): | ||||
|     button, (f1, f2) = GetFilesToCompare() | ||||
|     if any((button != 'Submit', f1 =='', f2 == '')): | ||||
|         sg.MsgBoxError('Operation cancelled') | ||||
|         exit(69) | ||||
| 
 | ||||
|     with open(f1, 'rb') as file1: | ||||
|         with open(f2, 'rb') as file2: | ||||
|             a = file1.read() | ||||
|             b = file2.read() | ||||
| 
 | ||||
|         for i, x in enumerate(a): | ||||
|             if x != b[i]: | ||||
|                 sg.MsgBox('Compare results for files', f1, f2, '**** Mismatch at offset {} ****'.format(i)) | ||||
|                 break | ||||
|         else: | ||||
|             if len(a) == len(b): | ||||
|                 sg.MsgBox('**** The files are IDENTICAL ****') | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
							
								
								
									
										123
									
								
								Demo_DisplayHash1and256.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								Demo_DisplayHash1and256.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,123 @@ | |||
| #!Python 3 | ||||
| import hashlib | ||||
| import PySimpleGUI as SG | ||||
| 
 | ||||
|  ######################################################################### | ||||
| # DisplayHash                                                            # | ||||
| #   A PySimpleGUI demo app that displays SHA1 hash for user browsed file # | ||||
| #   Useful and a recipe for GUI success                                  # | ||||
|  ######################################################################### | ||||
| 
 | ||||
| # ====____====____==== FUNCTION compute_hash_for_file(filename) ====____====____==== # | ||||
| # Reads a file, computes the Hash                                                    # | ||||
| # ---------------------------------------------------------------------------------- # | ||||
| def compute_sha1_hash_for_file(filename): | ||||
|     try: | ||||
|         x = open(filename, "rb").read() | ||||
|     except: | ||||
|         return 0 | ||||
| 
 | ||||
|     m = hashlib.sha1() | ||||
|     m.update(x) | ||||
|     f_sha = m.hexdigest() | ||||
| 
 | ||||
|     return f_sha | ||||
| 
 | ||||
| 
 | ||||
| # ====____====____==== FUNCTION compute_hash_for_file(filename) ====____====____==== # | ||||
| # Reads a file, computes the Hash                                                    # | ||||
| # ---------------------------------------------------------------------------------- # | ||||
| def compute_sha256_hash_for_file(filename): | ||||
|     try: | ||||
|         f = open(filename, "rb") | ||||
|         x = f.read() | ||||
|     except: | ||||
|         return 0 | ||||
| 
 | ||||
|     m = hashlib.sha256() | ||||
|     m.update(x) | ||||
|     f_sha = m.hexdigest() | ||||
| 
 | ||||
|     return f_sha | ||||
| 
 | ||||
| 
 | ||||
|  # ====____====____==== Uses A GooeyGUI GUI ====____====____== # | ||||
| #  Get the filename, display the hash, dirt simple all around   # | ||||
|  # ----------------------------------------------------------- # | ||||
| 
 | ||||
| # ---------------------------------------------------------------------- # | ||||
| #   Compute and display SHA1 hash                                        # | ||||
| #   Builds and displays the form using the most basic building blocks    # | ||||
| # ---------------------------------------------------------------------- # | ||||
| def HashManuallyBuiltGUI(): | ||||
|     # -------  Form design ------- # | ||||
|     with SG.FlexForm('SHA-1 & 256 Hash', auto_size_text=True) as form: | ||||
|         form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')], | ||||
|                      [SG.InputText(), SG.FileBrowse()], | ||||
|                      [SG.Submit(), SG.Cancel()]] | ||||
|         (button, (source_filename, )) = form.LayoutAndShow(form_rows) | ||||
| 
 | ||||
|     if button == 'Submit': | ||||
|         if source_filename != '': | ||||
|             hash_sha1 = compute_sha1_hash_for_file(source_filename).upper() | ||||
|             hash_sha256 = compute_sha256_hash_for_file(source_filename).upper() | ||||
|             SG.MsgBox( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75) | ||||
|         else: SG.MsgBoxError('Display A Hash in PySimpleGUI', 'Illegal filename') | ||||
|     else: | ||||
|         SG.MsgBoxError('Display A Hash in PySimpleGUI', '* Cancelled *') | ||||
| 
 | ||||
| def HashManuallyBuiltGUINonContext(): | ||||
|     # -------  Form design ------- # | ||||
|     form = SG.FlexForm('SHA-1 & 256 Hash', auto_size_text=True) | ||||
|     form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')], | ||||
|                      [SG.InputText(), SG.FileBrowse()], | ||||
|                      [SG.Submit(), SG.Cancel()]] | ||||
|     button, (source_filename, ) = form.LayoutAndShow(form_rows) | ||||
| 
 | ||||
|     if button == 'Submit': | ||||
|         if source_filename != '': | ||||
|             hash_sha1 = compute_sha1_hash_for_file(source_filename).upper() | ||||
|             hash_sha256 = compute_sha256_hash_for_file(source_filename).upper() | ||||
|             SG.MsgBox( 'Display A Hash in PySimpleGUI', 'The SHA-1 Hash for the file\n', source_filename, hash_sha1, 'SHA-256 is', hash_sha256, line_width=75) | ||||
|         else: SG.MsgBoxError('Display A Hash in PySimpleGUI', 'Illegal filename') | ||||
|     else: | ||||
|         SG.MsgBoxError('Display A Hash in PySimpleGUI', '* Cancelled *') | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| # ---------------------------------------------------------------------- # | ||||
| #   Compute and display SHA1 hash                                        # | ||||
| #   This one cheats and uses the higher-level Get A File pre-made func   # | ||||
| #   Hey, it's a really common operation so why not?                      # | ||||
| # ---------------------------------------------------------------------- # | ||||
| def HashMostCompactGUI(): | ||||
|     # -------  INPUT GUI portion  ------- # | ||||
| 
 | ||||
|     rc, source_filename = SG.GetFileBox('Display A Hash Using PySimpleGUI', | ||||
|                                   'Display a Hash code for file of your choice') | ||||
| 
 | ||||
|     # -------  OUTPUT GUI results portion  ------- # | ||||
|     if rc == True: | ||||
|         hash = compute_sha1_hash_for_file(source_filename) | ||||
|         SG.MsgBox('Display Hash - Compact GUI', 'The SHA-1 Hash for the file\n', source_filename, hash) | ||||
|     else: | ||||
|         SG.MsgBox('Display Hash - Compact GUI', '* Cancelled *') | ||||
| 
 | ||||
| 
 | ||||
| # ---------------------------------------------------------------------- # | ||||
| #  Our main calls two GUIs that act identically but use different calls  # | ||||
| # ---------------------------------------------------------------------- # | ||||
| def main(): | ||||
|     HashManuallyBuiltGUINonContext() | ||||
|     HashMostCompactGUI() | ||||
| 
 | ||||
| 
 | ||||
| # ====____====____==== Pseudo-MAIN program ====____====____==== # | ||||
| # This is our main-alike piece of code                          # | ||||
| #   + Starts up the GUI                                         # | ||||
| #   + Gets values from GUI                                      # | ||||
| #   + Runs DeDupe_folder based on GUI inputs                    # | ||||
| # ------------------------------------------------------------- # | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
							
								
								
									
										57
									
								
								Demo_DuplicateFileFinder.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								Demo_DuplicateFileFinder.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,57 @@ | |||
| import hashlib | ||||
| import os | ||||
| import PySimpleGUI as sg | ||||
| 
 | ||||
| 
 | ||||
| # ====____====____==== FUNCTION DeDuplicate_folder(path) ====____====____==== # | ||||
| # Function to de-duplicate the folder passed in                               # | ||||
| # --------------------------------------------------------------------------- # | ||||
| def FindDuplicatesFilesInFolder(path): | ||||
|     shatab = [] | ||||
|     total = 0 | ||||
|     small_count, dup_count, error_count = 0,0,0 | ||||
|     pngdir = path | ||||
|     if not os.path.exists(path): | ||||
|         sg.MsgBox('Duplicate Finder', '** Folder doesn\'t exist***', path) | ||||
|         return | ||||
|     pngfiles = os.listdir(pngdir) | ||||
|     total_files = len(pngfiles) | ||||
|     for idx, f in enumerate(pngfiles): | ||||
|         if not sg.EasyProgressMeter('Counting Duplicates', idx + 1, total_files, 'Counting Duplicate Files'): | ||||
|             break | ||||
|         total += 1 | ||||
|         fname = os.path.join(pngdir, f) | ||||
|         if os.path.isdir(fname): | ||||
|             continue | ||||
|         x = open(fname, "rb").read() | ||||
| 
 | ||||
|         m = hashlib.sha256() | ||||
|         m.update(x) | ||||
|         f_sha = m.digest() | ||||
|         if f_sha in shatab: | ||||
|             # uncomment next line to remove duplicate files | ||||
|             # os.remove(fname) | ||||
|             dup_count += 1 | ||||
|             # sg.Print(f'Duplicate file - {f}')    # cannot current use sg.Print with Progress Meter | ||||
|             continue | ||||
|         shatab.append(f_sha) | ||||
| 
 | ||||
|     msg = f'{total} Files processed\n'\ | ||||
|           f'{dup_count} Duplicates found\n' | ||||
|     sg.MsgBox('Duplicate Finder Ended', msg) | ||||
| 
 | ||||
| # ====____====____==== Pseudo-MAIN program ====____====____==== # | ||||
| # This is our main-alike piece of code                          # | ||||
| #   + Starts up the GUI                                         # | ||||
| #   + Gets values from GUI                                      # | ||||
| #   + Runs DeDupe_folder based on GUI inputs                    # | ||||
| # ------------------------------------------------------------- # | ||||
| if __name__ == '__main__': | ||||
| 
 | ||||
|     source_folder = None | ||||
|     rc, source_folder = sg.GetPathBox('Duplicate Finder - Count number of duplicate files', 'Enter path to folder you wish to find duplicates in') | ||||
|     if rc is True and source_folder is not None: | ||||
|         FindDuplicatesFilesInFolder(source_folder) | ||||
|     else: | ||||
|         sg.MsgBoxCancel('Cancelling', '*** Cancelling ***') | ||||
|     exit(0) | ||||
							
								
								
									
										50
									
								
								Demo_GoodColors.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								Demo_GoodColors.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,50 @@ | |||
| import PySimpleGUI as gg | ||||
| import time | ||||
| 
 | ||||
| def main(): | ||||
|     # -------  Make a new FlexForm  ------- # | ||||
|     form = gg.FlexForm('GoodColors', auto_size_text=True, default_element_size=(30,2)) | ||||
|     form.AddRow(gg.Text('Having trouble picking good colors? Try one of the colors defined by PySimpleGUI')) | ||||
|     form.AddRow(gg.Text('Here come the good colors as defined by PySimpleGUI')) | ||||
| 
 | ||||
|     #===== Show some nice BLUE colors with yellow text ===== ===== ===== ===== ===== =====  =====# | ||||
|     text_color = gg.YELLOWS[0] | ||||
|     buttons = (gg.SimpleButton(f'BLUES[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.BLUES)) | ||||
|     form.AddRow(gg.T('Button Colors Using PySimpleGUI.BLUES')) | ||||
|     form.AddRow(*buttons) | ||||
|     form.AddRow(gg.Text('_' * 100, size=(65, 1))) | ||||
| 
 | ||||
|     #===== Show some nice PURPLE colors with yellow text ===== ===== ===== ===== ===== =====  =====# | ||||
|     buttons = (gg.SimpleButton(f'PURPLES[{j}]\n{c}', button_color=(text_color, c), size=(10,2)) for j, c in enumerate(gg.PURPLES)) | ||||
|     form.AddRow(gg.T('Button Colors Using PySimpleGUI.PURPLES')) | ||||
|     form.AddRow(*buttons) | ||||
|     form.AddRow(gg.Text('_' * 100, size=(65, 1))) | ||||
| 
 | ||||
|     #===== Show some nice GREEN colors with yellow text ===== ===== ===== ===== ===== =====  =====# | ||||
|     buttons = (gg.SimpleButton(f'GREENS[{j}]\n{c}', button_color=(text_color, c),  size=(10,2)) for j, c in enumerate(gg.GREENS)) | ||||
|     form.AddRow(gg.T('Button Colors Using PySimpleGUI.GREENS')) | ||||
|     form.AddRow(*buttons) | ||||
|     form.AddRow(gg.Text('_' * 100, size=(65, 1))) | ||||
| 
 | ||||
|     #===== Show some nice TAN colors with yellow text ===== ===== ===== ===== ===== =====  =====# | ||||
|     text_color = gg.GREENS[0]        # let's use GREEN text on the tan | ||||
|     buttons = (gg.SimpleButton(f'TANS[{j}]\n{c}', button_color=(text_color, c),  size=(10,2)) for j, c in enumerate(gg.TANS)) | ||||
|     form.AddRow(gg.T('Button Colors Using PySimpleGUI.TANS')) | ||||
|     form.AddRow(*buttons) | ||||
|     form.AddRow(gg.Text('_' * 100, size=(65, 1))) | ||||
| 
 | ||||
|     #===== Show some nice YELLOWS colors with black text ===== ===== ===== ===== ===== =====  =====# | ||||
|     text_color = 'black'       # let's use black text on the tan | ||||
|     buttons = (gg.SimpleButton(f'YELLOWS[{j}]\n{c}', button_color=(text_color, c),  size=(10,2)) for j, c in enumerate(gg.YELLOWS)) | ||||
|     form.AddRow(gg.T('Button Colors Using PySimpleGUI.YELLOWS')) | ||||
|     form.AddRow(*buttons) | ||||
|     form.AddRow(gg.Text('_' * 100, size=(65, 1))) | ||||
| 
 | ||||
| 
 | ||||
|     #===== Add a click me button for fun and SHOW the form ===== ===== ===== ===== ===== =====  =====# | ||||
|     form.AddRow(gg.SimpleButton('Click ME!')) | ||||
|     (button, value) = form.Show()               # show it! | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
							
								
								
									
										55
									
								
								Demo_HowDoI.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								Demo_HowDoI.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | |||
| import PySimpleGUI as SG | ||||
| import subprocess | ||||
| import howdoi | ||||
| 
 | ||||
| # Test this command in a dos window if you are having trouble. | ||||
| HOW_DO_I_COMMAND =  'python -m howdoi.howdoi' | ||||
| 
 | ||||
| # if you want an icon on your taskbar for this gui, then change this line of code to point to the ICO file | ||||
| DEFAULT_ICON = 'E:\\TheRealMyDocs\\Icons\\QuestionMark.ico' | ||||
| 
 | ||||
| def HowDoI(): | ||||
|     ''' | ||||
|     Make and show a window (PySimpleGUI form) that takes user input and sends to the HowDoI web oracle | ||||
|     Excellent example of 2 GUI concepts | ||||
|         1. Output Element that will show text in a scrolled window | ||||
|         2. Non-Window-Closing Buttons - These buttons will cause the form to return with the form's values, but doesn't close the form | ||||
|     :return: never returns | ||||
|     ''' | ||||
|     # -------  Make a new FlexForm  ------- # | ||||
|     SG.SetOptions(border_width=1) | ||||
|     form = SG.FlexForm('How Do I ??', auto_size_text=True, default_element_size=(30, 2), icon=DEFAULT_ICON) | ||||
|     form.AddRow(SG.Text('Ask and your answer will appear here....', size=(40, 1))) | ||||
|     form.AddRow(SG.Output(size=(90, 20))) | ||||
|     form.AddRow(SG.Multiline(size=(85, 5), enter_submits=True), | ||||
|                 SG.ReadFormButton('SEND', button_color=(SG.YELLOWS[0], SG.BLUES[0])), | ||||
|                 SG.SimpleButton('EXIT', button_color=(SG.YELLOWS[0], SG.GREENS[0]))) | ||||
| 
 | ||||
|     # ---===--- Loop taking in user input and using it to query HowDoI --- # | ||||
|     while True: | ||||
|         (button, value) = form.Read() | ||||
|         if button == 'SEND': | ||||
|             QueryHowDoI(value[0][:-1])      # send string without carriage return on end | ||||
|         else: | ||||
|             break           # exit button clicked | ||||
| 
 | ||||
|     exit(69) | ||||
| 
 | ||||
| def QueryHowDoI(Query): | ||||
|     ''' | ||||
|     Kicks off a subprocess to send the 'Query' to HowDoI | ||||
|     Prints the result, which in this program will route to a gooeyGUI window | ||||
|     :param Query: text english question to ask the HowDoI web engine | ||||
|     :return: nothing | ||||
|     ''' | ||||
|     howdoi_command = HOW_DO_I_COMMAND | ||||
|     t = subprocess.Popen(howdoi_command + ' '+ Query, stdout=subprocess.PIPE) | ||||
|     (output, err) = t.communicate() | ||||
|     print('You asked: '+ Query) | ||||
|     print('_______________________________________') | ||||
|     print(output.decode("utf-8") ) | ||||
|     exit_code = t.wait() | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     HowDoI() | ||||
| 
 | ||||
							
								
								
									
										64
									
								
								Demo_Media_Player.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								Demo_Media_Player.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| import PySimpleGUI as sg | ||||
| 
 | ||||
| # | ||||
| # An Async Demonstration of a media player | ||||
| # Uses button images for a super snazzy look | ||||
| # See how it looks here: | ||||
| # https://user-images.githubusercontent.com/13696193/43159403-45c9726e-8f50-11e8-9da0-0d272e20c579.jpg | ||||
| # | ||||
| def MediaPlayerGUI(): | ||||
| 
 | ||||
|     # Images are located in a subfolder in the Demo Media Player.py folder | ||||
|     image_pause = './ButtonGraphics/Pause.png' | ||||
|     image_restart = './ButtonGraphics/Restart.png' | ||||
|     image_next = './ButtonGraphics/Next.png' | ||||
|     image_exit = './ButtonGraphics/Exit.png' | ||||
| 
 | ||||
|     # A text element that will be changed to display messages in the GUI | ||||
|     TextElem = sg.Text('', size=(15, 2), font=("Helvetica", 14)) | ||||
| 
 | ||||
|     # Open a form, note that context manager can't be used generally speaking for async forms | ||||
|     form = sg.FlexForm('Media File Player', auto_size_text=True, default_element_size=(20, 1), | ||||
|                        font=("Helvetica", 25)) | ||||
|     # define layout of the rows | ||||
|     layout= [[sg.Text('Media File Player',size=(17,1), font=("Helvetica", 25))], | ||||
|             [TextElem], | ||||
|              [sg.ReadFormButton('Restart Song', button_color=sg.TRANSPARENT_BUTTON, | ||||
|                                 image_filename=image_restart, image_size=(50, 50), image_subsample=2, border_width=0), | ||||
|                                 sg.Text(' ' * 2), | ||||
|               sg.ReadFormButton('Pause', button_color=sg.TRANSPARENT_BUTTON, | ||||
|                                 image_filename=image_pause, image_size=(50, 50), image_subsample=2, border_width=0), | ||||
|                                 sg.Text(' ' * 2), | ||||
|               sg.ReadFormButton('Next', button_color=sg.TRANSPARENT_BUTTON, | ||||
|                                 image_filename=image_next, image_size=(50, 50), image_subsample=2, border_width=0), | ||||
|                                 sg.Text(' ' * 2), | ||||
|               sg.Text(' ' * 2), sg.SimpleButton('Exit', button_color=sg.TRANSPARENT_BUTTON, | ||||
|                                                 image_filename=image_exit, image_size=(50, 50), image_subsample=2, border_width=0)], | ||||
|              [sg.Text('_'*30)], | ||||
|              [sg.Text(' '*30)], | ||||
|             [ | ||||
|              sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)), | ||||
|              sg.Text(' ' * 2), | ||||
|              sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)), | ||||
|              sg.Text(' ' * 8), | ||||
|              sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15))], | ||||
|              [sg.Text('Bass', font=("Helvetica", 15), size=(6, 1)), | ||||
|              sg.Text('Treble', font=("Helvetica", 15), size=(10, 1)), | ||||
|              sg.Text('Volume', font=("Helvetica", 15), size=(7, 1))] | ||||
| 
 | ||||
|              ] | ||||
| 
 | ||||
|     # Call the same LayoutAndRead but indicate the form is non-blocking | ||||
|     form.LayoutAndRead(layout, non_blocking=True) | ||||
|     # Our event loop | ||||
|     while(True): | ||||
|         # Read the form (this call will not block) | ||||
|         button, values = form.ReadNonBlocking() | ||||
|         if button == 'Exit': | ||||
|             break | ||||
|         # If a button was pressed, display it on the GUI by updating the text element | ||||
|         if button: | ||||
|             TextElem.Update(button) | ||||
| 
 | ||||
| MediaPlayerGUI() | ||||
| 
 | ||||
							
								
								
									
										59
									
								
								Demo_NonBlocking_Form.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								Demo_NonBlocking_Form.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,59 @@ | |||
| import PySimpleGUI as sg | ||||
| import time | ||||
| 
 | ||||
| def main(): | ||||
|     StatusOutputExample() | ||||
| 
 | ||||
| # form that doen't block | ||||
| def StatusOutputExample_context_manager(): | ||||
|     with sg.FlexForm('Running Timer', auto_size_text=True) as form: | ||||
|         output_element = sg.Text('', size=(8, 2), font=('Helvetica', 20)) | ||||
|         form_rows = [[sg.Text('Non-blocking GUI with updates')], | ||||
|                      [output_element], | ||||
|                      [sg.SimpleButton('Quit')]] | ||||
| 
 | ||||
|         form.LayoutAndRead(form_rows, non_blocking=True) | ||||
| 
 | ||||
|         for i in range(1, 1000): | ||||
|             output_element.Update('{:02d}:{:02d}.{:02d}'.format(*divmod(int(i/100), 60), i%100)) | ||||
|             button, values = form.ReadNonBlocking() | ||||
|             if values is None or button == 'Quit': | ||||
|                 break | ||||
|             time.sleep(.01) | ||||
|         else: | ||||
|             form.CloseNonBlockingForm() | ||||
| 
 | ||||
| 
 | ||||
| # form that doen't block | ||||
| def StatusOutputExample(): | ||||
|     # Make a form, but don't use context manager | ||||
|     form = sg.FlexForm('Running Timer', auto_size_text=True) | ||||
|     # Create a text element that will be updated with status information on the GUI itself | ||||
|     output_element = sg.Text('', size=(8, 2), font=('Helvetica', 20)) | ||||
|     # Create the rows | ||||
|     form_rows = [[sg.Text('Non-blocking GUI with updates')], | ||||
|                  [output_element], | ||||
|                  [sg.SimpleButton('Quit')]] | ||||
|     # Layout the rows of the form and perform a read. Indicate the form is non-blocking! | ||||
|     form.LayoutAndRead(form_rows, non_blocking=True) | ||||
| 
 | ||||
|     # | ||||
|     # Some place later in your code... | ||||
|     # You need to perform a ReadNonBlocking on your form every now and then or | ||||
|     # else it won't refresh | ||||
|     # | ||||
| 
 | ||||
|     for i in range(1, 1000): | ||||
|         output_element.Update('{:02d}:{:02d}.{:02d}'.format(*divmod(int(i / 100), 60), i % 100)) | ||||
|         button, values = form.ReadNonBlocking() | ||||
|         if values is None or button == 'Quit': | ||||
|             break | ||||
|         time.sleep(.01) | ||||
|     else: | ||||
|         form.CloseNonBlockingForm() | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| 
 | ||||
|     main() | ||||
							
								
								
									
										168
									
								
								Demo_Recipes.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								Demo_Recipes.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,168 @@ | |||
| import time | ||||
| from random import randint | ||||
| import PySimpleGUI as sg | ||||
| 
 | ||||
| # A simple blocking form.   Your best starter-form | ||||
| def SourceDestFolders(): | ||||
|     with sg.FlexForm('Demo Source / Destination Folders', auto_size_text=True) as form: | ||||
|         form_rows = [[sg.Text('Enter the Source and Destination folders')], | ||||
|                      [sg.Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Source')], | ||||
|                      [sg.Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Dest'), sg.FolderBrowse()], | ||||
|                      [sg.Submit(), sg.Cancel()]] | ||||
| 
 | ||||
|         button, (source, dest) = form.LayoutAndRead(form_rows) | ||||
|     if button == 'Submit': | ||||
|         sg.MsgBox('Submitted', 'The user entered source:', source, 'Destination folder:', dest, 'Using button', button) | ||||
|     else: | ||||
|         sg.MsgBoxError('Cancelled', 'User Cancelled') | ||||
| 
 | ||||
| # YOUR BEST STARTING POINT | ||||
| # This is a form showing you all of the basic Elements (widgets) | ||||
| # Some have a few of the optional parameters set, but there are more to choose from | ||||
| # You want to use the context manager because it will free up resources when you are finished | ||||
| # Use this especially if you are runningm multi-threaded | ||||
| # Where you free up resources is really important to tkinter | ||||
| def Everything(): | ||||
|     with sg.FlexForm('Everything bagel', auto_size_text=True, default_element_size=(40, 1)) as form: | ||||
|         layout = [ | ||||
|             [sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25), text_color='blue')], | ||||
|             [sg.Text('Here is some text.... and a place to enter text')], | ||||
|             [sg.InputText()], | ||||
|             [sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)], | ||||
|             [sg.Radio('My first Radio!     ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")], | ||||
|             [sg.Multiline(default_text='This is the default Text shoulsd you decide not to type anything', | ||||
|                           scale=(2, 10))], | ||||
|             [sg.InputCombo(['Combobox 1', 'Combobox 2'], size=(20, 3)), | ||||
|              sg.Slider(range=(1, 100), orientation='h', size=(35, 20), default_value=85)], | ||||
|             [sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6)), | ||||
|              sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=25), | ||||
|              sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=75), | ||||
|              sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=10), | ||||
|              sg.Spin(values=('Spin Box 1', '2','3'), initial_value='Spin Box 1')], | ||||
|             [sg.Text('_' * 100, size=(70, 1))], | ||||
|             [sg.Text('Choose Source and Destination Folders', size=(35, 1))], | ||||
|             [sg.Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Source'), sg.FolderBrowse()], | ||||
|             [sg.Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Dest'), | ||||
|              sg.FolderBrowse()], | ||||
|             [sg.Submit(), sg.Cancel(), sg.SimpleButton('Customized', button_color=('white', 'green'))] | ||||
|              ] | ||||
| 
 | ||||
|         button, values = form.LayoutAndRead(layout) | ||||
| 
 | ||||
|     sg.MsgBox('Title', 'Typical message box', 'The results of the form are a lot of data!  Get ready... ', 'The button clicked was "{}"'.format(button), 'The values are', values) | ||||
| 
 | ||||
| # Should you decide not to use a context manager, then try this form as your starting point | ||||
| # Be aware that tkinter, which this is based on, is picky about who frees up resources, especially if | ||||
| # you are running multithreaded | ||||
| def Everything_NoContextManager(): | ||||
|     form = sg.FlexForm('Everything bagel', auto_size_text=True, default_element_size=(40, 1)) | ||||
|     layout = [[sg.Text('All graphic widgets in one form!', size=(30, 1), font=("Helvetica", 25), text_color='blue')], | ||||
|               [sg.Text('Here is some text.... and a place to enter text')], | ||||
|               [sg.InputText()], | ||||
|               [sg.Checkbox('My first checkbox!'), sg.Checkbox('My second checkbox!', default=True)], | ||||
|               [sg.Radio('My first Radio!     ', "RADIO1", default=True), sg.Radio('My second Radio!', "RADIO1")], | ||||
|               [sg.Multiline(default_text='This is the default Text shoulsd you decide not to type anything', scale=(2, 10))], | ||||
|               [sg.InputCombo(['Combobox 1', 'Combobox 2'], size=(20, 3)), sg.Slider(range=(1, 100), orientation='h', size=(35, 20), default_value=85)], | ||||
|               [sg.Listbox(values=['Listbox 1', 'Listbox 2', 'Listbox 3'], size=(30, 6)), | ||||
|                sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=25), | ||||
|                sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=75), | ||||
|                sg.Slider(range=(1, 100), orientation='v', size=(10, 20), default_value=10)], | ||||
|               [sg.Text('_' * 100, size=(70, 1))], | ||||
|               [sg.Text('Choose Source and Destination Folders', size=(35, 1), text_color='red')], | ||||
|               [sg.Text('Source Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Source'), sg.FolderBrowse()], | ||||
|               [sg.Text('Destination Folder', size=(15, 1), auto_size_text=False, justification='right'), sg.InputText('Dest'), sg.FolderBrowse()], | ||||
|               [sg.Submit(), sg.Cancel(), sg.SimpleButton('Customized', button_color=('white', 'green'))]] | ||||
| 
 | ||||
|     button, values = form.LayoutAndRead(layout) | ||||
|     del(form) | ||||
| 
 | ||||
|     sg.MsgBox('Title', 'Typical message box', 'Here are the restults!  There is one entry per input field ', 'The button clicked was "{}"'.format(button), 'The values are', values) | ||||
| 
 | ||||
| def ProgressMeter(): | ||||
|     for i in range(1,10000): | ||||
|         if not sg.EasyProgressMeter('My Meter', i + 1, 10000): break | ||||
|         # SG.Print(i) | ||||
| 
 | ||||
| # Blocking form that doesn't close | ||||
| def ChatBot(): | ||||
|     with sg.FlexForm('Chat Window', auto_size_text=True, default_element_size=(30, 2)) as form: | ||||
|         layout = [[(sg.Text('This is where standard out is being routed', size=[40, 1]))], | ||||
|                   [sg.Output(size=(80, 20))], | ||||
|                   [sg.Multiline(size=(70, 5), enter_submits=True), sg.ReadFormButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])), sg.SimpleButton('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]] | ||||
|         # notice this is NOT the usual LayoutAndRead call because you don't yet want to read the form | ||||
|         # if you call LayoutAndRead from here, then you will miss the first button click | ||||
|         form.Layout(layout) | ||||
|         # ---===--- Loop taking in user input and using it to query HowDoI web oracle --- # | ||||
|         while True: | ||||
|             button, value = form.Read() | ||||
|             if button == 'SEND': | ||||
|                 print(value) | ||||
|             else: | ||||
|                 break | ||||
| 
 | ||||
| # Shows a form that's a running counter | ||||
| # this is the basic design pattern if you can keep your reading of the | ||||
| # form within the 'with' block.  If your read occurs far away in your code from the form creation | ||||
| # then you will want to use the NonBlockingPeriodicUpdateForm example | ||||
| def NonBlockingPeriodicUpdateForm_ContextManager(): | ||||
|     with sg.FlexForm('Running Timer', auto_size_text=True) as form: | ||||
|         text_element = sg.Text('', size=(10, 2), font=('Helvetica', 20), text_color='red', justification='center') | ||||
|         layout = [[sg.Text('Non blocking GUI with updates', justification='center')], | ||||
|                   [text_element], | ||||
|                   [sg.T(' ' * 15), sg.Quit()]] | ||||
|         form.LayoutAndRead(layout, non_blocking=True) | ||||
| 
 | ||||
|         for i in range(1,500): | ||||
|             text_element.Update('{:02d}:{:02d}.{:02d}'.format((i // 100) // 60, (i // 100) % 60, i % 100)) | ||||
|             button, values = form.ReadNonBlocking() | ||||
|             if values is None or button == 'Quit':      # if user closed the window using X | ||||
|                 break | ||||
|             time.sleep(.01) | ||||
|         else: | ||||
|             # if the loop finished then need to close the form for the user | ||||
|             form.CloseNonBlockingForm() | ||||
| 
 | ||||
| # Use this context-manager-free version if your read of the form occurs far away in your code | ||||
| # from the form creation (call to LayoutAndRead) | ||||
| def NonBlockingPeriodicUpdateForm(): | ||||
|     # Show a form that's a running counter | ||||
|     form = sg.FlexForm('Running Timer', auto_size_text=True) | ||||
|     text_element = sg.Text('', size=(10, 2), font=('Helvetica', 20), justification='center') | ||||
|     form_rows = [[sg.Text('Non blocking GUI with updates')], | ||||
|                  [text_element], | ||||
|                  [sg.T(' ' * 15), sg.Quit()]] | ||||
|     form.LayoutAndRead(form_rows, non_blocking=True) | ||||
| 
 | ||||
|     for i in range(1,50000): | ||||
|         text_element.Update('{:02d}:{:02d}.{:02d}'.format((i//100)//60, (i//100)%60, i%100)) | ||||
|         button, values = form.ReadNonBlocking() | ||||
|         if values is None or button == 'Quit':      # if user closed the window using X or clicked Quit button | ||||
|             break | ||||
|         time.sleep(.01) | ||||
|     else: | ||||
|         # if the loop finished then need to close the form for the user | ||||
|         form.CloseNonBlockingForm() | ||||
|     del(form) | ||||
| 
 | ||||
| def DebugTest(): | ||||
|     # SG.Print('How about we print a bunch of random numbers?', , size=(90,40)) | ||||
|     for i in range (1,300): | ||||
|         sg.Print(i, randint(1, 1000), end='', sep='-') | ||||
| 
 | ||||
| 
 | ||||
| def main(): | ||||
|     # SG.SetOptions(border_width=1, font=("Helvetica", 10), button_color=('white', SG.BLUES[0]), slider_border_width=1) | ||||
|     NonBlockingPeriodicUpdateForm_ContextManager() | ||||
|     NonBlockingPeriodicUpdateForm() | ||||
|     Everything_NoContextManager() | ||||
|     Everything() | ||||
|     ChatBot() | ||||
|     ProgressMeter() | ||||
|     SourceDestFolders() | ||||
|     ChatBot() | ||||
|     DebugTest() | ||||
|     sg.MsgBox('Done with all recipes') | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     main() | ||||
|     exit(69) | ||||
							
								
								
									
										89
									
								
								Demo_Tabbed_Form.py
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								Demo_Tabbed_Form.py
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,89 @@ | |||
| import PySimpleGUI as sg | ||||
| 
 | ||||
| MAX_NUMBER_OF_THREADS = 12 | ||||
| 
 | ||||
| def eBaySuperSearcherGUI(): | ||||
|     # Drop Down list of options | ||||
|     configs = ('0 - Gruen - Started 2 days ago in Watches', | ||||
|                '1 - Gruen - Currently Active in Watches', | ||||
|                '2 - Alpina - Currently Active in Jewelry', | ||||
|                '3 - Gruen - Ends in 1 day in Watches', | ||||
|                '4 - Gruen - Completed in Watches', | ||||
|                '5 - Gruen - Advertising', | ||||
|                '6 - Gruen - Currently Active in Jewelry', | ||||
|                '7 - Gruen - Price Test', | ||||
|                '8 - Gruen - No brand name specified') | ||||
| 
 | ||||
|     us_categories = ('Use Default with no change', | ||||
|                      'All - 1', | ||||
|                      'Jewelry - 281', | ||||
|                      '   Watches - 14324', | ||||
|                      '        Wristwatches - 31387', | ||||
|                      '        Pocket Watches - 3937', | ||||
|                      'Advertising - 34', | ||||
|                      '    Watch Ads - 165254' | ||||
|                      ) | ||||
| 
 | ||||
|     german_categories =('Use Default with no change', | ||||
|                         'All - 1', | ||||
|                         'Jewelry - 281', | ||||
|                         '   Watches - 14324', | ||||
|                         '        Wristwatches - 31387', | ||||
|                         '        Pocket Watches - 3937', | ||||
|                         'Advertising - 1', | ||||
|                         '    Watch Ads - 19823' | ||||
|                         ) | ||||
| 
 | ||||
| 
 | ||||
|     # the form layout | ||||
|     with sg.FlexForm('EBay Super Searcher', auto_size_text=True) as form: | ||||
|         with sg.FlexForm('EBay Super Searcher') as form2: | ||||
|             layout_tab_1 = [[sg.Text('eBay Super Searcher!', size=(60,1), font=('helvetica', 15))], | ||||
|               [sg.Text('Choose base configuration to run')], | ||||
|               [sg.InputCombo(configs)], | ||||
|               [sg.Text('_'*100, size=(80,1))], | ||||
|               [sg.InputText(),sg.Text('Choose Destination Folder'), sg.FolderBrowse(target=(sg.ThisRow,0))], | ||||
|               [sg.InputText(),sg.Text('Custom text to add to folder name')], | ||||
|               [sg.Text('_'*100, size=(80,1))], | ||||
|               [sg.Checkbox('US', default=True, size=(15, 1)), sg.Checkbox('German', size=(15, 1), default=True, )], | ||||
|               [sg.Radio('Active Listings','ActiveComplete', default = True,size=(15, 1)), sg.Radio('Completed Listings', 'ActiveComplete', size=(15, 1))], | ||||
|               [sg.Text('_'*100, size=(80,1))], | ||||
|               [sg.Checkbox('Save Images', size=(15,1)),sg.Checkbox('Save PDFs', size=(15,1)), sg.Checkbox('Extract PDFs', size=(15,1))], | ||||
|               [sg.Text('_'*100, size=(80,1))], | ||||
|                [sg.Text('Time Filters')], | ||||
|                [sg.Radio('No change','time', default=True),sg.Radio('ALL listings','time'),sg.Radio('Started 1 day ago','time', size=(15,1)),sg.Radio('Started 2 days ago','time', size=(15,1)), sg.Radio('Ends in 1 day','time', size=(15,1))], | ||||
|                [sg.Text('_'*100, size=(80,1))], | ||||
|               [sg.Text('Price Range'), sg.InputText(size=(10,1)),sg.Text('To'), sg.InputText(size=(10,1))], | ||||
|               [sg.Text('_'*100, size=(80,1))], | ||||
|               [sg.Submit(button_color=('red', 'yellow')), sg.Cancel(button_color=('white', 'blue')), sg.Text(f'{MAX_NUMBER_OF_THREADS} Threads will be started')]] | ||||
| 
 | ||||
| 
 | ||||
|             # First category is default (need to special case this) | ||||
|             layout_tab_2 = [[sg.Text('Choose Category')], | ||||
|                        [sg.Text('US Categories'),sg.Text('German Categories')], | ||||
|                        [sg.Radio(us_categories[0],'CATUS', default=True), sg.Radio(german_categories[0], 'CATDE', default=True)]] | ||||
| 
 | ||||
|             for i,cat in enumerate(us_categories): | ||||
|                 if i == 0: continue         # skip first one | ||||
|                 layout_tab_2.append([sg.Radio(cat,'CATUS'), sg.Radio(german_categories[i],'CATDE')]) | ||||
| 
 | ||||
| 
 | ||||
|             layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))]) | ||||
|             layout_tab_2.append([sg.Text('US Search String Override')]) | ||||
|             layout_tab_2.append([sg.InputText(size=(100,1))]) | ||||
|             layout_tab_2.append([sg.Text('German Search String Override')]) | ||||
|             layout_tab_2.append([sg.InputText(size=(100,1))]) | ||||
|             layout_tab_2.append([sg.Text('Typical US Search String')]) | ||||
|             layout_tab_2.append([sg.InputText(size=(100,1), default_text='gruen -sara -quarz -quartz -embassy -bob -robert -elephants -adidas -LED ')]) | ||||
|             layout_tab_2.append([sg.Text('_' * 100, size=(75, 1))]) | ||||
|             layout_tab_2.append([sg.Submit(button_color=('red', 'yellow'),auto_size_text=True), sg.Cancel(button_color=('white', 'blue'), auto_size_text=True)]) | ||||
| 
 | ||||
|             results = sg.ShowTabbedForm('eBay Super Searcher', (form,layout_tab_1,'Where To Save'), (form2, layout_tab_2, 'Categories & Search String')) | ||||
| 
 | ||||
|     return results | ||||
| 
 | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
|     results = eBaySuperSearcherGUI() | ||||
|     print(results) | ||||
|     sg.MsgBox('Results', results) | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue