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
File diff suppressed because it is too large
Load Diff
|
@ -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()
|
|
@ -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()
|
|
@ -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)
|
|
@ -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()
|
|
@ -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()
|
||||
|
|
@ -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()
|
||||
|
|
@ -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()
|
|
@ -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)
|
|
@ -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…
Reference in New Issue