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:
MikeTheWatchGuy 2018-07-25 06:40:14 -04:00
parent 13d99dcd75
commit 2109bdbc97
10 changed files with 2427 additions and 0 deletions

1729
Demo_Color.py Normal file

File diff suppressed because it is too large Load Diff

33
Demo_Compare_Files.py Normal file
View 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
View 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()

View 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
View 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
View 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
View 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
View 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
View 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
View 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)