Merge pull request #161 from MikeTheWatchGuy/Dev-latest

RELEASE 3.0
This commit is contained in:
MikeTheWatchGuy 2018-09-07 18:05:07 -04:00 committed by GitHub
commit 5df67be3d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 232 additions and 21 deletions

View File

@ -757,17 +757,19 @@ listbox_values = [key for key in fig_dict.keys()]
while True: while True:
sg.ChangeLookAndFeel('Dark') sg.ChangeLookAndFeel('Dark')
sg.SetOptions(element_padding=(0,0))
col_listbox = [[sg.Listbox(values=listbox_values, size=(max(len(x) for x in listbox_values),len(listbox_values)), change_submits=True, key='func')], col_listbox = [[sg.Listbox(values=listbox_values, size=(max(len(x) for x in listbox_values),len(listbox_values)), change_submits=True, key='func')],
[sg.SimpleButton('Run'), sg.Exit()]] [sg.SimpleButton('Run', pad=((30,0),0)), sg.Exit(button_color=('white', 'firebrick4'))]]
layout = [[sg.Text('PySimpleGUI Coookbook', font=('current 18'))], layout = [[sg.Text('PySimpleGUI Coookbook', font=('current 18'))],
[sg.Column(col_listbox, pad=(5,(3,2))), sg.Multiline(size=(70,35), do_not_clear=True, key='multi')], [sg.Column(col_listbox), sg.Multiline(size=(70,35), do_not_clear=True, key='multi')],
] ]
# create the form and show it without the plot # create the form and show it without the plot
# form.Layout(layout) # form.Layout(layout)
form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI', default_button_element_size=(8,2),auto_size_buttons=False) form = sg.FlexForm('Demo Application - Embedding Matplotlib In PySimpleGUI', default_button_element_size=(10,1),auto_size_buttons=False, no_titlebar=True)
button, values = form.LayoutAndRead(layout) button, values = form.LayoutAndRead(layout)
# show it all again and get buttons # show it all again and get buttons
while True: while True:

View File

@ -52,7 +52,7 @@ else:
fname = sys.argv[1] fname = sys.argv[1]
if not fname: if not fname:
sg.MsgBox("Cancelling:", "No filename supplied") sg.Popup("Cancelling:", "No filename supplied")
raise SystemExit("Cancelled: no filename supplied") raise SystemExit("Cancelled: no filename supplied")
doc = fitz.open(fname) doc = fitz.open(fname)
@ -122,7 +122,7 @@ root.destroy()
del root del root
form = sg.FlexForm(title, return_keyboard_events = True, form = sg.FlexForm(title, return_keyboard_events = True,
location = (0,0), use_default_focus = False, no_titlebar=True) location = (0,0), use_default_focus = False, no_titlebar=False)
cur_page = 0 cur_page = 0
data, clip_pos = get_page(cur_page, data, clip_pos = get_page(cur_page,

View File

@ -3,13 +3,9 @@
# that adjusts the size of text displayed # that adjusts the size of text displayed
import PySimpleGUI as sg import PySimpleGUI as sg
fontSize = 12 fontSize = 12
layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin'), layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_value=fontSize, change_submits=True, key='spin'),
sg.Slider(range=(6,172), orientation='h', size=(10,20), change_submits=True, key='slider', font=('Helvetica 20')), sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]] sg.Slider(range=(6,172), orientation='h', size=(10,20), change_submits=True, key='slider', font=('Helvetica 20')), sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
sz = fontSize sz = fontSize
form = sg.FlexForm("Font size selector", grab_anywhere=False) form = sg.FlexForm("Font size selector", grab_anywhere=False)
form.Layout(layout) form.Layout(layout)

View File

@ -5,13 +5,14 @@ import time
# good for applications with an loop that polls hardware # good for applications with an loop that polls hardware
def Timer(): def Timer():
sg.ChangeLookAndFeel('Dark') sg.ChangeLookAndFeel('Dark')
sg.SetOptions(element_padding=(0,0))
# Make a form, but don't use context manager # Make a form, but don't use context manager
form = sg.FlexForm('Running Timer', grab_anywhere=False, no_titlebar=True, auto_size_buttons=False) form = sg.FlexForm('Running Timer', grab_anywhere=False, no_titlebar=True, auto_size_buttons=False)
# Create a text element that will be updated with status information on the GUI itself # Create a text element that will be updated with status information on the GUI itself
# Create the rows # Create the rows
form_rows = [[sg.Text('Stopwatch')], form_rows = [[sg.Text('')],
[sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')],
[sg.ReadFormButton('Pause'), sg.ReadFormButton('Reset'), sg.Exit()]] [sg.ReadFormButton('Pause'), sg.ReadFormButton('Reset'), sg.Exit(button_color=('white','firebrick4'))]]
# Layout the rows of the form and perform a read. Indicate the form is non-blocking! # Layout the rows of the form and perform a read. Indicate the form is non-blocking!
form.Layout(form_rows) form.Layout(form_rows)
# #

View File

@ -11,7 +11,7 @@
# PySimpleGUI # PySimpleGUI
(Ver 2.30) (Ver 3.00)
@ -823,7 +823,8 @@ This is the definition of the FlexForm object:
return_keyboard_events=False, return_keyboard_events=False,
use_default_focus=True, use_default_focus=True,
text_justification=None, text_justification=None,
no_titlebar=False): no_titlebar=False,
grab_anywhere=True):
Parameter Descriptions. You will find these same parameters specified for each `Element` and some of them in `Row` specifications. The `Element` specified value will take precedence over the `Row` and `Form` values. Parameter Descriptions. You will find these same parameters specified for each `Element` and some of them in `Row` specifications. The `Element` specified value will take precedence over the `Row` and `Form` values.
@ -847,6 +848,7 @@ Parameter Descriptions. You will find these same parameters specified for each
use_default_focus - if True and no focus set, then automatically set a focus use_default_focus - if True and no focus set, then automatically set a focus
text_justification - Justification to use for Text Elements in this form text_justification - Justification to use for Text Elements in this form
no_titlebar - Create window without a titlebar no_titlebar - Create window without a titlebar
grab_anywhere - Grab any location on the window to move the window
#### Window Location #### Window Location
@ -1234,6 +1236,8 @@ The Types of buttons include:
* Close Form * Close Form
* Read Form * Read Form
* Realtime * Realtime
* Calendar Chooser
* Color Chooser
Close Form - Normal buttons like Submit, Cancel, Yes, No, etc, are "Close Form" buttons. They cause the input values to be read and then the form is closed, returning the values to the caller. Close Form - Normal buttons like Submit, Cancel, Yes, No, etc, are "Close Form" buttons. They cause the input values to be read and then the form is closed, returning the values to the caller.
@ -1242,6 +1246,10 @@ Folder Browse - When clicked a folder browse dialog box is opened. The results
File Browse - Same as the Folder Browse except rather than choosing a folder, a single file is chosen. File Browse - Same as the Folder Browse except rather than choosing a folder, a single file is chosen.
Calendar Chooser - Opens a graphical calendar to select a date.
Color Chooser - Opens a color chooser dialog
Read Form - This is an async form button that will read a snapshot of all of the input fields, but does not close the form after it's clicked. Read Form - This is an async form button that will read a snapshot of all of the input fields, but does not close the form after it's clicked.
Realtime - This is another async form button. Normal button clicks occur after a button's click is released. Realtime buttons report a click the entire time the button is held down. Realtime - This is another async form button. Normal button clicks occur after a button's click is released. Realtime buttons report a click the entire time the button is held down.
@ -1281,10 +1289,13 @@ These Pre-made buttons are some of the most important elements of all because th
![ok cancel 3](https://user-images.githubusercontent.com/13696193/44959927-aa5f5e80-aec4-11e8-86e1-5dc0b3a2b803.jpg) ![ok cancel 3](https://user-images.githubusercontent.com/13696193/44959927-aa5f5e80-aec4-11e8-86e1-5dc0b3a2b803.jpg)
#### Button targets
The FileBrowse, FolderBrowse, FileSaveAs buttons all fill-in values into a text input field somewhere on the form. The location of the TextInput element is specified by the `Target` variable in the function call. The Target is specified using a grid system. The rows in your GUI are numbered starting with 0. The target can be specified as a hard coded grid item or it can be relative to the button. The `FileBrowse`, `FolderBrowse`, `FileSaveAs` , `FilesSaveAs`, `CalendarButton`, `ColorChooserButton` buttons all fill-in values into another element located on the form. The target can be a Text Element or an InputText Element. The location of the element is specified by the `target` variable in the function call. The Target is specified using a grid system. The rows in your GUI are numbered starting with 0. The target can be specified as a hard coded grid item or it can be relative to the button.
The default value for `Target` is `(ThisRow, -1)`. ThisRow is a special value that tells the GUI to use the same row as the button. The Y-value of -1 means the field one value to the left of the button. For a File or Folder Browse button, the field that it fills are generally to the left of the button is most cases. The default value for `targe` is `(ThisRow, -1)`. `ThisRow` is a special value that tells the GUI to use the same row as the button. The Y-value of -1 means the field one value to the left of the button. For a File or Folder Browse button, the field that it fills are generally to the left of the button is most cases.
If a value of `(None, None)` is chosen for the target, then the button itself will hold the information. Later the button can be queried for the value.
Let's examine this form as an example: Let's examine this form as an example:
@ -1303,6 +1314,33 @@ The code for the entire form could be:
[sg.In()], [sg.In()],
[sg.FolderBrowse(target=(-1, 0)), sg.OK()]] [sg.FolderBrowse(target=(-1, 0)), sg.OK()]]
**Save & Open Buttons**
There are 3 different types of File/Folder open dialog box available. If you are looking for a file to open, the `FileBrowse` is what you want. If you want to save a file, `SaveAs` is the button. If you want to get a folder name, then `FolderBrowse` is the button to use.
![open](https://user-images.githubusercontent.com/13696193/45243804-2b529780-b2c3-11e8-90dc-6c9061db2a1e.jpg)
![folder](https://user-images.githubusercontent.com/13696193/45243805-2b529780-b2c3-11e8-95ee-fec3c0b11319.jpg)
![saveas](https://user-images.githubusercontent.com/13696193/45243807-2beb2e00-b2c3-11e8-8549-ba71cdc05951.jpg)
**Calendar Buttons**
These buttons pop up a calendar chooser window. The chosen date is returned as a string.
![calendar](https://user-images.githubusercontent.com/13696193/45243374-99965a80-b2c1-11e8-8311-49777835ca40.jpg)
**Color Chooser Buttons**
These buttons pop up a standard color chooser window. The result is returned as a tuple. One of the returned values is an RGB hex representation.
![color](https://user-images.githubusercontent.com/13696193/45243375-99965a80-b2c1-11e8-9779-b71bed85fab6.jpg)
**Custom Buttons** **Custom Buttons**
Not all buttons are created equal. A button that closes a form is different that a button that returns from the form without closing it. If you want to define your own button, you will generally do this with the Button Element `SimpleButton`, which closes the form when clicked. Not all buttons are created equal. A button that closes a form is different that a button that returns from the form without closing it. If you want to define your own button, you will generally do this with the Button Element `SimpleButton`, which closes the form when clicked.
@ -1405,8 +1443,10 @@ The return value for `EasyProgressMeter` is:
`True` if meter updated correctly `True` if meter updated correctly
`False` if user clicked the Cancel button, closed the form, or vale reached the max value. `False` if user clicked the Cancel button, closed the form, or vale reached the max value.
**Customized Progress Bar** **Customized Progress Bar**
If you want a bit more customization of your meter, then you can go up 1 level and use the calls to `ProgressMeter` and `ProgressMeterUpdate`. These APIs behave like an object we're all used to. First you create the `ProgressMeter` object, then you call the `Update` method to update it. If you want a bit more customization of your meter, then you can go up 1 level and use the calls to `ProgressMeter` and `ProgressMeterUpdate`. These APIs behave like an object we're all used to. First you create the `ProgressMeter` object, then you call the `Update` method to update it.
You setup the progress meter by calling You setup the progress meter by calling
my_meter = ProgressMeter(title, my_meter = ProgressMeter(title,
@ -1433,6 +1473,30 @@ Putting it all together you get this design pattern
The final way of using a Progress Meter with PySimpleGUI is to build a custom form with a `ProgressBar` Element in the form. You will need to run your form as a non-blocking form. When you are ready to update your progress bar, you call the `UpdateBar` method for the `ProgressBar` element itself. The final way of using a Progress Meter with PySimpleGUI is to build a custom form with a `ProgressBar` Element in the form. You will need to run your form as a non-blocking form. When you are ready to update your progress bar, you call the `UpdateBar` method for the `ProgressBar` element itself.
![progress custom](https://user-images.githubusercontent.com/13696193/45243969-c3508100-b2c3-11e8-82bc-927d0307e093.jpg)
# create the progress bar element
progress_bar = sg.ProgressBar(10000, orientation='h', size=(20,20))
# layout the form
layout = [[sg.Text('A custom progress meter')],
[progress_bar],
[sg.Cancel()]]
# create the form`
form = sg.FlexForm('Custom Progress Meter')
# display the form as a non-blocking form
form.LayoutAndRead(layout, non_blocking=True)
# loop that would normally do something useful
for i in range(10000):
# check to see if the cancel button was clicked and exit loop if clicked
button, values = form.ReadNonBlocking()
if button == 'Cancel' or values == None:
break
# update bar with loop value +1 so that bar eventually reaches the maximum
progress_bar.UpdateBar(i+1)
# done with loop... need to destroy the window as it's still open
form.CloseNonBlockingForm()
#### Output #### Output
The Output Element is a re-direction of Stdout. Anything "printed" will be displayed in this element. The Output Element is a re-direction of Stdout. Anything "printed" will be displayed in this element.
@ -1786,7 +1850,26 @@ Use realtime keyboard capture by calling
elif value is None: elif value is None:
break break
## Updating Elements
This is a somewhat advanced topic...
Typically you perform Element updates in response to events from other Elements. An example is that when you click a button some text on the form changes to red. You can change the Element's attributes, or at least some of them, and the Element's value.
In some source code examples you will find an older techique for updating elements that did not involve keys. If you see a technique in the code that does not use keys, then know that there is a version using keys that is easier.
Here's the key's version....
We have an InputText field that we want to update. When the Element was created we used this call:
sg.Input(key='input')
To update or change the value for that Input Element, we use this contruct:
form.FindElement('input').Update('new text')
Using the '.' makes the code shorter. The FindElement call returns an Element. We then call that Element's Update function.
See the Font Sizer demo for example source code.
## Sample Applications ## Sample Applications
@ -1796,6 +1879,8 @@ Use the example programs as a starting basis for your GUI. Copy, paste, modify
|--|--| |--|--|
|**Demo_All_Widgets.py**| Nearly all of the Elements shown in a single form |**Demo_All_Widgets.py**| Nearly all of the Elements shown in a single form
|**Demo_Borderless_Window.py**| Create clean looking windows with no border |**Demo_Borderless_Window.py**| Create clean looking windows with no border
|**Demo_Button_States.py**| One way of implementing disabling of buttons
|**Demo_Calendar.py** | Demo of the Calendar Chooser button
|**Demo_Canvas.py** | Form with a Canvas Element that is updated outside of the form |**Demo_Canvas.py** | Form with a Canvas Element that is updated outside of the form
|**Demo_Chat.py** | A chat window with scrollable history |**Demo_Chat.py** | A chat window with scrollable history
|**Demo_Chatterbot.py** | Front-end to Chatterbot Machine Learning project |**Demo_Chatterbot.py** | Front-end to Chatterbot Machine Learning project
@ -1804,11 +1889,15 @@ Use the example programs as a starting basis for your GUI. Copy, paste, modify
|**Demo_Compare_Files.py** | Using a simple GUI front-end to create a compare 2-files utility |**Demo_Compare_Files.py** | Using a simple GUI front-end to create a compare 2-files utility
|**Demo_Cookbook_Browser.py** | Source code browser for all Recipes in Cookbook |**Demo_Cookbook_Browser.py** | Source code browser for all Recipes in Cookbook
|**Demo_Dictionary.py** | Specifying and using return values in dictionary format |**Demo_Dictionary.py** | Specifying and using return values in dictionary format
**Demo_DOC_Viewer_PIL.py** | Display a PDF, HTML, ebook file, etc in your form
|**Demo_DisplayHash1and256.py** | Using high level API and custom form to implement a simple display hash code utility |**Demo_DisplayHash1and256.py** | Using high level API and custom form to implement a simple display hash code utility
|**Demo_DuplicateFileFinder.py** | High level API used to get a folder that is used by utility that finds duplicate files. Uses progress meter to show progress. 2 lines of code required to add GUI and meter |**Demo_DuplicateFileFinder.py** | High level API used to get a folder that is used by utility that finds duplicate files. Uses progress meter to show progress. 2 lines of code required to add GUI and meter
|**Demo_Fill_Form.py** | How to perform a bulk-fill for a form. Saving and loading a form from disk
|**Demo Font Sizer.py** | Demonstrates Elements updating other Elements
|**Demo_Func_Callback_Simulator.py** | For the Raspberry Pi crowd. Event loop that simulates traditional GUI callback functions should you already have an architecture that uses them |**Demo_Func_Callback_Simulator.py** | For the Raspberry Pi crowd. Event loop that simulates traditional GUI callback functions should you already have an architecture that uses them
|**Demo_GoodColors.py** | Using some of the pre-defined PySimpleGUI individual colors |**Demo_GoodColors.py** | Using some of the pre-defined PySimpleGUI individual colors
|**Demo_HowDoI.py** | This is a utility to be experienced! It will change how you code |**Demo_HowDoI.py** | This is a utility to be experienced! It will change how you code
|**Demo_Img_Viewer.py** | Display jpg, png,tiff, bmp files
|**Demo_Keyboard.py** | Using blocking keyboard events |**Demo_Keyboard.py** | Using blocking keyboard events
|**Demo_Keyboard_Realtime.py** | Using non-blocking / realtime keyboard events |**Demo_Keyboard_Realtime.py** | Using non-blocking / realtime keyboard events
|**Demo_Machine_Learning.py** | A sample Machine Learning front end |**Demo_Machine_Learning.py** | A sample Machine Learning front end
@ -1819,13 +1908,18 @@ Use the example programs as a starting basis for your GUI. Copy, paste, modify
|**Demo_Media_Player.py** | Non-blocking form with a media player layout. Demonstrates button graphics, Update method |**Demo_Media_Player.py** | Non-blocking form with a media player layout. Demonstrates button graphics, Update method
|**Demo_MIDI_Player.py** | GUI wrapper for Mido MIDI package. Functional MIDI player that controls attached MIDI devices |**Demo_MIDI_Player.py** | GUI wrapper for Mido MIDI package. Functional MIDI player that controls attached MIDI devices
|**Demo_NonBlocking_Form.py** | a basic async form |**Demo_NonBlocking_Form.py** | a basic async form
|** Demo_OpenCV.py** | Integrated with OpenCV
|** Demo_Password_Login** | Password protection using SHA1
|**Demo_PDF_Viewer.py** | Submitted by a user! Previews PDF documents. Uses keyboard input & mouse scrollwheel to navigate |**Demo_PDF_Viewer.py** | Submitted by a user! Previews PDF documents. Uses keyboard input & mouse scrollwheel to navigate
|**Demo_Pi_LEDs.py** | Control GPIO using buttons
|**Demo_Pi_Robotics.py** | Simulated robot control using realtime buttons |**Demo_Pi_Robotics.py** | Simulated robot control using realtime buttons
|**Demo_PNG_Vierwer.py** | Uses Image Element to display PNG files |**Demo_PNG_Vierwer.py** | Uses Image Element to display PNG files
|**Demo_Recipes.py** | A collection of various Recipes. Note these are not the same as the Recipes in the Recipe Cookbook |**Demo_Recipes.py** | A collection of various Recipes. Note these are not the same as the Recipes in the Recipe Cookbook
|**Demo_Script_Launcher.py** | Demonstrates one way of adding a front-end onto several command line scripts |**Demo_Script_Launcher.py** | Demonstrates one way of adding a front-end onto several command line scripts
|**Demo_Script_Parameters.py** | Add a 1-line GUI to the front of your previously command-line only scripts |**Demo_Script_Parameters.py** | Add a 1-line GUI to the front of your previously command-line only scripts
|**Demo_Tabbed_Form.py** | Using the Tab feature |**Demo_Tabbed_Form.py** | Using the Tab feature
|**Demo_Table_Simulation.py** | Use input fields to display and edit tables
|**Demo_Timer.py** | Simple non-blocking form
## Packages Used In Demos ## Packages Used In Demos
@ -1931,6 +2025,7 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 2.11.0 | Aug 29, 2018 - Lots of little changes that are needed for the demo programs to work. Buttons have their own default element size, fix for Mac default button color, padding support for all elements, option to immediately return if list box gets selected, FilesBrowse button, Canvas Element, Frame Element, Slider resolution option, Form.Refresh method, better text wrapping, 'SystemDefault' look and feel settin | 2.11.0 | Aug 29, 2018 - Lots of little changes that are needed for the demo programs to work. Buttons have their own default element size, fix for Mac default button color, padding support for all elements, option to immediately return if list box gets selected, FilesBrowse button, Canvas Element, Frame Element, Slider resolution option, Form.Refresh method, better text wrapping, 'SystemDefault' look and feel settin
| 2.20.0 | Sept 4, 2018 - Some sizable features this time around of interest to advanced users. Renaming of the MsgBox functions to Popup. Renaming GetFile, etc, to PopupGetFile. High-level windowing capabilities start with Popup, PopupNoWait/PopupNonblocking, PopupNoButtons, default icon, change_submits option for Listbox/Combobox/Slider/Spin/, New OptionMenu element, updating elements after shown, system defaul color option for progress bars, new button type (Dummy Button) that only closes a window, SCROLLABLE Columns!! (yea, playing in the Big League now), LayoutAndShow function removed, form.Fill - bulk updates to forms, FindElement - find element based on key value (ALL elements have keys now), no longer use grid packing for row elements (a potentially huge change), scrolled text box sizing changed, new look and feel themes (Dark, Dark2, Black, Tan, TanBlue, DarkTanBlue, DarkAmber, DarkBlue, Reds, Green) | 2.20.0 | Sept 4, 2018 - Some sizable features this time around of interest to advanced users. Renaming of the MsgBox functions to Popup. Renaming GetFile, etc, to PopupGetFile. High-level windowing capabilities start with Popup, PopupNoWait/PopupNonblocking, PopupNoButtons, default icon, change_submits option for Listbox/Combobox/Slider/Spin/, New OptionMenu element, updating elements after shown, system defaul color option for progress bars, new button type (Dummy Button) that only closes a window, SCROLLABLE Columns!! (yea, playing in the Big League now), LayoutAndShow function removed, form.Fill - bulk updates to forms, FindElement - find element based on key value (ALL elements have keys now), no longer use grid packing for row elements (a potentially huge change), scrolled text box sizing changed, new look and feel themes (Dark, Dark2, Black, Tan, TanBlue, DarkTanBlue, DarkAmber, DarkBlue, Reds, Green)
| 2.30.0 | Sept 6, 2018 - Calendar Chooser (button), borderless windows, load/save form to disk | 2.30.0 | Sept 6, 2018 - Calendar Chooser (button), borderless windows, load/save form to disk
| 3.0.0 | Sept 7, 2018 - The "fix for poor choice of 2.x numbers" release. Color Chooser (button), "grab anywhere" windows are on by default, disable combo boxes, Input Element text justification (last part needed for 'tables'), Image Element changes to support OpenCV?, PopupGetFile and PopupGetFolder have better no_window option
### Release Notes ### Release Notes
@ -1950,11 +2045,19 @@ Listboxes are still without scrollwheels. The mouse can drag to see more items.
2.9 COLUMNS! This is the biggest feature and had the biggest impact on the code base. It was a difficult feature to add, but it was worth it. Can now make even more layouts. Almost any layout is possible with this addition. 2.9 COLUMNS! This is the biggest feature and had the biggest impact on the code base. It was a difficult feature to add, but it was worth it. Can now make even more layouts. Almost any layout is possible with this addition.
.................. insert releases 2.9 to 2.30 .................
3.0 We've come a long way baby! Time for a major revision bump. One reason is that the numbers started to confuse people the latest release was 2.30, but some people read it as 2.3 and thought it went backwards. I kinda messed up the 2.x series of numbers, so why not start with a clean slate. A lot has happened anyway so it's well earned.
One change that will set PySimpleGUI apart is the parlor trick of being able to move the window by clicking on it anywhere. This is turned on by default. It's not a common way to interact with windows. Normally you have to move using the titlebar. Not so with PySimpleGUI. Now you can drag using any part of the window. You will want to turn this off for windows with sliders. This feature is enabled in the FlexForm call.
Related to the Grab Anywhere feature is the no_titlebar option, again found in the call to FlexForm. Your window will be a spiffy, borderless window. It's a really interesting effect. Slight problem is that you do not have an icon on the taskbar with these types of windows, so if you don't supply a button to close the window, there's no way to close it other than task manager.
### Upcoming ### Upcoming
Make suggestions people! Future release features Make suggestions people! Future release features
Port to other graphic engines. Hook up the front-end interface to a backend other than tkinter. Qt, WxPython, etc. Port to other graphic engines. Hook up the front-end interface to a backend other than tkinter. Qt, WxPython, etc. WxPython is higher priority.
@ -1986,6 +2089,8 @@ It seemed quite natural to use Python's powerful list constructs when possible.
**Dictionaries** **Dictionaries**
Want to view your form's results as a dictionary instead of a list... no problem, just use the `key` keyword on your elements. For complex forms with a lot of values that need to be changed frequently, this is by far the best way of consuming the results. Want to view your form's results as a dictionary instead of a list... no problem, just use the `key` keyword on your elements. For complex forms with a lot of values that need to be changed frequently, this is by far the best way of consuming the results.
You can also look up elements using their keys. This is an excellent way to update elements in reaction to another element. Call `form.FindElement(key)` to get the Element.
## Author ## Author
MikeTheWatchGuy MikeTheWatchGuy
@ -2034,3 +2139,4 @@ In the hands of a competent programmer, this tool is **amazing**. It's a must-
The PySimpleGUI window that the results are shown in is an 'input' field which means you can copy and paste the results right into your code. The PySimpleGUI window that the results are shown in is an 'input' field which means you can copy and paste the results right into your code.

116
readme.md
View File

@ -11,7 +11,7 @@
# PySimpleGUI # PySimpleGUI
(Ver 2.30) (Ver 3.00)
@ -823,7 +823,8 @@ This is the definition of the FlexForm object:
return_keyboard_events=False, return_keyboard_events=False,
use_default_focus=True, use_default_focus=True,
text_justification=None, text_justification=None,
no_titlebar=False): no_titlebar=False,
grab_anywhere=True):
Parameter Descriptions. You will find these same parameters specified for each `Element` and some of them in `Row` specifications. The `Element` specified value will take precedence over the `Row` and `Form` values. Parameter Descriptions. You will find these same parameters specified for each `Element` and some of them in `Row` specifications. The `Element` specified value will take precedence over the `Row` and `Form` values.
@ -847,6 +848,7 @@ Parameter Descriptions. You will find these same parameters specified for each
use_default_focus - if True and no focus set, then automatically set a focus use_default_focus - if True and no focus set, then automatically set a focus
text_justification - Justification to use for Text Elements in this form text_justification - Justification to use for Text Elements in this form
no_titlebar - Create window without a titlebar no_titlebar - Create window without a titlebar
grab_anywhere - Grab any location on the window to move the window
#### Window Location #### Window Location
@ -1234,6 +1236,8 @@ The Types of buttons include:
* Close Form * Close Form
* Read Form * Read Form
* Realtime * Realtime
* Calendar Chooser
* Color Chooser
Close Form - Normal buttons like Submit, Cancel, Yes, No, etc, are "Close Form" buttons. They cause the input values to be read and then the form is closed, returning the values to the caller. Close Form - Normal buttons like Submit, Cancel, Yes, No, etc, are "Close Form" buttons. They cause the input values to be read and then the form is closed, returning the values to the caller.
@ -1242,6 +1246,10 @@ Folder Browse - When clicked a folder browse dialog box is opened. The results
File Browse - Same as the Folder Browse except rather than choosing a folder, a single file is chosen. File Browse - Same as the Folder Browse except rather than choosing a folder, a single file is chosen.
Calendar Chooser - Opens a graphical calendar to select a date.
Color Chooser - Opens a color chooser dialog
Read Form - This is an async form button that will read a snapshot of all of the input fields, but does not close the form after it's clicked. Read Form - This is an async form button that will read a snapshot of all of the input fields, but does not close the form after it's clicked.
Realtime - This is another async form button. Normal button clicks occur after a button's click is released. Realtime buttons report a click the entire time the button is held down. Realtime - This is another async form button. Normal button clicks occur after a button's click is released. Realtime buttons report a click the entire time the button is held down.
@ -1281,10 +1289,13 @@ These Pre-made buttons are some of the most important elements of all because th
![ok cancel 3](https://user-images.githubusercontent.com/13696193/44959927-aa5f5e80-aec4-11e8-86e1-5dc0b3a2b803.jpg) ![ok cancel 3](https://user-images.githubusercontent.com/13696193/44959927-aa5f5e80-aec4-11e8-86e1-5dc0b3a2b803.jpg)
#### Button targets
The FileBrowse, FolderBrowse, FileSaveAs buttons all fill-in values into a text input field somewhere on the form. The location of the TextInput element is specified by the `Target` variable in the function call. The Target is specified using a grid system. The rows in your GUI are numbered starting with 0. The target can be specified as a hard coded grid item or it can be relative to the button. The `FileBrowse`, `FolderBrowse`, `FileSaveAs` , `FilesSaveAs`, `CalendarButton`, `ColorChooserButton` buttons all fill-in values into another element located on the form. The target can be a Text Element or an InputText Element. The location of the element is specified by the `target` variable in the function call. The Target is specified using a grid system. The rows in your GUI are numbered starting with 0. The target can be specified as a hard coded grid item or it can be relative to the button.
The default value for `Target` is `(ThisRow, -1)`. ThisRow is a special value that tells the GUI to use the same row as the button. The Y-value of -1 means the field one value to the left of the button. For a File or Folder Browse button, the field that it fills are generally to the left of the button is most cases. The default value for `targe` is `(ThisRow, -1)`. `ThisRow` is a special value that tells the GUI to use the same row as the button. The Y-value of -1 means the field one value to the left of the button. For a File or Folder Browse button, the field that it fills are generally to the left of the button is most cases.
If a value of `(None, None)` is chosen for the target, then the button itself will hold the information. Later the button can be queried for the value.
Let's examine this form as an example: Let's examine this form as an example:
@ -1303,6 +1314,33 @@ The code for the entire form could be:
[sg.In()], [sg.In()],
[sg.FolderBrowse(target=(-1, 0)), sg.OK()]] [sg.FolderBrowse(target=(-1, 0)), sg.OK()]]
**Save & Open Buttons**
There are 3 different types of File/Folder open dialog box available. If you are looking for a file to open, the `FileBrowse` is what you want. If you want to save a file, `SaveAs` is the button. If you want to get a folder name, then `FolderBrowse` is the button to use.
![open](https://user-images.githubusercontent.com/13696193/45243804-2b529780-b2c3-11e8-90dc-6c9061db2a1e.jpg)
![folder](https://user-images.githubusercontent.com/13696193/45243805-2b529780-b2c3-11e8-95ee-fec3c0b11319.jpg)
![saveas](https://user-images.githubusercontent.com/13696193/45243807-2beb2e00-b2c3-11e8-8549-ba71cdc05951.jpg)
**Calendar Buttons**
These buttons pop up a calendar chooser window. The chosen date is returned as a string.
![calendar](https://user-images.githubusercontent.com/13696193/45243374-99965a80-b2c1-11e8-8311-49777835ca40.jpg)
**Color Chooser Buttons**
These buttons pop up a standard color chooser window. The result is returned as a tuple. One of the returned values is an RGB hex representation.
![color](https://user-images.githubusercontent.com/13696193/45243375-99965a80-b2c1-11e8-9779-b71bed85fab6.jpg)
**Custom Buttons** **Custom Buttons**
Not all buttons are created equal. A button that closes a form is different that a button that returns from the form without closing it. If you want to define your own button, you will generally do this with the Button Element `SimpleButton`, which closes the form when clicked. Not all buttons are created equal. A button that closes a form is different that a button that returns from the form without closing it. If you want to define your own button, you will generally do this with the Button Element `SimpleButton`, which closes the form when clicked.
@ -1405,8 +1443,10 @@ The return value for `EasyProgressMeter` is:
`True` if meter updated correctly `True` if meter updated correctly
`False` if user clicked the Cancel button, closed the form, or vale reached the max value. `False` if user clicked the Cancel button, closed the form, or vale reached the max value.
**Customized Progress Bar** **Customized Progress Bar**
If you want a bit more customization of your meter, then you can go up 1 level and use the calls to `ProgressMeter` and `ProgressMeterUpdate`. These APIs behave like an object we're all used to. First you create the `ProgressMeter` object, then you call the `Update` method to update it. If you want a bit more customization of your meter, then you can go up 1 level and use the calls to `ProgressMeter` and `ProgressMeterUpdate`. These APIs behave like an object we're all used to. First you create the `ProgressMeter` object, then you call the `Update` method to update it.
You setup the progress meter by calling You setup the progress meter by calling
my_meter = ProgressMeter(title, my_meter = ProgressMeter(title,
@ -1433,6 +1473,30 @@ Putting it all together you get this design pattern
The final way of using a Progress Meter with PySimpleGUI is to build a custom form with a `ProgressBar` Element in the form. You will need to run your form as a non-blocking form. When you are ready to update your progress bar, you call the `UpdateBar` method for the `ProgressBar` element itself. The final way of using a Progress Meter with PySimpleGUI is to build a custom form with a `ProgressBar` Element in the form. You will need to run your form as a non-blocking form. When you are ready to update your progress bar, you call the `UpdateBar` method for the `ProgressBar` element itself.
![progress custom](https://user-images.githubusercontent.com/13696193/45243969-c3508100-b2c3-11e8-82bc-927d0307e093.jpg)
# create the progress bar element
progress_bar = sg.ProgressBar(10000, orientation='h', size=(20,20))
# layout the form
layout = [[sg.Text('A custom progress meter')],
[progress_bar],
[sg.Cancel()]]
# create the form`
form = sg.FlexForm('Custom Progress Meter')
# display the form as a non-blocking form
form.LayoutAndRead(layout, non_blocking=True)
# loop that would normally do something useful
for i in range(10000):
# check to see if the cancel button was clicked and exit loop if clicked
button, values = form.ReadNonBlocking()
if button == 'Cancel' or values == None:
break
# update bar with loop value +1 so that bar eventually reaches the maximum
progress_bar.UpdateBar(i+1)
# done with loop... need to destroy the window as it's still open
form.CloseNonBlockingForm()
#### Output #### Output
The Output Element is a re-direction of Stdout. Anything "printed" will be displayed in this element. The Output Element is a re-direction of Stdout. Anything "printed" will be displayed in this element.
@ -1786,7 +1850,26 @@ Use realtime keyboard capture by calling
elif value is None: elif value is None:
break break
## Updating Elements
This is a somewhat advanced topic...
Typically you perform Element updates in response to events from other Elements. An example is that when you click a button some text on the form changes to red. You can change the Element's attributes, or at least some of them, and the Element's value.
In some source code examples you will find an older techique for updating elements that did not involve keys. If you see a technique in the code that does not use keys, then know that there is a version using keys that is easier.
Here's the key's version....
We have an InputText field that we want to update. When the Element was created we used this call:
sg.Input(key='input')
To update or change the value for that Input Element, we use this contruct:
form.FindElement('input').Update('new text')
Using the '.' makes the code shorter. The FindElement call returns an Element. We then call that Element's Update function.
See the Font Sizer demo for example source code.
## Sample Applications ## Sample Applications
@ -1796,6 +1879,8 @@ Use the example programs as a starting basis for your GUI. Copy, paste, modify
|--|--| |--|--|
|**Demo_All_Widgets.py**| Nearly all of the Elements shown in a single form |**Demo_All_Widgets.py**| Nearly all of the Elements shown in a single form
|**Demo_Borderless_Window.py**| Create clean looking windows with no border |**Demo_Borderless_Window.py**| Create clean looking windows with no border
|**Demo_Button_States.py**| One way of implementing disabling of buttons
|**Demo_Calendar.py** | Demo of the Calendar Chooser button
|**Demo_Canvas.py** | Form with a Canvas Element that is updated outside of the form |**Demo_Canvas.py** | Form with a Canvas Element that is updated outside of the form
|**Demo_Chat.py** | A chat window with scrollable history |**Demo_Chat.py** | A chat window with scrollable history
|**Demo_Chatterbot.py** | Front-end to Chatterbot Machine Learning project |**Demo_Chatterbot.py** | Front-end to Chatterbot Machine Learning project
@ -1804,11 +1889,15 @@ Use the example programs as a starting basis for your GUI. Copy, paste, modify
|**Demo_Compare_Files.py** | Using a simple GUI front-end to create a compare 2-files utility |**Demo_Compare_Files.py** | Using a simple GUI front-end to create a compare 2-files utility
|**Demo_Cookbook_Browser.py** | Source code browser for all Recipes in Cookbook |**Demo_Cookbook_Browser.py** | Source code browser for all Recipes in Cookbook
|**Demo_Dictionary.py** | Specifying and using return values in dictionary format |**Demo_Dictionary.py** | Specifying and using return values in dictionary format
**Demo_DOC_Viewer_PIL.py** | Display a PDF, HTML, ebook file, etc in your form
|**Demo_DisplayHash1and256.py** | Using high level API and custom form to implement a simple display hash code utility |**Demo_DisplayHash1and256.py** | Using high level API and custom form to implement a simple display hash code utility
|**Demo_DuplicateFileFinder.py** | High level API used to get a folder that is used by utility that finds duplicate files. Uses progress meter to show progress. 2 lines of code required to add GUI and meter |**Demo_DuplicateFileFinder.py** | High level API used to get a folder that is used by utility that finds duplicate files. Uses progress meter to show progress. 2 lines of code required to add GUI and meter
|**Demo_Fill_Form.py** | How to perform a bulk-fill for a form. Saving and loading a form from disk
|**Demo Font Sizer.py** | Demonstrates Elements updating other Elements
|**Demo_Func_Callback_Simulator.py** | For the Raspberry Pi crowd. Event loop that simulates traditional GUI callback functions should you already have an architecture that uses them |**Demo_Func_Callback_Simulator.py** | For the Raspberry Pi crowd. Event loop that simulates traditional GUI callback functions should you already have an architecture that uses them
|**Demo_GoodColors.py** | Using some of the pre-defined PySimpleGUI individual colors |**Demo_GoodColors.py** | Using some of the pre-defined PySimpleGUI individual colors
|**Demo_HowDoI.py** | This is a utility to be experienced! It will change how you code |**Demo_HowDoI.py** | This is a utility to be experienced! It will change how you code
|**Demo_Img_Viewer.py** | Display jpg, png,tiff, bmp files
|**Demo_Keyboard.py** | Using blocking keyboard events |**Demo_Keyboard.py** | Using blocking keyboard events
|**Demo_Keyboard_Realtime.py** | Using non-blocking / realtime keyboard events |**Demo_Keyboard_Realtime.py** | Using non-blocking / realtime keyboard events
|**Demo_Machine_Learning.py** | A sample Machine Learning front end |**Demo_Machine_Learning.py** | A sample Machine Learning front end
@ -1819,13 +1908,18 @@ Use the example programs as a starting basis for your GUI. Copy, paste, modify
|**Demo_Media_Player.py** | Non-blocking form with a media player layout. Demonstrates button graphics, Update method |**Demo_Media_Player.py** | Non-blocking form with a media player layout. Demonstrates button graphics, Update method
|**Demo_MIDI_Player.py** | GUI wrapper for Mido MIDI package. Functional MIDI player that controls attached MIDI devices |**Demo_MIDI_Player.py** | GUI wrapper for Mido MIDI package. Functional MIDI player that controls attached MIDI devices
|**Demo_NonBlocking_Form.py** | a basic async form |**Demo_NonBlocking_Form.py** | a basic async form
|** Demo_OpenCV.py** | Integrated with OpenCV
|** Demo_Password_Login** | Password protection using SHA1
|**Demo_PDF_Viewer.py** | Submitted by a user! Previews PDF documents. Uses keyboard input & mouse scrollwheel to navigate |**Demo_PDF_Viewer.py** | Submitted by a user! Previews PDF documents. Uses keyboard input & mouse scrollwheel to navigate
|**Demo_Pi_LEDs.py** | Control GPIO using buttons
|**Demo_Pi_Robotics.py** | Simulated robot control using realtime buttons |**Demo_Pi_Robotics.py** | Simulated robot control using realtime buttons
|**Demo_PNG_Vierwer.py** | Uses Image Element to display PNG files |**Demo_PNG_Vierwer.py** | Uses Image Element to display PNG files
|**Demo_Recipes.py** | A collection of various Recipes. Note these are not the same as the Recipes in the Recipe Cookbook |**Demo_Recipes.py** | A collection of various Recipes. Note these are not the same as the Recipes in the Recipe Cookbook
|**Demo_Script_Launcher.py** | Demonstrates one way of adding a front-end onto several command line scripts |**Demo_Script_Launcher.py** | Demonstrates one way of adding a front-end onto several command line scripts
|**Demo_Script_Parameters.py** | Add a 1-line GUI to the front of your previously command-line only scripts |**Demo_Script_Parameters.py** | Add a 1-line GUI to the front of your previously command-line only scripts
|**Demo_Tabbed_Form.py** | Using the Tab feature |**Demo_Tabbed_Form.py** | Using the Tab feature
|**Demo_Table_Simulation.py** | Use input fields to display and edit tables
|**Demo_Timer.py** | Simple non-blocking form
## Packages Used In Demos ## Packages Used In Demos
@ -1931,6 +2025,7 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
| 2.11.0 | Aug 29, 2018 - Lots of little changes that are needed for the demo programs to work. Buttons have their own default element size, fix for Mac default button color, padding support for all elements, option to immediately return if list box gets selected, FilesBrowse button, Canvas Element, Frame Element, Slider resolution option, Form.Refresh method, better text wrapping, 'SystemDefault' look and feel settin | 2.11.0 | Aug 29, 2018 - Lots of little changes that are needed for the demo programs to work. Buttons have their own default element size, fix for Mac default button color, padding support for all elements, option to immediately return if list box gets selected, FilesBrowse button, Canvas Element, Frame Element, Slider resolution option, Form.Refresh method, better text wrapping, 'SystemDefault' look and feel settin
| 2.20.0 | Sept 4, 2018 - Some sizable features this time around of interest to advanced users. Renaming of the MsgBox functions to Popup. Renaming GetFile, etc, to PopupGetFile. High-level windowing capabilities start with Popup, PopupNoWait/PopupNonblocking, PopupNoButtons, default icon, change_submits option for Listbox/Combobox/Slider/Spin/, New OptionMenu element, updating elements after shown, system defaul color option for progress bars, new button type (Dummy Button) that only closes a window, SCROLLABLE Columns!! (yea, playing in the Big League now), LayoutAndShow function removed, form.Fill - bulk updates to forms, FindElement - find element based on key value (ALL elements have keys now), no longer use grid packing for row elements (a potentially huge change), scrolled text box sizing changed, new look and feel themes (Dark, Dark2, Black, Tan, TanBlue, DarkTanBlue, DarkAmber, DarkBlue, Reds, Green) | 2.20.0 | Sept 4, 2018 - Some sizable features this time around of interest to advanced users. Renaming of the MsgBox functions to Popup. Renaming GetFile, etc, to PopupGetFile. High-level windowing capabilities start with Popup, PopupNoWait/PopupNonblocking, PopupNoButtons, default icon, change_submits option for Listbox/Combobox/Slider/Spin/, New OptionMenu element, updating elements after shown, system defaul color option for progress bars, new button type (Dummy Button) that only closes a window, SCROLLABLE Columns!! (yea, playing in the Big League now), LayoutAndShow function removed, form.Fill - bulk updates to forms, FindElement - find element based on key value (ALL elements have keys now), no longer use grid packing for row elements (a potentially huge change), scrolled text box sizing changed, new look and feel themes (Dark, Dark2, Black, Tan, TanBlue, DarkTanBlue, DarkAmber, DarkBlue, Reds, Green)
| 2.30.0 | Sept 6, 2018 - Calendar Chooser (button), borderless windows, load/save form to disk | 2.30.0 | Sept 6, 2018 - Calendar Chooser (button), borderless windows, load/save form to disk
| 3.0.0 | Sept 7, 2018 - The "fix for poor choice of 2.x numbers" release. Color Chooser (button), "grab anywhere" windows are on by default, disable combo boxes, Input Element text justification (last part needed for 'tables'), Image Element changes to support OpenCV?, PopupGetFile and PopupGetFolder have better no_window option
### Release Notes ### Release Notes
@ -1950,11 +2045,19 @@ Listboxes are still without scrollwheels. The mouse can drag to see more items.
2.9 COLUMNS! This is the biggest feature and had the biggest impact on the code base. It was a difficult feature to add, but it was worth it. Can now make even more layouts. Almost any layout is possible with this addition. 2.9 COLUMNS! This is the biggest feature and had the biggest impact on the code base. It was a difficult feature to add, but it was worth it. Can now make even more layouts. Almost any layout is possible with this addition.
.................. insert releases 2.9 to 2.30 .................
3.0 We've come a long way baby! Time for a major revision bump. One reason is that the numbers started to confuse people the latest release was 2.30, but some people read it as 2.3 and thought it went backwards. I kinda messed up the 2.x series of numbers, so why not start with a clean slate. A lot has happened anyway so it's well earned.
One change that will set PySimpleGUI apart is the parlor trick of being able to move the window by clicking on it anywhere. This is turned on by default. It's not a common way to interact with windows. Normally you have to move using the titlebar. Not so with PySimpleGUI. Now you can drag using any part of the window. You will want to turn this off for windows with sliders. This feature is enabled in the FlexForm call.
Related to the Grab Anywhere feature is the no_titlebar option, again found in the call to FlexForm. Your window will be a spiffy, borderless window. It's a really interesting effect. Slight problem is that you do not have an icon on the taskbar with these types of windows, so if you don't supply a button to close the window, there's no way to close it other than task manager.
### Upcoming ### Upcoming
Make suggestions people! Future release features Make suggestions people! Future release features
Port to other graphic engines. Hook up the front-end interface to a backend other than tkinter. Qt, WxPython, etc. Port to other graphic engines. Hook up the front-end interface to a backend other than tkinter. Qt, WxPython, etc. WxPython is higher priority.
@ -1986,6 +2089,8 @@ It seemed quite natural to use Python's powerful list constructs when possible.
**Dictionaries** **Dictionaries**
Want to view your form's results as a dictionary instead of a list... no problem, just use the `key` keyword on your elements. For complex forms with a lot of values that need to be changed frequently, this is by far the best way of consuming the results. Want to view your form's results as a dictionary instead of a list... no problem, just use the `key` keyword on your elements. For complex forms with a lot of values that need to be changed frequently, this is by far the best way of consuming the results.
You can also look up elements using their keys. This is an excellent way to update elements in reaction to another element. Call `form.FindElement(key)` to get the Element.
## Author ## Author
MikeTheWatchGuy MikeTheWatchGuy
@ -2034,3 +2139,4 @@ In the hands of a competent programmer, this tool is **amazing**. It's a must-
The PySimpleGUI window that the results are shown in is an 'input' field which means you can copy and paste the results right into your code. The PySimpleGUI window that the results are shown in is an 'input' field which means you can copy and paste the results right into your code.