Merge pull request #228 from MikeTheWatchGuy/Dev-latest

CPU Widget made more efficient, new Table Element settings, Updated P…
This commit is contained in:
MikeTheWatchGuy 2018-09-15 15:46:15 -04:00 committed by GitHub
commit 4c47ac4dda
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 118 additions and 109 deletions

View File

@ -17,7 +17,7 @@ import operator
invalid command name "1616802625480StopMove"
"""
# globale used to communicate with thread.. yea yea... it's working fine
g_interval = 1
g_cpu_percent = 0
g_procs = None
@ -38,11 +38,11 @@ def main():
sg.ChangeLookAndFeel('Black')
form_rows = [[sg.Text('', size=(8,1), font=('Helvetica', 20),text_color=sg.YELLOWS[0], justification='center', key='text')],
[sg.Text('', size=(30, 8), font=('Courier New', 12),text_color='white', justification='left', key='processes')],
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15,0), 0)), sg.Spin([x+1 for x in range(10)], 1, key='spin')],
]
[sg.Exit(button_color=('white', 'firebrick4'), pad=((15,0), 0)), sg.Spin([x+1 for x in range(10)], 1, key='spin')],]
form = sg.FlexForm('CPU Utilization', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True)
form.Layout(form_rows)
# start cpu measurement thread
thread = Thread(target=CPU_thread,args=(None,))
thread.start()
# ---------------- main loop ----------------
@ -58,9 +58,11 @@ def main():
except:
g_interval = 1
# cpu_percent = psutil.cpu_percent(interval=interval)
# cpu_percent = psutil.cpu_percent(interval=interval) # if don't wan to use a task
cpu_percent = g_cpu_percent
time.sleep(.1)
# let the GUI run ever 700ms regardless of CPU polling time. makes window be more responsive
time.sleep(.7)
display_string = ''
if g_procs:

View File

@ -15,8 +15,8 @@ if filename is not None:
sg.SetOptions(element_padding=(0, 0))
col_layout = [[sg.Table(values=data, headings=[x for x in range(len(data[0]))], max_col_width=8,
auto_size_columns=False, justification='right', size=(8, len(data)))]]
col_layout = [[sg.Table(values=data[1:][:], headings=[data[0][x] for x in range(len(data[0]))], max_col_width=25,
auto_size_columns=True, display_row_numbers=True, justification='right', size=(None, len(data)))]]
layout = [[sg.Column(col_layout, size=(1200,600), scrollable=True)],]

40
Demo_Table_Pandas.py Normal file
View File

@ -0,0 +1,40 @@
import pandas as pd
import PySimpleGUI as sg
"""
Display a CSV file using Table Element and Pandas
Thank you to for writing this demo
"""
def table_example():
filename = sg.PopupGetFile('filename to open', no_window=True, file_types=(("CSV Files", "*.csv"),))
# --- populate table with file contents --- #
data = []
header_list = []
if filename is not None:
try:
df = pd.read_csv(filename, sep=',', engine='python') # read everything else into a list of rows
header_list = df.columns.tolist()
data = df.values.tolist()
# print(data)
except:
sg.PopupError('Error reading file')
exit(69)
sg.SetOptions(element_padding=(0, 0))
col_layout = [[sg.Table(values=data, headings=header_list, max_col_width=20,
auto_size_columns=True, justification='right', size=(None, len(data)))]]
layout = [[sg.Column(col_layout, size=(1200, 600), scrollable=True)]]
form = sg.FlexForm('Table', grab_anywhere=False)
b, v = form.LayoutAndRead(layout)
exit(69)
table_example()

View File

@ -1541,7 +1541,7 @@ class Menu(Element):
# Table #
# ---------------------------------------------------------------------- #
class Table(Element):
def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=10, select_mode=None, scrollable=None, font=None, justification='left', text_color=None, background_color=None, scale=(None, None), size=(None, None), pad=None, key=None):
def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, scrollable=None, font=None, justification='right', text_color=None, background_color=None, scale=(None, None), size=(None, None), pad=None, key=None):
self.Values = values
self.ColumnHeadings = headings
self.ColumnsToDisplay = visible_column_map
@ -1555,6 +1555,7 @@ class Table(Element):
self.Scrollable = scrollable
self.InitialState = None
self.SelectMode = select_mode
self.DisplayRowNumbers = display_row_numbers
self.TKTreeview = None
super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, scale=scale, font=font, size=size, pad=pad, key=key)
@ -2683,7 +2684,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
column_widths[i] = col_len
except:
column_widths[i] = col_len
if element.ColumnsToDisplay is None:
displaycolumns = element.ColumnHeadings
else:
@ -2691,14 +2691,16 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
for i, should_display in enumerate(element.ColumnsToDisplay):
if should_display:
displaycolumns.append(element.ColumnHeadings[i])
displaycolumns = ['Row',] + displaycolumns
column_headings = ['Row',] + element.ColumnHeadings
# scrollable_frame = TkScrollableFrame(tk_row_frame)
column_headings= element.ColumnHeadings
if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns
displaycolumns = ['Row',] + displaycolumns
column_headings = ['Row',] + element.ColumnHeadings
element.TKTreeview = ttk.Treeview(tk_row_frame, columns=column_headings,
displaycolumns=displaycolumns, show='headings', height=height, selectmode=element.SelectMode)
treeview = element.TKTreeview
treeview.heading('Row', text='Row') # make a dummy heading
treeview.column('Row', width=50, anchor=anchor)
if element.DisplayRowNumbers:
treeview.heading('Row', text='Row') # make a dummy heading
treeview.column('Row', width=50, anchor=anchor)
for i, heading in enumerate(element.ColumnHeadings):
treeview.heading(heading, text=heading)
if element.AutoSizeColumns:
@ -2708,13 +2710,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form):
width = element.ColumnWidths[i]
except:
width = element.DefaultColumnWidth
treeview.column(heading, width=width*CharWidthInPixels(), anchor=anchor)
for i, value in enumerate(element.Values):
value = [i] + value
if element.DisplayRowNumbers:
value = [i] + value
id = treeview.insert('', 'end', text=value, values=value)
# print(id)
# for i in range(5):
# treeview.insert(id, 'end', text=value, values=i)
if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT:
element.TKTreeview.configure(background=element.BackgroundColor)
# scrollable_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both')

View File

@ -327,15 +327,17 @@ This recipe implements a remote control interface for a robot. There are 4 dire
---------
## Easy Progress Meter
## OneLineProgressMeter
This recipe shows just how easy it is to add a progress meter to your code.
![progress meter 6](https://user-images.githubusercontent.com/13696193/43955982-73b33b38-9c70-11e8-8b07-cc1473a58a73.jpg)
![onelineprogressmeter](https://user-images.githubusercontent.com/13696193/45589254-bd285900-b8f0-11e8-9122-b43f06bf074d.jpg)
import PySimpleGUI as sg
for i in range(1000):
sg.EasyProgressMeter('Easy Meter Example', i+1, 1000)
sg.OneLineProgressMeter('One Line Meter Example', i+1, 1000, 'mymeter')
-----

View File

@ -11,7 +11,7 @@
# PySimpleGUI
(Ver 3.2.0)
(Ver 3.3.0)
@ -71,7 +71,7 @@ Perhaps you're looking for a way to interact with your **Raspberry Pi** in a mor
In addition to a primary GUI, you can add a Progress Meter to your code with ONE LINE of code. Slide this into any of your `for` loops and get a nice meter like this:
EasyProgressMeter('My meter title', current_value, max value)
OneLineProgressMeter('My meter title', current_value, max value, 'key')
![easyprogressmeter](https://user-images.githubusercontent.com/13696193/44960065-83099100-aec6-11e8-8aa8-96e4b100a0e4.jpg)
@ -199,7 +199,12 @@ You will see a number of different styles of buttons, data entry fields, etc, in
- The SDK calls collapse down into a single line of Python code that presents a custom GUI and returns values
- Linear programming instead of callbacks
#### Lofty Goals
>
>
> Change Python
The expectation is not that ***this*** package will become part of the Python Standard Library. The hope is that Python will become ***the*** go-to language for creating GUI programs that run on Windows, Mac, and Linux. There is a gap in the Python GUI solution. Fill that gap and who knows what will happen. Maybe there's no "there there". Or maybe an easy to use GUI API will enable Python to dominate yet another computing discipline like it has so many others. I want to find out.
-----
@ -413,13 +418,14 @@ The window created to get a folder name looks the same as the get a file name.
![popupgetfolder](https://user-images.githubusercontent.com/13696193/44957861-45484080-aea5-11e8-926c-cf607a45251c.jpg)
#### Progress Meter!
#### Progress Meters!
We all have loops in our code. 'Isn't it joyful waiting, watching a counter scrolling past in a text window? How about one line of code to get a progress meter, that contains statistics about your code?
EasyProgressMeter(title,
OneLineProgressMeter(title,
current_value,
max_value,
key,
*args,
orientation=None,
bar_color=DEFAULT_PROGRESS_BAR_COLOR,
@ -431,14 +437,14 @@ We all have loops in our code. 'Isn't it joyful waiting, watching a counter scr
Here's the one-line Progress Meter in action!
for i in range(1,10000):
sg.EasyProgressMeter('My Meter', i+1, 10000, 'Optional message')
sg.OneLineProgressMeter('My Meter', i+1, 10000, 'Optional message', 'key')
That line of code resulted in this window popping up and updating.
![preogress meter](https://user-images.githubusercontent.com/13696193/43667625-d47da702-9746-11e8-91e6-e5177883abae.jpg)
A meter AND fun statistics to watch while your machine grinds away, all for the price of 1 line of code.
With a little trickery you can provide a way to break out of your loop using the Progress Meter form. The cancel button results in a `False` return value from `EasyProgressMeter`. It normally returns `True`.
With a little trickery you can provide a way to break out of your loop using the Progress Meter form. The cancel button results in a `False` return value from `OneLineProgressMeter`. It normally returns `True`.
***Be sure and add one to your loop counter*** so that your counter goes from 1 to the max value. If you do not add one, your counter will never hit the max value. Instead it will go from 0 to max-1.
@ -1526,46 +1532,19 @@ If there are more than 1 button on a form, the FIRST button that is of type Clos
---
#### ProgressBar
The `ProgressBar` element is used to build custom Progress Bar forms. It is HIGHLY recommended that you use the functions that provide a complete progress meter solution for you. Progress Meters are not easy to work with because the forms have to be non-blocking and they are tricky to debug.
The `ProgressBar` element is used to build custom Progress Bar forms. It is HIGHLY recommended that you use OneLineProgressMeter that provides a complete progress meter solution for you. Progress Meters are not easy to work with because the forms have to be non-blocking and they are tricky to debug.
The **easiest** way to get progress meters into your code is to use the `EasyProgessMeter` API. This consists of a pair of functions, `EasyProgessMeter` and `EasyProgressMeterCancel`. You can easily cancel any progress meter by calling it with the current value = max value. This will mark the meter as expired and close the window.
You've already seen EasyProgressMeter calls presented earlier in this readme.
The **easiest** way to get progress meters into your code is to use the `OneLineProgressMeter` API. This consists of a pair of functions, `OneLineProgressMeter` and `OneLineProgressMeterCancel`. You can easily cancel any progress meter by calling it with the current value = max value. This will mark the meter as expired and close the window.
You've already seen OneLineProgressMeter calls presented earlier in this readme.
sg.EasyProgressMeter('My Meter', i+1, 1000, 'Optional message')
sg.OneLineProgressMeter('My Meter', i+1, 1000, 'Optional message', 'key')
The return value for `EasyProgressMeter` is:
The return value for `OneLineProgressMeter` is:
`True` if meter updated correctly
`False` if user clicked the Cancel button, closed the form, or vale reached the max value.
**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.
You setup the progress meter by calling
my_meter = ProgressMeter(title,
max_value,
*args,
orientantion=None,
bar_color=DEFAULT_PROGRESS_BAR_COLOR,
button_color=None,
size=DEFAULT_PROGRESS_BAR_SIZE,
scale=(None, None),
border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH)
Then to update the bar within your loop
return_code = ProgressMeterUpdate(my_meter,
value,
*args):
Putting it all together you get this design pattern
my_meter = sg.ProgressMeter('Meter Title', 100000, orentation='Vert')
for i in range(0, 100000):
sg.ProgressMeterUpdate(my_meter, i+1, 'Some variable', 'Another variable')
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 Mater in Your Form
Another 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)
@ -2055,12 +2034,13 @@ 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_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_OpenCV.py** | Integrated with OpenCV
|** Demo_Password_Login** | Password protection using SHA1
|**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_Pi_LEDs.py** | Control GPIO using buttons
|**Demo_Pi_Robotics.py** | Simulated robot control using realtime buttons
|**Demo_PNG_Vierwer.py** | Uses Image Element to display PNG files
| **Demo_Progress_Meters.py** | Demonstrates using 2 progress meters simultaneously
|**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_Parameters.py** | Add a 1-line GUI to the front of your previously command-line only scripts
@ -2143,9 +2123,9 @@ While not an "issue" this is a ***stern warning***
## **Do not attempt** to call `PySimpleGUI` from multiple threads! It's `tkinter` based and `tkinter` has issues with multiple threads
**Progress Meters** - the visual graphic portion of the meter may be off. May return to the native tkinter progress meter solution in the future. Right now a "custom" progress meter is used. On the bright side, the statistics shown are extremely accurate and can tell you something about the performance of your code.
**Progress Meters** - the visual graphic portion of the meter may be off. May return to the native tkinter progress meter solution in the future. Right now a "custom" progress meter is used. On the bright side, the statistics shown are extremely accurate and can tell you something about the performance of your code. If you are running 2 or more progress meters at the same time using `OneLineProgressMeter`, you need to close the meter by using the "Cancel" button rather than the X
**Async Forms** - these include the 'easy' forms (EasyProgressMeter and EasyPrint/Print). If you start overlapping having Async forms open with normal forms then things get a littler squirrelly. Still tracking down the issues and am making it more solid every day possible. You'll know there's an issue when you see blank form.
**Async Forms** - these include the 'easy' forms (`OneLineProgressMeter` and EasyPrint/Print). If you start overlapping having Async forms open with normal forms then things get a littler squirrelly. Still tracking down the issues and am making it more solid every day possible. You'll know there's an issue when you see blank form.
**EasyPrint** - EasyPrint is a new feature that's pretty awesome. You print and the output goes to a window, with a scroll bar, that you can copy and paste from. Being a new feature, it's got some potential problems. There are known interaction problems with other GUI windows. For example, closing a Print window can also close other windows you have open. For now, don't close your debug print window until other windows are closed too.
@ -2207,6 +2187,8 @@ Related to the Grab Anywhere feature is the no_titlebar option, again found in t
3.2.0 Biggest change was the addition of the Table Element. Trying to make changes so that form resizing is a possibility but unknown if will work in the long run. Removed all MsgBox, Get* functions and replaced with Popup functions. Popups had multiple new parameters added to change the look and feel of a popup.
3.3.0 OneLineProgressMeter function added which gives you not only a one-line solution to progress meters, but it also gives you the ability to have more than 1 running at the same time, something not possible with the EasyProgressMeterCall
### Upcoming
Make suggestions people! Future release features

View File

@ -11,7 +11,7 @@
# PySimpleGUI
(Ver 3.2.0)
(Ver 3.3.0)
@ -71,7 +71,7 @@ Perhaps you're looking for a way to interact with your **Raspberry Pi** in a mor
In addition to a primary GUI, you can add a Progress Meter to your code with ONE LINE of code. Slide this into any of your `for` loops and get a nice meter like this:
EasyProgressMeter('My meter title', current_value, max value)
OneLineProgressMeter('My meter title', current_value, max value, 'key')
![easyprogressmeter](https://user-images.githubusercontent.com/13696193/44960065-83099100-aec6-11e8-8aa8-96e4b100a0e4.jpg)
@ -199,7 +199,12 @@ You will see a number of different styles of buttons, data entry fields, etc, in
- The SDK calls collapse down into a single line of Python code that presents a custom GUI and returns values
- Linear programming instead of callbacks
#### Lofty Goals
>
>
> Change Python
The expectation is not that ***this*** package will become part of the Python Standard Library. The hope is that Python will become ***the*** go-to language for creating GUI programs that run on Windows, Mac, and Linux. There is a gap in the Python GUI solution. Fill that gap and who knows what will happen. Maybe there's no "there there". Or maybe an easy to use GUI API will enable Python to dominate yet another computing discipline like it has so many others. I want to find out.
-----
@ -413,13 +418,14 @@ The window created to get a folder name looks the same as the get a file name.
![popupgetfolder](https://user-images.githubusercontent.com/13696193/44957861-45484080-aea5-11e8-926c-cf607a45251c.jpg)
#### Progress Meter!
#### Progress Meters!
We all have loops in our code. 'Isn't it joyful waiting, watching a counter scrolling past in a text window? How about one line of code to get a progress meter, that contains statistics about your code?
EasyProgressMeter(title,
OneLineProgressMeter(title,
current_value,
max_value,
key,
*args,
orientation=None,
bar_color=DEFAULT_PROGRESS_BAR_COLOR,
@ -431,14 +437,14 @@ We all have loops in our code. 'Isn't it joyful waiting, watching a counter scr
Here's the one-line Progress Meter in action!
for i in range(1,10000):
sg.EasyProgressMeter('My Meter', i+1, 10000, 'Optional message')
sg.OneLineProgressMeter('My Meter', i+1, 10000, 'Optional message', 'key')
That line of code resulted in this window popping up and updating.
![preogress meter](https://user-images.githubusercontent.com/13696193/43667625-d47da702-9746-11e8-91e6-e5177883abae.jpg)
A meter AND fun statistics to watch while your machine grinds away, all for the price of 1 line of code.
With a little trickery you can provide a way to break out of your loop using the Progress Meter form. The cancel button results in a `False` return value from `EasyProgressMeter`. It normally returns `True`.
With a little trickery you can provide a way to break out of your loop using the Progress Meter form. The cancel button results in a `False` return value from `OneLineProgressMeter`. It normally returns `True`.
***Be sure and add one to your loop counter*** so that your counter goes from 1 to the max value. If you do not add one, your counter will never hit the max value. Instead it will go from 0 to max-1.
@ -1526,46 +1532,19 @@ If there are more than 1 button on a form, the FIRST button that is of type Clos
---
#### ProgressBar
The `ProgressBar` element is used to build custom Progress Bar forms. It is HIGHLY recommended that you use the functions that provide a complete progress meter solution for you. Progress Meters are not easy to work with because the forms have to be non-blocking and they are tricky to debug.
The `ProgressBar` element is used to build custom Progress Bar forms. It is HIGHLY recommended that you use OneLineProgressMeter that provides a complete progress meter solution for you. Progress Meters are not easy to work with because the forms have to be non-blocking and they are tricky to debug.
The **easiest** way to get progress meters into your code is to use the `EasyProgessMeter` API. This consists of a pair of functions, `EasyProgessMeter` and `EasyProgressMeterCancel`. You can easily cancel any progress meter by calling it with the current value = max value. This will mark the meter as expired and close the window.
You've already seen EasyProgressMeter calls presented earlier in this readme.
The **easiest** way to get progress meters into your code is to use the `OneLineProgressMeter` API. This consists of a pair of functions, `OneLineProgressMeter` and `OneLineProgressMeterCancel`. You can easily cancel any progress meter by calling it with the current value = max value. This will mark the meter as expired and close the window.
You've already seen OneLineProgressMeter calls presented earlier in this readme.
sg.EasyProgressMeter('My Meter', i+1, 1000, 'Optional message')
sg.OneLineProgressMeter('My Meter', i+1, 1000, 'Optional message', 'key')
The return value for `EasyProgressMeter` is:
The return value for `OneLineProgressMeter` is:
`True` if meter updated correctly
`False` if user clicked the Cancel button, closed the form, or vale reached the max value.
**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.
You setup the progress meter by calling
my_meter = ProgressMeter(title,
max_value,
*args,
orientantion=None,
bar_color=DEFAULT_PROGRESS_BAR_COLOR,
button_color=None,
size=DEFAULT_PROGRESS_BAR_SIZE,
scale=(None, None),
border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH)
Then to update the bar within your loop
return_code = ProgressMeterUpdate(my_meter,
value,
*args):
Putting it all together you get this design pattern
my_meter = sg.ProgressMeter('Meter Title', 100000, orentation='Vert')
for i in range(0, 100000):
sg.ProgressMeterUpdate(my_meter, i+1, 'Some variable', 'Another variable')
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 Mater in Your Form
Another 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)
@ -2055,12 +2034,13 @@ 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_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_OpenCV.py** | Integrated with OpenCV
|** Demo_Password_Login** | Password protection using SHA1
|**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_Pi_LEDs.py** | Control GPIO using buttons
|**Demo_Pi_Robotics.py** | Simulated robot control using realtime buttons
|**Demo_PNG_Vierwer.py** | Uses Image Element to display PNG files
| **Demo_Progress_Meters.py** | Demonstrates using 2 progress meters simultaneously
|**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_Parameters.py** | Add a 1-line GUI to the front of your previously command-line only scripts
@ -2143,9 +2123,9 @@ While not an "issue" this is a ***stern warning***
## **Do not attempt** to call `PySimpleGUI` from multiple threads! It's `tkinter` based and `tkinter` has issues with multiple threads
**Progress Meters** - the visual graphic portion of the meter may be off. May return to the native tkinter progress meter solution in the future. Right now a "custom" progress meter is used. On the bright side, the statistics shown are extremely accurate and can tell you something about the performance of your code.
**Progress Meters** - the visual graphic portion of the meter may be off. May return to the native tkinter progress meter solution in the future. Right now a "custom" progress meter is used. On the bright side, the statistics shown are extremely accurate and can tell you something about the performance of your code. If you are running 2 or more progress meters at the same time using `OneLineProgressMeter`, you need to close the meter by using the "Cancel" button rather than the X
**Async Forms** - these include the 'easy' forms (EasyProgressMeter and EasyPrint/Print). If you start overlapping having Async forms open with normal forms then things get a littler squirrelly. Still tracking down the issues and am making it more solid every day possible. You'll know there's an issue when you see blank form.
**Async Forms** - these include the 'easy' forms (`OneLineProgressMeter` and EasyPrint/Print). If you start overlapping having Async forms open with normal forms then things get a littler squirrelly. Still tracking down the issues and am making it more solid every day possible. You'll know there's an issue when you see blank form.
**EasyPrint** - EasyPrint is a new feature that's pretty awesome. You print and the output goes to a window, with a scroll bar, that you can copy and paste from. Being a new feature, it's got some potential problems. There are known interaction problems with other GUI windows. For example, closing a Print window can also close other windows you have open. For now, don't close your debug print window until other windows are closed too.
@ -2207,6 +2187,8 @@ Related to the Grab Anywhere feature is the no_titlebar option, again found in t
3.2.0 Biggest change was the addition of the Table Element. Trying to make changes so that form resizing is a possibility but unknown if will work in the long run. Removed all MsgBox, Get* functions and replaced with Popup functions. Popups had multiple new parameters added to change the look and feel of a popup.
3.3.0 OneLineProgressMeter function added which gives you not only a one-line solution to progress meters, but it also gives you the ability to have more than 1 running at the same time, something not possible with the EasyProgressMeterCall
### Upcoming
Make suggestions people! Future release features