Readme update for version 2.4 features. Button images
After Width: | Height: | Size: 8.0 KiB |
After Width: | Height: | Size: 3.4 KiB |
After Width: | Height: | Size: 7.9 KiB |
After Width: | Height: | Size: 7.4 KiB |
After Width: | Height: | Size: 7.8 KiB |
After Width: | Height: | Size: 7.7 KiB |
After Width: | Height: | Size: 7.6 KiB |
|
@ -1,11 +0,0 @@
|
||||||
import PySimpleGUI as sg
|
|
||||||
|
|
||||||
sg.MsgBox('Title', 'My first message... Is the length the same?')
|
|
||||||
rc, number = sg.GetTextBox('Title goes here', 'Enter a number')
|
|
||||||
if not rc:
|
|
||||||
sg.MsgBoxError('You have cancelled')
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
msg = '\n'.join([f'{i}' for i in range(0,int(number))])
|
|
||||||
|
|
||||||
sg.ScrolledTextBox(msg, height=10)
|
|
|
@ -0,0 +1,60 @@
|
||||||
|
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=(20, 3), 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=(20, 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,
|
||||||
|
size=(10, 2), font=("Helvetica", 15)), 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,
|
||||||
|
font=("Helvetica", 15), size=(10, 2)), 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,
|
||||||
|
size=(10, 2), font=("Helvetica", 15)), 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,
|
||||||
|
size=(10, 2), font=("Helvetica", 15))],
|
||||||
|
[sg.Text('Treble', font=("Helvetica", 15), size=(6, 1)),
|
||||||
|
sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15)),
|
||||||
|
sg.Text(' ' * 5),
|
||||||
|
sg.Text('Volume', font=("Helvetica", 15), size=(7, 1)),
|
||||||
|
sg.Slider(range=(-10, 10), default_value=0, size=(10, 20), orientation='vertical', font=("Helvetica", 15))],
|
||||||
|
]
|
||||||
|
|
||||||
|
# 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()
|
168
readme.md
|
@ -1,16 +1,19 @@
|
||||||
|
|
||||||
![logo01 2 _2](https://user-images.githubusercontent.com/13696193/43082437-1252511a-8e62-11e8-9150-fc227cc56cfe.png)
|
![logo01 2 _2](https://user-images.githubusercontent.com/13696193/43082437-1252511a-8e62-11e8-9150-fc227cc56cfe.png)
|
||||||
|
|
||||||
[![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) since Jul 11, 2018
|
[![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) since Jul 11, 2018
|
||||||
# PySimpleGUI
|
# PySimpleGUI
|
||||||
(Ver 2.3)
|
(Ver 2.4)
|
||||||
|
|
||||||
This really is a simple GUI, but also powerfully customizable.
|
This really is a simple GUI, but also powerfully customizable.
|
||||||
|
|
||||||
import PySimpleGUI as SG
|
|
||||||
|
|
||||||
SG.MsgBox('My Message Box', 'This is the shortest GUI program ever!')
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
![snap0102](https://user-images.githubusercontent.com/13696193/42781058-1d28d9fa-8913-11e8-847e-5c2afc16ca4c.jpg)
|
sg.MsgBox('Hello From PySimpleGUI!', 'This is the shortest GUI program ever!')
|
||||||
|
|
||||||
|
|
||||||
|
![snap0136](https://user-images.githubusercontent.com/13696193/43162494-33095ece-8f59-11e8-86de-b6d8bcc5a52f.jpg)
|
||||||
|
|
||||||
Add a Progress Meter to your code with ONE LINE of code
|
Add a Progress Meter to your code with ONE LINE of code
|
||||||
|
|
||||||
|
@ -18,9 +21,13 @@ Add a Progress Meter to your code with ONE LINE of code
|
||||||
|
|
||||||
![progress meter 2](https://user-images.githubusercontent.com/13696193/42695896-a37eff5c-8684-11e8-8fbb-3d756655a44b.jpg)
|
![progress meter 2](https://user-images.githubusercontent.com/13696193/42695896-a37eff5c-8684-11e8-8fbb-3d756655a44b.jpg)
|
||||||
|
|
||||||
|
Or how about a media player GUI with custom buttons... in 30 lines of code.
|
||||||
|
|
||||||
|
![media file player](https://user-images.githubusercontent.com/13696193/43161977-9ee7cace-8f57-11e8-8ff8-3ea24b69dab9.jpg)
|
||||||
|
|
||||||
I was frustrated by having to deal with the dos prompt when I had a powerful Windows machine right in front of me. Why is it SO difficult to do even the simplest of input/output to a window in Python??
|
I was frustrated by having to deal with the dos prompt when I had a powerful Windows machine right in front of me. Why is it SO difficult to do even the simplest of input/output to a window in Python??
|
||||||
|
|
||||||
There are a number of 'easy to use' Python GUIs, but they're **very** limiting. PySimpleGUI takes the best of packages like `EasyGUI`(no longer maintained) and `WxSimpleGUI` (a great package, but limited). The primary difference between these and PySimpleGUI is that in addition to getting those simple Message Boxes you also get the ability to make your own forms that are highly customizeable. Don't like the standard Message Box? Then make your own!
|
There are a number of 'easy to use' Python GUIs, but they're **very** limiting. PySimpleGUI takes the best of packages like `EasyGUI`and `WxSimpleGUI` , both really handy but limited. The primary difference between these and PySimpleGUI is that in addition to getting the simple Message Boxes you also get the ability to make your own forms that are highly customizeable. Don't like the standard Message Box? Then make your own!
|
||||||
|
|
||||||
Every call has optional parameters so that you can change the look and feel. Don't like the button color? It's easy to change by adding a button_color parameter to your widget.
|
Every call has optional parameters so that you can change the look and feel. Don't like the button color? It's easy to change by adding a button_color parameter to your widget.
|
||||||
|
|
||||||
|
@ -336,24 +343,27 @@ It's both not enjoyable nor helpful to immediately jump into tweaking each and e
|
||||||
# Copy these design patterns!
|
# Copy these design patterns!
|
||||||
## Pattern 1 - With Context Manager
|
## Pattern 1 - With Context Manager
|
||||||
|
|
||||||
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')],
|
with sg.FlexForm('SHA-1 & 256 Hash', auto_size_text=True) as form:
|
||||||
[SG.InputText(), SG.FileBrowse()],
|
form_rows = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
|
||||||
[SG.Submit(), SG.Cancel()]]
|
[sg.InputText(), sg.FileBrowse()],
|
||||||
button, (source_filename, ) = form.LayoutAndShow(form_rows)
|
[sg.Submit(), sg.Cancel()]]
|
||||||
|
button, (source_filename,) = form.LayoutAndRead(form_rows)
|
||||||
|
|
||||||
## Pattern 2 - No Context Manager
|
## Pattern 2 - No Context Manager
|
||||||
|
|
||||||
form = SG.FlexForm('SHA-1 & 256 Hash', auto_size_text=True)
|
|
||||||
form_rows = [[SG.Text('SHA-1 and SHA-256 Hashes for the file')],
|
form = sg.FlexForm('SHA-1 & 256 Hash', auto_size_text=True)
|
||||||
[SG.InputText(), SG.FileBrowse()],
|
form_rows = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
|
||||||
[SG.Submit(), SG.Cancel()]]
|
[sg.InputText(), sg.FileBrowse()],
|
||||||
button, (source_filename,) = form.LayoutAndShow(form_rows)
|
[sg.Submit(), sg.Cancel()]]
|
||||||
|
button, (source_filename,) = form.LayoutAndRead(form_rows)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
These 2 design patters both produce this custom form:
|
These 2 design patters both produce this custom form:
|
||||||
|
|
||||||
![sha hash](https://user-images.githubusercontent.com/13696193/42603149-a56acf3a-853a-11e8-91de-771efd3a65a8.jpg)
|
![snap0134](https://user-images.githubusercontent.com/13696193/43162410-e7775466-8f58-11e8-8d6a-da4772c00dd8.jpg)
|
||||||
|
|
||||||
It's important to use the "with" context manager so that resources are freed as quickly as possible, using the currently executing thread. PySimpleGUI uses `tkinter`. `tkinter` is very picky about who releases objects and when. The `with` takes care of disposing of everything properly for you.
|
It's important to use the "with" context manager so that resources are freed as quickly as possible, using the currently executing thread. PySimpleGUI uses `tkinter`. `tkinter` is very picky about who releases objects and when. The `with` takes care of disposing of everything properly for you.
|
||||||
|
|
||||||
|
@ -378,7 +388,7 @@ Now we're on the second row of the form. On this row there are 2 elements. The
|
||||||
|
|
||||||
The last line of the `form_rows` variable assignment contains a Submit and a Cancel Button. These are buttons that will cause a form to return its value to the caller.
|
The last line of the `form_rows` variable assignment contains a Submit and a Cancel Button. These are buttons that will cause a form to return its value to the caller.
|
||||||
|
|
||||||
(button, (source_filename, )) = form.LayoutAndShow(form_rows)
|
(button, (source_filename, )) = form.LayoutAndRead(form_rows)
|
||||||
This is the code that **displays** the form, collects the information and returns the data collected. In this example we have a button return code and only 1 input field
|
This is the code that **displays** the form, collects the information and returns the data collected. In this example we have a button return code and only 1 input field
|
||||||
|
|
||||||
|
|
||||||
|
@ -393,21 +403,21 @@ This is the code that **displays** the form, collects the information and return
|
||||||
|
|
||||||
Each of the Elements that are Input Elements will have a value in the list of return values. You can unpack your GUI directly into the variables you want to use.
|
Each of the Elements that are Input Elements will have a value in the list of return values. You can unpack your GUI directly into the variables you want to use.
|
||||||
|
|
||||||
button, (filename, folder1, folder2, should_overwrite) = form.LayoutAndShow(form_rows)
|
button, (filename, folder1, folder2, should_overwrite) = form.LayoutAndRead(form_rows)
|
||||||
|
|
||||||
Or, you can unpack the return results separately.
|
Or, you can unpack the return results separately.
|
||||||
|
|
||||||
button, values = form.LayoutAndShow(form_rows)
|
button, values = form.LayoutAndRead(form_rows)
|
||||||
filename, folder1, folder2, should_overwrite = values
|
filename, folder1, folder2, should_overwrite = values
|
||||||
|
|
||||||
If you have a SINGLE value being returned, it is written this way:
|
If you have a SINGLE value being returned, it is written this way:
|
||||||
|
|
||||||
button, (value1,) = form.LayoutAndShow(form_rows)
|
button, (value1,) = form.LayoutAndRead(form_rows)
|
||||||
|
|
||||||
|
|
||||||
Another way of parsing the return values is to store the list of values into a variable representing the list of values.
|
Another way of parsing the return values is to store the list of values into a variable representing the list of values.
|
||||||
|
|
||||||
button, value_list = form.LayoutAndShow(form_rows)
|
button, value_list = form.LayoutAndRead(form_rows)
|
||||||
value1 = value_list[0]
|
value1 = value_list[0]
|
||||||
value2 = value_list[1]
|
value2 = value_list[1]
|
||||||
...
|
...
|
||||||
|
@ -897,6 +907,26 @@ layout = [[SG.SimpleButton('My Button')]]
|
||||||
|
|
||||||
All buttons can have their text changed by changing the `button_text` variable.
|
All buttons can have their text changed by changing the `button_text` variable.
|
||||||
|
|
||||||
|
**Button Images**
|
||||||
|
Now this is an exciting feature not found in many simplified packages.... images on buttons! You can make a pretty spiffy user interface with the help of a few button images.
|
||||||
|
|
||||||
|
Your button images need to be in PNG or GIF format. When you make a button with an image, set the button background to the same color as the background. There's a button color TRANSPARENT_BUTTON that you can set your button color to.
|
||||||
|
|
||||||
|
This example comes from the `Demo Media Player.py` example program. Because it's a non-blocking button, it's defined as `ReadFormButton`. You also put images on blocking buttons by using `SimpleButton`.
|
||||||
|
|
||||||
|
|
||||||
|
sg.ReadFormButton('Restart Song', button_color=sg.TRANSPARENT_BUTTON,
|
||||||
|
image_filename=image_restart, image_size=(50, 50), image_subsample=2, border_width=0)
|
||||||
|
|
||||||
|
Three parameters are used for button images.
|
||||||
|
|
||||||
|
image_filename - Filename. Can be a relative path
|
||||||
|
image_size - Size of image file in pixels
|
||||||
|
image_subsample - Amount to divide the size by. 2 means your image will be 1/2 the size. 3 means 1/3
|
||||||
|
|
||||||
|
This is one you'll have to experiment with at this point. Not up for an exhaustive explanation.
|
||||||
|
|
||||||
|
|
||||||
**File Types**
|
**File Types**
|
||||||
The `FileBrowse` button has an additional setting named `file_types`. This variable is used to filter the files shown in the file dialog box. The default value for this setting is
|
The `FileBrowse` button has an additional setting named `file_types`. This variable is used to filter the files shown in the file dialog box. The default value for this setting is
|
||||||
|
|
||||||
|
@ -979,8 +1009,6 @@ Here's a complete solution for a chat-window using an Async form with an Output
|
||||||
break
|
break
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Tabbed Forms
|
## Tabbed Forms
|
||||||
Tabbed forms are shown using the `ShowTabbedForm` call. The call has the format
|
Tabbed forms are shown using the `ShowTabbedForm` call. The call has the format
|
||||||
|
|
||||||
|
@ -1061,9 +1089,11 @@ We're going to build an app that does the latter. It's going to update our form
|
||||||
The basic flow and functions you will be calling are:
|
The basic flow and functions you will be calling are:
|
||||||
Setup
|
Setup
|
||||||
|
|
||||||
|
|
||||||
form = FlexForm()
|
form = FlexForm()
|
||||||
form.AddRows(form_rows)
|
form_rows = .....
|
||||||
form.Show(non_blocking = True)
|
form.LayoutAndRead(form_rows, non_blocking=True)
|
||||||
|
|
||||||
|
|
||||||
Periodic refresh
|
Periodic refresh
|
||||||
|
|
||||||
|
@ -1072,23 +1102,37 @@ If you need to close the form
|
||||||
|
|
||||||
form.CloseNonBlockingForm()
|
form.CloseNonBlockingForm()
|
||||||
|
|
||||||
Rather than the usual `form.LayoutAndShow()` call, we're manually adding the rows (doing the layout) and then showing the form. After the form is shown, you simply call `form.ReadNonBlocking()` every now and then.
|
Rather than the usual `form.LayoutAndRead()` call, we're manually adding the rows (doing the layout) and then showing the form. After the form is shown, you simply call `form.ReadNonBlocking()` every now and then.
|
||||||
|
|
||||||
When you are ready to close the form (assuming the form wasn't closed by the user or a button click) you simply call `form.CloseNonBlockingForm()`
|
When you are ready to close the form (assuming the form wasn't closed by the user or a button click) you simply call `form.CloseNonBlockingForm()`
|
||||||
|
|
||||||
**Example - Running timer that updates**
|
**Example - Running timer that updates**
|
||||||
We're going to make a form and update one of the elements of that form every .01 seconds. Here's the entire code to do that.
|
See the sample code on the GitHub named Demo Media Player for another example of Async Forms. We're going to make a form and update one of the elements of that form every .01 seconds. Here's the entire code to do that.
|
||||||
|
|
||||||
with SG.FlexForm('Running Timer', auto_size_text=True) as form:
|
|
||||||
output_element = SG.Text('', size=(8, 2), font=('Helvetica', 20))
|
import PySimpleGUI as sg
|
||||||
form_rows = [[SG.Text('Non-blocking GUI with updates')],
|
import time
|
||||||
|
|
||||||
|
# form that doesn't block
|
||||||
|
# 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],
|
[output_element],
|
||||||
[SG.SimpleButton('Quit')]]
|
[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)
|
||||||
|
|
||||||
form.AddRows(form_rows)
|
#
|
||||||
form.Show(non_blocking=True)
|
# Some place later in your code...
|
||||||
for i in range(1, 100):
|
# You need to perform a ReadNonBlocking on your form every now and then or
|
||||||
output_element.Update('{:02d}:{:02d}.{:02d}'.format(*divmod(int(i/100), 60), i%100))
|
# 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()
|
button, values = form.ReadNonBlocking()
|
||||||
if values is None or button == 'Quit':
|
if values is None or button == 'Quit':
|
||||||
break
|
break
|
||||||
|
@ -1096,6 +1140,8 @@ We're going to make a form and update one of the elements of that form every .01
|
||||||
else:
|
else:
|
||||||
form.CloseNonBlockingForm()
|
form.CloseNonBlockingForm()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
What we have here is the same sequence of function calls as in the description. Get a form, add rows to it, show the form, and then refresh it every now and then.
|
What we have here is the same sequence of function calls as in the description. Get a form, add rows to it, show the form, and then refresh it every now and then.
|
||||||
|
|
||||||
The new thing in this example is the call use of the Update method for the Text Element. The first thing we do inside the loop is "update" the text element that we made earlier. This changes the value of the text field on the form. The new value will be displayed when `form.ReadNonBlocking()` is called.
|
The new thing in this example is the call use of the Update method for the Text Element. The first thing we do inside the loop is "update" the text element that we made earlier. This changes the value of the text field on the form. The new value will be displayed when `form.ReadNonBlocking()` is called.
|
||||||
|
@ -1126,8 +1172,42 @@ To get a random color pair call `PySimpleGUI.GetRandomColorPair`. This returns
|
||||||
that color's compliment.
|
that color's compliment.
|
||||||
sprint
|
sprint
|
||||||
|
|
||||||
**sprint**
|
**Debug Output**
|
||||||
Call `sprint` with as many parameters as you want and it'll print them all out in a `ScrolledTextBox`. This is simply a function pointing to `PySimpleGUI.ScrolledTextBox`.
|
Be sure and check out the EasyPrint (Print) function described in the high-level API section. Leave your code the way it is, route your stdout and stderror to a scrolling window.
|
||||||
|
|
||||||
|
For a fun time, add this line to the top of your script
|
||||||
|
|
||||||
|
import PySimpleGUI as sg
|
||||||
|
print = sg.Print
|
||||||
|
|
||||||
|
|
||||||
|
**Look and Feel**
|
||||||
|
Dial in the look and feel that you like with the `SetOptions` function. You can change all of the defaults in one function call. One line of code to customize the entire GUI.
|
||||||
|
|
||||||
|
**ObjToString**
|
||||||
|
Ever wanted to easily display an objects contents easily? Use ObjToString to get a nicely formatted recursive walk of your objects.
|
||||||
|
This statement:
|
||||||
|
|
||||||
|
print(sg.ObjToSting(x))
|
||||||
|
|
||||||
|
And this was the output
|
||||||
|
|
||||||
|
<class '__main__.X'>
|
||||||
|
abc = abc
|
||||||
|
attr12 = 12
|
||||||
|
c = <class '__main__.C'>
|
||||||
|
b = <class '__main__.B'>
|
||||||
|
a = <class '__main__.A'>
|
||||||
|
attr1 = 1
|
||||||
|
attr2 = 2
|
||||||
|
attr3 = three
|
||||||
|
attr10 = 10
|
||||||
|
attrx = x
|
||||||
|
|
||||||
|
You'll quickly wonder how you ever coded without it.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
---
|
---
|
||||||
# Known Issues
|
# Known Issues
|
||||||
|
@ -1154,18 +1234,18 @@ A MikeTheWatchGuy production... entirely responsible for this code.... unless it
|
||||||
| 2.1.1 | July 18, 2018 - Global settings exposed, fixes
|
| 2.1.1 | July 18, 2018 - Global settings exposed, fixes
|
||||||
| 2.2.0| July 20, 2018 - Image Elements, Print output
|
| 2.2.0| July 20, 2018 - Image Elements, Print output
|
||||||
| 2.3.0 | July 23, 2018 - Changed form.Read return codes, Slider Elements, Listbox element. Renamed some methods but left legacy calls in place for now.
|
| 2.3.0 | July 23, 2018 - Changed form.Read return codes, Slider Elements, Listbox element. Renamed some methods but left legacy calls in place for now.
|
||||||
| 2.4.0 | July XX, 2018 - Planned release. Button images.
|
| 2.4.0 | July 24, 2018 - Button images. Fixes so can run on Raspberry Pi
|
||||||
|
|
||||||
### Release Notes
|
### Release Notes
|
||||||
2.3 - Sliders, Listbox's and Image elements (oh my!)
|
2.3 - Sliders, Listbox's and Image elements (oh my!)
|
||||||
|
|
||||||
If using Progress Meters, avoid cancelling them when you have another window open. It could lead to future windows being blank. It's being worked on.
|
If using Progress Meters, avoid cancelling them when you have another window open. It could lead to future windows being blank. It's being worked on.
|
||||||
|
|
||||||
|
New debug printing capability. `sg.Print`
|
||||||
|
|
||||||
### Upcoming
|
### Upcoming
|
||||||
Make suggestions people! Future release features
|
Make suggestions people! Future release features
|
||||||
|
|
||||||
Button images. Ability to replace boring rectangular buttons with your own images.
|
|
||||||
|
|
||||||
Columns. How multiple columns would be specified in the SDK interface are still being designed.
|
Columns. How multiple columns would be specified in the SDK interface are still being designed.
|
||||||
|
|
||||||
Progress Meters - Replace custom meter with tkinter meter.
|
Progress Meters - Replace custom meter with tkinter meter.
|
||||||
|
@ -1216,11 +1296,3 @@ For Python questions, I simply start my query with 'Python'. Let's say you forg
|
||||||
In the hands of a competent programmer, this tool is **amazing**. It's a must-try kind of program that has completely changed my programming process. I'm not afraid of asking for help! You just have to be smart about using what you find.
|
In the hands of a competent programmer, this tool is **amazing**. It's a must-try kind of program that has completely changed my programming process. I'm not afraid of asking for help! You just have to be smart about using what you find.
|
||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|