Fixed bad examples. Updated readme quite a bit, but a lot more to do!
This commit is contained in:
parent
b6b766dfdb
commit
176b0c9122
277
docs/index.md
277
docs/index.md
|
@ -1275,7 +1275,8 @@ With a little trickery you can provide a way to break out of your loop using the
|
||||||
***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.
|
***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.
|
||||||
|
|
||||||
# Debug Output
|
# Debug Output
|
||||||
Another call in the 'Easy' families of APIs is `EasyPrint`. It will output to a debug window. If the debug window isn't open, then the first call will open it. No need to do anything but stick a 'print' call in your code. You can even replace your 'print' calls with calls to EasyPrint by simply sticking the statement
|
|
||||||
|
Another call in the 'Easy' families of APIs is `EasyPrint`. As is with other commonly used PySimpleGUI calls, there are other names for the same call. You can use `Print` or `eprint` in addition to `EasyPrint`. They all do the same thing, output to a debug window. If the debug window isn't open, then the first call will open it. No need to do anything but stick an 'sg.Print' call in your code. You can even replace your 'print' calls with calls to EasyPrint by simply sticking the statement
|
||||||
|
|
||||||
```python
|
```python
|
||||||
print = sg.EasyPrint
|
print = sg.EasyPrint
|
||||||
|
@ -1283,7 +1284,7 @@ print = sg.EasyPrint
|
||||||
|
|
||||||
at the top of your code.
|
at the top of your code.
|
||||||
|
|
||||||
There are a number of names for the same EasyPrint function. `Print` is one of the better ones to use as it's easy to remember. It is simply `print` with a capital P.
|
`Print` is one of the better ones to use as it's easy to remember. It is simply `print` with a capital P. `sg.Print('this will go to the debug window')`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
@ -1308,22 +1309,22 @@ Just like the standard print call, `EasyPrint` supports the `sep` and `end` keyw
|
||||||
|
|
||||||
You can change the size of the debug window using the `SetOptions` call with the `debug_win_size` parameter.
|
You can change the size of the debug window using the `SetOptions` call with the `debug_win_size` parameter.
|
||||||
|
|
||||||
There is an option to tell PySimpleGUI to reroute all of your stdout and stderr output to this window. To do so call EasyPrint with the parameter `do_not_reroute_stdout` set to True. After calling it once with this parameter set to True, all future calls to a normal`print` will go to the debug window.
|
There is an option to tell PySimpleGUI to reroute all of your stdout and stderr output to this window. To do so call EasyPrint with the parameter `do_not_reroute_stdout` set to `False`. After calling it once with this parameter set to True, all future calls to a normal`print` will go to the debug window.
|
||||||
|
|
||||||
If you close the debug window it will re-open the next time you Print to it.
|
If you close the debug window it will re-open the next time you Print to it. If you wish to close the window using your code, then you can call either `EasyPrintClose()` or `PrintClose()`
|
||||||
|
|
||||||
---
|
---
|
||||||
# Custom window API Calls (Your First window)
|
# Custom window API Calls (Your First window)
|
||||||
|
|
||||||
This is the FUN part of the programming of this GUI. In order to really get the most out of the API, you should be using an IDE that supports auto complete or will show you the definition of the function. This will make customizing go smoother.
|
This is the FUN part of the programming of this GUI. In order to really get the most out of the API, you should be using an IDE that supports auto complete or will show you the definition of the function. This will make customizing go smoother.
|
||||||
|
|
||||||
This first section on custom windows is for your typical, blocking, non-persistent window. By this I mean, when you "show" the window, the function will not return until the user has clicked a button or closed the window. When this happens, the window will be automatically closed.
|
This first section on custom windows is for your typical, blocking, non-persistent window. By this I mean, when you "show" the window, the function will not return until the user has clicked a button or closed the window with an X.
|
||||||
|
|
||||||
Two other types of windows exist.
|
Two other types of windows exist.
|
||||||
1. Persistent window - rather than closing on button clicks, the show window function returns and the window continues to be visible. This is good for applications like a chat window.
|
1. Persistent window - the `Window.Read()` method returns and the window continues to be visible. This is good for applications like a chat window or a timer or anything that stays active on the screen for a while.
|
||||||
2. Asynchronous window - the trickiest of the lot. Great care must be exercised. Examples are an MP3 player or status dashboard. Async windows are updated (refreshed) on a periodic basis.
|
2. Asynchronous window - the trickiest of the lot. Great care must be exercised. Examples are an MP3 player or status dashboard. Async windows are updated (refreshed) on a periodic basis. You can spot them easily as they will have a `timeout` parameter on the call to read. `event, values = window.Read(timeout=100)`
|
||||||
|
|
||||||
It's both not enjoyable nor helpful to immediately jump into tweaking each and every little thing available to you.
|
It's both not enjoyable nor helpful to immediately jump into tweaking each and every little thing available to you. Make some simple windows. Use the Cookbook and the Demo Programs as a way to learn and as a "starting point".
|
||||||
|
|
||||||
## The window Designer
|
## The window Designer
|
||||||
|
|
||||||
|
@ -1390,11 +1391,13 @@ layout = [[sg.Text('Enter a Number')],
|
||||||
[sg.Input()],
|
[sg.Input()],
|
||||||
[sg.OK()] ]
|
[sg.OK()] ]
|
||||||
|
|
||||||
event, (number,) = sg.Window('Enter a number example', layout).Read()
|
event, values = sg.Window('Enter a number example', layout).Read()
|
||||||
|
|
||||||
sg.Popup(event, number)
|
sg.Popup(event, values[0])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Your call to `Read` will return a dictionary, but will "look like a list" in how you access it. The first input field will be entry 0, the next one is 1, etc. Later you'll learn about the `key` parameter which allows you to use your own values to identify elements instead of them being numbered for you.
|
||||||
|
|
||||||
### Example 2 - Get a filename
|
### Example 2 - Get a filename
|
||||||
Let's say you've got a utility you've written that operates on some input file and you're ready to use a GUI to enter than filename rather than the command line. Follow the same steps as the previous example - draw your window on paper, break it up into rows, label the elements.
|
Let's say you've got a utility you've written that operates on some input file and you're ready to use a GUI to enter than filename rather than the command line. Follow the same steps as the previous example - draw your window on paper, break it up into rows, label the elements.
|
||||||
|
|
||||||
|
@ -1410,9 +1413,9 @@ layout = [[sg.Text('Filename')],
|
||||||
[sg.Input(), sg.FileBrowse()],
|
[sg.Input(), sg.FileBrowse()],
|
||||||
[sg.OK(), sg.Cancel()] ]
|
[sg.OK(), sg.Cancel()] ]
|
||||||
|
|
||||||
event, (number,) = sg.Window('Get filename example', layout).Read()
|
event, values = sg.Window('Get filename example', layout).Read()
|
||||||
|
|
||||||
sg.Popup(event, number)
|
sg.Popup(event, values[0])
|
||||||
```
|
```
|
||||||
|
|
||||||
Read on for detailed instructions on the calls that show the window and return your results.
|
Read on for detailed instructions on the calls that show the window and return your results.
|
||||||
|
@ -1421,25 +1424,25 @@ Read on for detailed instructions on the calls that show the window and return y
|
||||||
|
|
||||||
All of your PySimpleGUI programs will utilize one of these 2 design patterns depending on the type of window you're implementing.
|
All of your PySimpleGUI programs will utilize one of these 2 design patterns depending on the type of window you're implementing.
|
||||||
|
|
||||||
## Pattern 1 - "One-shot Window" - Read into list or dictionary (**The Most Common** Pattern)
|
## Pattern 1 - "One-shot Window" - Read a window one time then close it
|
||||||
|
|
||||||
This will be the most common pattern you'll follow if you are not using an "event loop" (not reading the window multiple times). The window is read and closes.
|
This will be the most common pattern you'll follow if you are not using an "event loop" (not reading the window multiple times). The window is read and closed.
|
||||||
|
|
||||||
It's unusual to assign the values returned from the read call directly into user variables. Usually the variables are grouped together into a list or dictionary of multiple return values.
|
The input fields in your window will be returned to you as a dictionary (syntactically it looks just like a list lookup)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
window_rows = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
|
layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
|
||||||
[sg.InputText(), sg.FileBrowse()],
|
[sg.InputText(), sg.FileBrowse()],
|
||||||
[sg.Submit(), sg.Cancel()]]
|
[sg.Submit(), sg.Cancel()]]
|
||||||
|
|
||||||
window = sg.Window('SHA-1 & 256 Hash', window_rows)
|
window = sg.Window('SHA-1 & 256 Hash', layout)
|
||||||
|
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
window.Close()
|
window.Close()
|
||||||
|
|
||||||
source_filename = values[0]
|
source_filename = values[0] # the first input element is values[0]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pattern 2 A - Persistent window (multiple reads using an event loop)
|
## Pattern 2 A - Persistent window (multiple reads using an event loop)
|
||||||
|
@ -1452,7 +1455,7 @@ This code will present a window and will print values until the user clicks the
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
layout = [[sg.Text('Persistent window')],
|
layout = [[sg.Text('Persistent window')],
|
||||||
[sg.Input(do_not_clear=True)],
|
[sg.Input()],
|
||||||
[sg.Button('Read'), sg.Exit()]]
|
[sg.Button('Read'), sg.Exit()]]
|
||||||
|
|
||||||
window = sg.Window('Window that stays open', layout)
|
window = sg.Window('Window that stays open', layout)
|
||||||
|
@ -1468,11 +1471,13 @@ window.Close()
|
||||||
|
|
||||||
## Pattern 2 B - Persistent window (multiple reads using an event loop + updates data in window)
|
## Pattern 2 B - Persistent window (multiple reads using an event loop + updates data in window)
|
||||||
|
|
||||||
This is a slightly more complex, but maybe more realistic version that reads input from the user and displays that input as text in the window. Your program is likely to be doing both of those activities so this will give you a big jump-start.
|
This is a slightly more complex, but maybe more realistic version that reads input from the user and displays that input as text in the window. Your program is likely to be doing both of those activities (input and output) so this will give you a big jump-start.
|
||||||
|
|
||||||
Do not worry yet what all of these statements mean. Just copy it so you can begin to play with it, make some changes. Experiment to see how thing work.
|
Do not worry yet what all of these statements mean. Just copy it so you can begin to play with it, make some changes. Experiment to see how thing work.
|
||||||
|
|
||||||
A final note... the parameter `do_not_clear` in the input call determines the action of the input field after a button event. If this value is True, the input value remains visible following button clicks. If False, then the input field is CLEARED of whatever was input. If you are building a "Form" type of window with data entry, you likely want False, the default setting (you can remove the parameter completely).
|
A final note... the parameter `do_not_clear` in the input call determines the action of the input field after a button event. If this value is True, the input value remains visible following button clicks. If False, then the input field is CLEARED of whatever was input. If you are building a "Form" type of window with data entry, you likely want False. The default is to NOT clear the input element (`do_not_clear=True`).
|
||||||
|
|
||||||
|
This example introduces the concept of "keys". Keys are super important in PySimpleGUI as they enable you to identify and work with Elements using names you want to use. Keys can be ANYTHING, except `None`. To access an input element's data that is read in the example below, you will use `values['_IN_']` instead of `values[0]` like before.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import sys
|
import sys
|
||||||
|
@ -1482,7 +1487,7 @@ else:
|
||||||
import PySimpleGUI27 as sg
|
import PySimpleGUI27 as sg
|
||||||
|
|
||||||
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ],
|
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ],
|
||||||
[sg.Input(do_not_clear=True, key='_IN_')],
|
[sg.Input(key='_IN_')],
|
||||||
[sg.Button('Show'), sg.Button('Exit')]]
|
[sg.Button('Show'), sg.Button('Exit')]]
|
||||||
|
|
||||||
window = sg.Window('Window Title', layout)
|
window = sg.Window('Window Title', layout)
|
||||||
|
@ -1499,6 +1504,12 @@ while True: # Event Loop
|
||||||
window.Close()
|
window.Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Qt Designer
|
||||||
|
|
||||||
|
There actually is a PySimpleGUI Window Designer that uses Qt's window designer. It's outside the scope of this document however. You'll find the project here: https://github.com/nngogol/PySimpleGUIDesigner
|
||||||
|
|
||||||
|
I hope to start using it more soon.
|
||||||
|
|
||||||
## How GUI Programming in Python Should Look? At least for beginners ?
|
## How GUI Programming in Python Should Look? At least for beginners ?
|
||||||
|
|
||||||
While one goal was making it simple to create a GUI another just as important goal was to do it in a Pythonic manner. Whether it achieved these goals is debatable, but it was an attempt just the same.
|
While one goal was making it simple to create a GUI another just as important goal was to do it in a Pythonic manner. Whether it achieved these goals is debatable, but it was an attempt just the same.
|
||||||
|
@ -1518,6 +1529,9 @@ layout = [[sg.Text('Rename files or folders')],
|
||||||
window = sg.Window('Rename Files or Folders', layout)
|
window = sg.Window('Rename Files or Folders', layout)
|
||||||
|
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
|
||||||
|
folder_path, file_path = values[0], values[1] # get the data from the values dictionary
|
||||||
|
print(folder_path, file_path)
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
@ -1543,20 +1557,20 @@ And what about those return values? Most people simply want to show a window, g
|
||||||
|
|
||||||
For return values the window is scanned from top to bottom, left to right. Each field that's an input field will occupy a spot in the return values.
|
For return values the window is scanned from top to bottom, left to right. Each field that's an input field will occupy a spot in the return values.
|
||||||
|
|
||||||
In our example window, there are 2 fields, so the return values from this window will be a list with 2 values in it.
|
In our example window, there are 2 fields, so the return values from this window will be a dictionary with 2 values in it. Remember, if you do not specify a `key` when creating an element, one will be created for you. They are ints starting with 0. In this example, we have 2 input elements. They will be addressable as values[0] and values[1]
|
||||||
|
|
||||||
```python
|
```python
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
folder_path, file_path = values
|
folder_path, file_path = values[0], values[1]
|
||||||
```
|
```
|
||||||
|
|
||||||
In one statement we both show the window and read the user's inputs. In the next the *list* of return values is split into individual variables `folder_path` and `file_path`.
|
In one statement we both show the window and read the user's inputs. In the next line of code the *dictionary* of return values is split into individual variables `folder_path` and `file_path`.
|
||||||
|
|
||||||
Isn't this what a Python programmer looking for a GUI wants? Something easy to work with to get the values and move on to the rest of the program, where the real action is taking place. Why write pages of GUI code when the same layout can be achieved with PySimpleGUI in 3 or 4 lines of code. 4 lines or 40? Most would choose 4.
|
Isn't this what a Python programmer looking for a GUI wants? Something easy to work with to get the values and move on to the rest of the program, where the real action is taking place. Why write pages of GUI code when the same layout can be achieved with PySimpleGUI in 3 or 4 lines of code. 4 lines or 40? Most would choose 4.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
|
|
||||||
As of version 2.8 there are 2 forms of return values, list and dictionary.
|
There are 2 return values from a call to `Window.Read()`, an `event` that caused the `Read` to return and `values` a list or dictionary of values. If there are no elements with keys in the layout, then it will be a list. However, some elements, like some buttons, have a key automatically added to them. **It's best to use keys on all of your input type elements.**
|
||||||
|
|
||||||
### Two Return Values
|
### Two Return Values
|
||||||
|
|
||||||
|
@ -1566,7 +1580,7 @@ All Window Read calls return 2 values. By convention a read statement is writte
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
```
|
```
|
||||||
|
|
||||||
You don't HAVE to write your reads in this way. You can name your variables however you want. But if you want to code them in a way that other programmers using PySimpleGUI are used to, then use these statements.
|
You don't HAVE to write your reads in this way. You can name your variables however you want. But if you want to code them in a way that other programmers using PySimpleGUI are used to, then use this statement.
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
|
@ -1595,7 +1609,9 @@ For Windows that have specifically enabled these. Please see the appropriate se
|
||||||
|
|
||||||
### Window closed event
|
### Window closed event
|
||||||
|
|
||||||
Another convention to follow is the check for windows being closed with an X. This is an important event to catch. If you don't check for this and you attempt to use the window, your program will crash. Please check for closed window and exit your program gracefully.
|
Another convention to follow is the check for windows being closed with an X. *This is an important event to catch*. If you don't check for this and you attempt to use the window, your program will crash. Please check for closed window and exit your program gracefully. Your users will like you for it.
|
||||||
|
|
||||||
|
Close your windows when you're done with them even though exiting the program will also close them. tkinter can generate an error/warning sometimes if you don't close the window.
|
||||||
|
|
||||||
To check for a closed window use this line of code:
|
To check for a closed window use this line of code:
|
||||||
|
|
||||||
|
@ -1610,7 +1626,25 @@ while True:
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
if event is None:
|
if event is None:
|
||||||
break
|
break
|
||||||
|
window.Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You will very often see the examples and demo programs write this check as:
|
||||||
|
|
||||||
|
```python
|
||||||
|
event, values = window.Read()
|
||||||
|
if event in (None, 'Exit'):
|
||||||
|
break
|
||||||
|
```
|
||||||
|
|
||||||
|
This if statement is the same as:
|
||||||
|
```python
|
||||||
|
if event is None or event == 'Exit':
|
||||||
|
break
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of `'Exit'` use the name of the button you want to exit the window (Cancel, Quit, etc)
|
||||||
|
|
||||||
### Button Click Events
|
### Button Click Events
|
||||||
|
|
||||||
By default buttons will always return a click event, or in the case of realtime buttons, a button down event. You don't have to do anything to enable button clicks. To disable the events, disable the button using its Update method.
|
By default buttons will always return a click event, or in the case of realtime buttons, a button down event. You don't have to do anything to enable button clicks. To disable the events, disable the button using its Update method.
|
||||||
|
@ -1875,6 +1909,8 @@ You can learn more about these async / non-blocking windows toward the end of th
|
||||||
# Window Object - Beginning a window
|
# Window Object - Beginning a window
|
||||||
The first step is to create the window object using the desired window customization.
|
The first step is to create the window object using the desired window customization.
|
||||||
|
|
||||||
|
**IMPORTANT** - Many of the `Window` methods require you to either call `Window.Read` or `Window.Finalize` before you call the method. This is because these 2 calls are what actually creates the window using the underlying GUI Framework. Prior to one of those calls, the methods are likely to crash as they will not yet have their underlying widgets created.
|
||||||
|
|
||||||
Represents a single Window
|
Represents a single Window
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -2187,7 +2223,7 @@ Minimize()
|
||||||
|
|
||||||
Move the upper left corner of this window to the x,y coordinates provided
|
Move the upper left corner of this window to the x,y coordinates provided
|
||||||
|
|
||||||
```python
|
```
|
||||||
Move(x, y)
|
Move(x, y)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2366,9 +2402,9 @@ To keep a window on top of all other windows on the screen, set keep_on_top = Tr
|
||||||
|
|
||||||
PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call.
|
PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call.
|
||||||
|
|
||||||
## Window Methods
|
## Window Methods That Complete Formation of Window
|
||||||
|
|
||||||
There are a number of operations you can do on a window after you've created the window. You call these after creating your Windows object.
|
There are a number of operations you can do on a window after you've created the window. You call these after creating your Windows object. Most Window methods are not usable until you call one of these.
|
||||||
|
|
||||||
#### Layout(rows)
|
#### Layout(rows)
|
||||||
|
|
||||||
|
@ -2394,9 +2430,9 @@ If you set the timeout = 0, then the Read will immediately return rather than wa
|
||||||
|
|
||||||
#### ReadNonBlocking() (NO LONGER USED)
|
#### ReadNonBlocking() (NO LONGER USED)
|
||||||
|
|
||||||
While this call will technically still work, it is being removed. If you want to get the same result, call Read with timeout = 0.
|
Some of the old code examples showed calling this function. You should now call it now. If you want to get the same result, call Read with `timeout = 0`.
|
||||||
|
|
||||||
The only time you will see this call is in OLD CODE. Please file an Issue if you see this call in any code or in any documentation. It must go away never to be seen again.
|
Please file an Issue if you see this call in any code or in any documentation. It must go away never to be seen again.
|
||||||
|
|
||||||
# Elements
|
# Elements
|
||||||
"Elements" are the building blocks used to create windows. Some GUI APIs use the term "Widget" to describe these graphic elements.
|
"Elements" are the building blocks used to create windows. Some GUI APIs use the term "Widget" to describe these graphic elements.
|
||||||
|
@ -2443,19 +2479,26 @@ Some parameters that you will see on almost all Elements are:
|
||||||
- colors - Color name or #RRGGBB string
|
- colors - Color name or #RRGGBB string
|
||||||
- pad - Amount of padding to put around element
|
- pad - Amount of padding to put around element
|
||||||
- enable_events - Turns on the element specific events
|
- enable_events - Turns on the element specific events
|
||||||
|
- visible - Make elements appear and disappear
|
||||||
|
|
||||||
#### Tooltip
|
#### Tooltip
|
||||||
Tooltips are text boxes that popup next to an element if you hold your mouse over the top of it. If you want to be extra kind to your window's user, then you can create tooltips for them by setting the parameter `tooltip` to some text string. You will need to supply your own line breaks / text wrapping. If you don't want to manually add them, then take a look at the standard library package `textwrap`.
|
Tooltips are text boxes that popup next to an element if you hold your mouse over the top of it. If you want to be extra kind to your window's user, then you can create tooltips for them by setting the parameter `tooltip` to some text string. You will need to supply your own line breaks / text wrapping. If you don't want to manually add them, then take a look at the standard library package `textwrap`.
|
||||||
|
|
||||||
Tooltips are one of those "polish" items that really dress-up a GUI and show's a level of sophistication. Go ahead, impress people, throw some tooltips into your GUI.
|
Tooltips are one of those "polish" items that really dress-up a GUI and show's a level of sophistication. Go ahead, impress people, throw some tooltips into your GUI. You can change the color of the background of the tooltip on the tkinter version of PySimpleGUI by setting `TOOLTIP_BACKGROUND_COLOR` to the color string of your choice. The default value for the color is:
|
||||||
|
`TOOLTIP_BACKGROUND_COLOR = "#ffffe0"`
|
||||||
|
|
||||||
#### Size
|
#### Size
|
||||||
Specifies the amount of room reserved for the Element. For elements that are character based, such a Text, it is (# characters, # rows). Sometimes it is a pixel measurement such as the Image element. And sometimes a mix like on the Slider element (characters long by pixels wide).
|
Specifies the amount of room reserved for the Element. For elements that are character based, such a Text, it is (# characters, # rows). Sometimes it is a pixel measurement such as the Image element. And sometimes a mix like on the Slider element (characters long by pixels wide).
|
||||||
|
|
||||||
|
Some elements, Text and Button, have an auto-size setting that is `on` by default. It will size the element based on the contents. The result is that buttons and text fields will be the size of the string creating them. You can turn it off. For example, for Buttons, the effect will be that all buttons will be the same size in that window.
|
||||||
|
|
||||||
#### Colors
|
#### Colors
|
||||||
A string representing color. Anytime colors are involved, you can specify the tkinter color name such as 'lightblue' or an RGB hex value '#RRGGBB'. For buttons, the color parameter is a tuple (text color, background color)
|
A string representing color. Anytime colors are involved, you can specify the tkinter color name such as 'lightblue' or an RGB hex value '#RRGGBB'. For buttons, the color parameter is a tuple (text color, background color)
|
||||||
|
|
||||||
|
Anytime colors are written as a tuple in PySimpleGUI, the way to figure out which color is the background is to replace the "," with the word "on". ('white', 'red') specifies a button that is "white on red". Works anywhere there's a color tuple.
|
||||||
|
|
||||||
#### Pad
|
#### Pad
|
||||||
|
|
||||||
The amount of room around the element in pixels. The default value is (5,3) which means leave 5 pixels on each side of the x-axis and 3 pixels on each side of the y-axis. You can change this on a global basis using a call to SetOptions, or on an element basis.
|
The amount of room around the element in pixels. The default value is (5,3) which means leave 5 pixels on each side of the x-axis and 3 pixels on each side of the y-axis. You can change this on a global basis using a call to SetOptions, or on an element basis.
|
||||||
|
|
||||||
If you want more pixels on one side than the other, then you can split the number into 2 number. If you want 200 pixels on the left side, and 3 pixels on the right, the pad would be ((200,3), 3). In this example, only the x-axis is split.
|
If you want more pixels on one side than the other, then you can split the number into 2 number. If you want 200 pixels on the left side, and 3 pixels on the right, the pad would be ((200,3), 3). In this example, only the x-axis is split.
|
||||||
|
@ -2494,6 +2537,16 @@ Then to get the input value from the read it would be: `values['mykey']`
|
||||||
|
|
||||||
You also use the same key if you want to call Update on an element. Please see the section below on Updates to understand that usage.
|
You also use the same key if you want to call Update on an element. Please see the section below on Updates to understand that usage.
|
||||||
|
|
||||||
|
Keys can be ANYTHING. Let's say you have a window with a grid of input elements. You could use their row and column location as a key (a tuple)
|
||||||
|
|
||||||
|
`key=(row, col)`
|
||||||
|
|
||||||
|
Then when you read the `values` variable that's returned to you from calling `Window.Read()`, the key in the `values` variable will be whatever you used to create the element. In this case you would read the values as:
|
||||||
|
`values[(row, col)]`
|
||||||
|
|
||||||
|
Most of the time they are simple text strings. In the Demo Programs, keys are written with this convention:
|
||||||
|
`_KEY_NAME_` (underscore at beginning and end with all caps letters). You don't have to follow that convention. It's used so that you can quickly spot when a key is being used.
|
||||||
|
|
||||||
#### Visible
|
#### Visible
|
||||||
Beginning in version 3.17 you can create Elements that are initially invisible that you can later make visible.
|
Beginning in version 3.17 you can create Elements that are initially invisible that you can later make visible.
|
||||||
|
|
||||||
|
@ -2503,17 +2556,13 @@ Later when you want to make that Element visible you simply call the Element's `
|
||||||
|
|
||||||
This feature works best on Qt, but does work on the tkinter version as well. The visible parameter can also be used with the Column and Frame "container" Elements.
|
This feature works best on Qt, but does work on the tkinter version as well. The visible parameter can also be used with the Column and Frame "container" Elements.
|
||||||
|
|
||||||
### Output Element
|
|
||||||
Building a window is simply making lists of Elements. Each list is a row in the overall GUI dialog box. The definition looks something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
layout = [ [row 1 element, row 1 element],
|
|
||||||
[row 2 element, row 2 element, row 2 element] ]
|
|
||||||
```
|
|
||||||
The code is a crude representation of the GUI, laid out in text.
|
|
||||||
## Shortcut Functions / Multiple Function Names
|
## Shortcut Functions / Multiple Function Names
|
||||||
|
|
||||||
Many of the main method calls and Element names have shortcuts. This enables you to code much quicker once you are used to using the SDK. The Text Element, for example, has 3 different names `Text`, `Txt` or`T`. InputText can also be written `Input` or `In` . `FindElement` was recently renamed to `Element` because it's a commonly used function.
|
Perhaps not the best idea, but one that's done none the less is the naming of methods and functions. Some of the more "Heavily Travelled Elements" have "shortcuts".
|
||||||
|
|
||||||
|
In other words, I am lazy and don't like to type. The result is multiple ways to do exactly the same thing. Typically, the Demo Programs and other examples use the full name, or at least a longer name. Thankfully PyCharm will show you the same documentation regardless which you use.
|
||||||
|
|
||||||
|
This enables you to code much quicker once you are used to using the SDK. The Text Element, for example, has 3 different names `Text`, `Txt` or`T`. InputText can also be written `Input` or `In` . The shortcuts aren't limited to Elements. The `Window` method `Window.FindElement` can be written as `Window.Element` because it's such a commonly used function.
|
||||||
|
|
||||||
## Text Element | `T == Txt == Text`
|
## Text Element | `T == Txt == Text`
|
||||||
Basic Element. It displays text. That's it.
|
Basic Element. It displays text. That's it.
|
||||||
|
@ -2617,14 +2666,18 @@ Individual colors are specified using either the color names as defined in tkint
|
||||||
"#RRGGBB" or "darkblue"
|
"#RRGGBB" or "darkblue"
|
||||||
|
|
||||||
### `auto_size_text `
|
### `auto_size_text `
|
||||||
A `True` value for `auto_size_text`, when placed on Text Elements, indicates that the width of the Element should be shrunk do the width of the text. The default setting is True.
|
A `True` value for `auto_size_text`, when placed on Text Elements, indicates that the width of the Element should be shrunk do the width of the text. The default setting is True. You need to remember this when you create `Text` elements that you are using for output.
|
||||||
|
|
||||||
|
`Text('', key='_TXTOUT_)` will create a `Text` Element that has 0 length. If you try to output a string that's 5 characters, it won't be shown in the window because there isn't enough room. The remedy is to manually set the size to what you expect to output
|
||||||
|
|
||||||
|
`Text('', size=(15,1), key='_TXTOUT_)` creates a `Text` Element that can hold 15 characters.
|
||||||
|
|
||||||
### Chortcut functions
|
### Chortcut functions
|
||||||
The shorthand functions for `Text` are `Txt` and `T`
|
The shorthand functions for `Text` are `Txt` and `T`
|
||||||
|
|
||||||
### Events `enable_events`
|
### Events `enable_events`
|
||||||
|
|
||||||
If you set the parameter `enable_events` or `click_submits` then you will get an event if the user clicks on the Text.
|
If you set the parameter `enable_events` then you will get an event if the user clicks on the Text.
|
||||||
|
|
||||||
## Multiline Element
|
## Multiline Element
|
||||||
This Element doubles as both an input and output Element.
|
This Element doubles as both an input and output Element.
|
||||||
|
@ -3104,7 +3157,7 @@ Parameter Descriptions:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
ListBoxes can cause a window to return from a Read call. If the flag change_submits is set, then when a user makes a selection, the Read immediately returns.
|
ListBoxes can cause a window to return from a Read call. If the flag `enable_events` is set, then when a user makes a selection, the Read immediately returns.
|
||||||
|
|
||||||
Another way ListBoxes can cause Reads to return is if the flag bind_return_key is set. If True, then if the user presses the return key while an entry is selected, then the Read returns. Also, if this flag is set, if the user double-clicks an entry it will return from the Read.
|
Another way ListBoxes can cause Reads to return is if the flag bind_return_key is set. If True, then if the user presses the return key while an entry is selected, then the Read returns. Also, if this flag is set, if the user double-clicks an entry it will return from the Read.
|
||||||
|
|
||||||
|
@ -3839,7 +3892,7 @@ gui_rows = [[sg.Text('Robotics Remote Control')],
|
||||||
[sg.Quit(button_color=('black', 'orange'))]
|
[sg.Quit(button_color=('black', 'orange'))]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = sg.Window('Robotics Remote Control', auto_size_text=True).Layout(gui_rows)
|
window = sg.Window('Robotics Remote Control', gui_rows)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Some place later in your code...
|
# Some place later in your code...
|
||||||
|
@ -3849,7 +3902,7 @@ window = sg.Window('Robotics Remote Control', auto_size_text=True).Layout(gui_ro
|
||||||
# your program's main loop
|
# your program's main loop
|
||||||
while (True):
|
while (True):
|
||||||
# This is the code that reads and updates your window
|
# This is the code that reads and updates your window
|
||||||
event, values = window.Read(timeout=0)
|
event, values = window.Read(timeout=50)
|
||||||
if event is not None:
|
if event is not None:
|
||||||
print(event)
|
print(event)
|
||||||
if event == 'Quit' or values is None:
|
if event == 'Quit' or values is None:
|
||||||
|
@ -4025,7 +4078,7 @@ layout = [[sg.Text('A custom progress meter')],
|
||||||
[sg.Cancel()]]
|
[sg.Cancel()]]
|
||||||
|
|
||||||
# create the window`
|
# create the window`
|
||||||
window = sg.Window('Custom Progress Meter').Layout(layout)
|
window = sg.Window('Custom Progress Meter', layout)
|
||||||
progress_bar = window.FindElement('progressbar')
|
progress_bar = window.FindElement('progressbar')
|
||||||
# loop that would normally do something useful
|
# loop that would normally do something useful
|
||||||
for i in range(10000):
|
for i in range(10000):
|
||||||
|
@ -4071,7 +4124,7 @@ Parameter Descriptions:
|
||||||
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
||||||
|visible|(bool) set visibility state of the element|
|
|visible|(bool) set visibility state of the element|
|
||||||
|
|
||||||
## Output Elements
|
## Output Element
|
||||||
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.
|
||||||
|
|
||||||
Note that you will NOT see what you `print` until you call either window.Read or window.Refresh. If you want to immediately see what was printed, call window.Refresh() immediately after your print statement.
|
Note that you will NOT see what you `print` until you call either window.Read or window.Refresh. If you want to immediately see what was printed, call window.Refresh() immediately after your print statement.
|
||||||
|
@ -4140,9 +4193,9 @@ def ChatBot():
|
||||||
sg.RButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])),
|
sg.RButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])),
|
||||||
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
|
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
|
||||||
|
|
||||||
window = sg.Window('Chat Window', default_element_size=(30, 2)).Layout(layout)
|
window = sg.Window('Chat Window', layout, default_element_size=(30, 2))
|
||||||
|
|
||||||
# ---===--- Loop taking in user input then printing so will show up in Output Element --- #
|
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
|
||||||
while True:
|
while True:
|
||||||
event, value = window.Read()
|
event, value = window.Read()
|
||||||
if event == 'SEND':
|
if event == 'SEND':
|
||||||
|
@ -4184,8 +4237,7 @@ Parameter Descriptions:
|
||||||
|---|---|
|
|---|---|
|
||||||
|layout|List[List[Element]] Layout that will be shown in the Column container|
|
|layout|List[List[Element]] Layout that will be shown in the Column container|
|
||||||
|background_color|(str) color of background of entire Column|
|
|background_color|(str) color of background of entire Column|
|
||||||
|size|Tuple[int, int] (width, height) size in pixels (doesn't work quite right, sometimes
|
|size|Tuple[int, int] (width, height) size in pixels (doesn't work quite right, sometimes only 1 dimension is set by tkinter|
|
||||||
only 1 dimension is set by tkinter|
|
|
||||||
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
||||||
|scrollable|(bool) if True then scrollbars will be added to the column|
|
|scrollable|(bool) if True then scrollbars will be added to the column|
|
||||||
|vertical_scroll_only|(bool) if Truen then no horizontal scrollbar will be shown|
|
|vertical_scroll_only|(bool) if Truen then no horizontal scrollbar will be shown|
|
||||||
|
@ -4222,7 +4274,7 @@ layout = [[sg.Slider(range=(1,100), default_value=10, orientation='v', size=(8,2
|
||||||
# Display the window and get values
|
# Display the window and get values
|
||||||
# If you're willing to not use the "context manager" design pattern, then it's possible
|
# If you're willing to not use the "context manager" design pattern, then it's possible
|
||||||
# to collapse the window display and read down to a single line of code.
|
# to collapse the window display and read down to a single line of code.
|
||||||
event, values = sg.Window('Compact 1-line window with column').Layout(layout).Read()
|
event, values = sg.Window('Compact 1-line window with column', layout).Read()
|
||||||
|
|
||||||
sg.Popup(event, values, line_width=200)
|
sg.Popup(event, values, line_width=200)
|
||||||
```
|
```
|
||||||
|
@ -4291,7 +4343,7 @@ layout = [
|
||||||
[sg.Submit(), sg.Cancel()]
|
[sg.Submit(), sg.Cancel()]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = sg.Window('Frame with buttons', font=("Helvetica", 12)).Layout(layout)
|
window = sg.Window('Frame with buttons', layout, font=("Helvetica", 12))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Canvas Element
|
## Canvas Element
|
||||||
|
@ -4334,6 +4386,7 @@ One such integration is with Matploplib and Pyplot. There is a Demo program wri
|
||||||
tooltip - tooltip text)
|
tooltip - tooltip text)
|
||||||
|
|
||||||
The order of operations to obtain a tkinter Canvas Widget is:
|
The order of operations to obtain a tkinter Canvas Widget is:
|
||||||
|
```python
|
||||||
|
|
||||||
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
|
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
|
||||||
# define the window layout
|
# define the window layout
|
||||||
|
@ -4342,13 +4395,14 @@ The order of operations to obtain a tkinter Canvas Widget is:
|
||||||
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
|
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
|
||||||
|
|
||||||
# create the window and show it without the plot
|
# create the window and show it without the plot
|
||||||
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
|
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout).Finalize()
|
||||||
|
|
||||||
# add the plot to the window
|
# add the plot to the window
|
||||||
fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig)
|
fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig)
|
||||||
|
|
||||||
# show it all again and get buttons
|
# show it all again and get buttons
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
```
|
||||||
|
|
||||||
To get a tkinter Canvas Widget from PySimpleGUI, follow these steps:
|
To get a tkinter Canvas Widget from PySimpleGUI, follow these steps:
|
||||||
* Add Canvas Element to your window
|
* Add Canvas Element to your window
|
||||||
|
@ -4553,8 +4607,7 @@ Parameter Descriptions:
|
||||||
|bottom_right|Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle|
|
|bottom_right|Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle|
|
||||||
|extent|(float) Andle to end drawing. Used in conjunction with start_angle|
|
|extent|(float) Andle to end drawing. Used in conjunction with start_angle|
|
||||||
|start_angle|(float) Angle to begin drawing. Used in conjunction with extent|
|
|start_angle|(float) Angle to begin drawing. Used in conjunction with extent|
|
||||||
|style|(str) Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last',
|
|style|(str) Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last', 'butt', 'projecting', 'round', 'bevel', 'miter'|
|
||||||
'butt', 'projecting', 'round', 'bevel', 'miter'|
|
|
||||||
|arc_color|(str) color to draw arc with|
|
|arc_color|(str) color to draw arc with|
|
||||||
|||
|
|||
|
||||||
| **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the arc |
|
| **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the arc |
|
||||||
|
@ -4760,17 +4813,21 @@ Changes some of the settings for the Table Element. Must call `Window.Read` or `
|
||||||
Update(values=None,
|
Update(values=None,
|
||||||
num_rows=None,
|
num_rows=None,
|
||||||
visible=None,
|
visible=None,
|
||||||
select_rows=None)
|
select_rows=None,
|
||||||
|
alternating_row_color=None,
|
||||||
|
row_colors=None)
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameter Descriptions:
|
Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|values||
|
|values|List[List[Any]] A new 2-dimensional table to show|
|
||||||
|num_rows||
|
|num_rows|(int) How many rows to display at a time|
|
||||||
|visible|(bool) control visibility of element|
|
|visible|(bool) if True then will be visible|
|
||||||
|select_rows||
|
|select_rows|List[int] List of rows to select as if user did|
|
||||||
|
|alternating_row_color|(str) the color to make every other row|
|
||||||
|
|row_colors|List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)|
|
||||||
|
|
||||||
---
|
---
|
||||||
### Known visualization problem....
|
### Known visualization problem....
|
||||||
|
@ -5001,37 +5058,28 @@ Parameter Descriptions:
|
||||||
|
|
||||||
### Reading Tab Groups
|
### Reading Tab Groups
|
||||||
|
|
||||||
Tab Groups now return a value when a Read returns. They return which tab is currently selected. There is also a change_submits parameter that can be set that causes a Read to return if a Tab in that group is selected / changed. The key or title belonging to the Tab that was switched to will be returned as the value
|
Tab Groups now return a value when a Read returns. They return which tab is currently selected. There is also a `enable_events` parameter that can be set that causes a Read to return if a Tab in that group is selected / changed. The key or title belonging to the Tab that was switched to will be returned as the value
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior
|
Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior
|
||||||
|
|
||||||
```
|
```
|
||||||
Update(values=None,
|
Update(disabled=None, visible=None)
|
||||||
key=None,
|
|
||||||
value=None,
|
|
||||||
text=None,
|
|
||||||
icon=None,
|
|
||||||
visible=None)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameter Descriptions:
|
Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|values||
|
|disabled|(bool) disable or enable state of the element|
|
||||||
|key|Used with window.FindElement and with return values to uniquely identify this element|
|
|
||||||
|value||
|
|
||||||
|text||
|
|
||||||
|icon||
|
|
||||||
|visible|(bool) control visibility of element|
|
|visible|(bool) control visibility of element|
|
||||||
|
|
||||||
## Pane Element
|
## Pane Element
|
||||||
|
|
||||||
New in version 3.20 is the Pane Element, a super-cool tkinter feature. You won't find this one in PySimpleGUIQt, only PySimpleGUI. It's difficult to describe one of these things. Think of them as "Tabs without labels" that you can slide.
|
New in version 3.20 is the Pane Element, a super-cool tkinter feature. You won't find this one in PySimpleGUIQt, only PySimpleGUI. It's difficult to describe one of these things. Think of them as "Tabs without labels" that you can slide.
|
||||||
|
|
||||||
A sliding Pane that is unique to tkinter
|
A sliding Pane that is unique to tkinter. Uses Columns to create individual panes
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -5053,17 +5101,17 @@ Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|pane_list||
|
|pane_list|List[Column] Must be a list of Column Elements. Each Column supplied becomes one pane that's shown|
|
||||||
|background_color|color of background|
|
|background_color|(str) color of background|
|
||||||
|size|(w,h) w=characters-wide, h=rows-high|
|
|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high How much room to reserve for the Pane|
|
||||||
|pad|Amount of padding to put around element|
|
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
||||||
|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')|
|
|orientation|(str) 'horizontal' or 'vertical' or ('h' or 'v'). Direction the Pane should slide|
|
||||||
|show_handle|(Default = True)|
|
|show_handle|(bool) if True, the handle is drawn that makes it easier to grab and slide|
|
||||||
|relief|relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`|
|
|relief|(enum) relief style. Values are same as other elements that use relief values. `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`|
|
||||||
|handle_size||
|
|handle_size|(int) Size of the handle in pixels|
|
||||||
|border_width|width of border around element|
|
|border_width|(int) width of border around element in pixels|
|
||||||
|key|Used with window.FindElement and with return values to uniquely identify this element|
|
|key|(any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window|
|
||||||
|visible|set visibility state of the element (Default = True)|
|
|visible|(bool) set visibility state of the element|
|
||||||
|
|
||||||
***Each "Pane" of a Pane Element must be a Column Element***. The parameter `pane_list` is a list of Column Elements.
|
***Each "Pane" of a Pane Element must be a Column Element***. The parameter `pane_list` is a list of Column Elements.
|
||||||
|
|
||||||
|
@ -5373,7 +5421,7 @@ layout = [[sg.Text('Persistent window')],
|
||||||
[sg.Input()],
|
[sg.Input()],
|
||||||
[sg.RButton('Read'), sg.Exit()]]
|
[sg.RButton('Read'), sg.Exit()]]
|
||||||
|
|
||||||
window = sg.Window('Window that stays open', layout)
|
window = sg.Window('Window that stays open').Layout(layout)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
@ -5441,18 +5489,18 @@ TIMEOUT_KEY = '__timeout__'
|
||||||
If you wanted to test for "no event" in your loop, it would be written like this:
|
If you wanted to test for "no event" in your loop, it would be written like this:
|
||||||
```python
|
```python
|
||||||
while True:
|
while True:
|
||||||
event, value = window.Read(timeout=100)
|
event, value = window.Read(timeout=0)
|
||||||
if event is None:
|
if event is None:
|
||||||
break # the use has closed the window
|
break # the use has closed the window
|
||||||
if event == sg.TIMEOUT_KEY:
|
if event == sg.TIMEOUT_KEY:
|
||||||
print("No event happened")
|
print("Nothing happened")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a sleep in your loop, you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly.
|
||||||
|
|
||||||
|
Non-blocking is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine.
|
||||||
|
|
||||||
Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over.
|
There is a hybrid approach... a read with a timeout. You'll score much higher points on the impressive meter if you're able to use a lot less CPU time by using this type of read.
|
||||||
|
|
||||||
If you have a ZERO timeout value in the `Read` call in your loop, you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Set your `timeout` parameter to a non-zero value like 100 which is going to return to you every 100 ms. That's a reasonable number to use as you're likely not thrashing the CPU.
|
|
||||||
|
|
||||||
The most legit time to use a non-blocking window is when you're working directly with hardware. Maybe you're driving a serial bus. If you look at the Event Loop in the Demo_OpenCV_Webcam.py program, you'll see that the read is a non-blocking read. However, there is a place in the event loop where blocking occurs. The point in the loop where you will block is the call to read frames from the webcam. When a frame is available you want to quickly deliver it to the output device, so you don't want your GUI blocking. You want the read from the hardware to block.
|
The most legit time to use a non-blocking window is when you're working directly with hardware. Maybe you're driving a serial bus. If you look at the Event Loop in the Demo_OpenCV_Webcam.py program, you'll see that the read is a non-blocking read. However, there is a place in the event loop where blocking occurs. The point in the loop where you will block is the call to read frames from the webcam. When a frame is available you want to quickly deliver it to the output device, so you don't want your GUI blocking. You want the read from the hardware to block.
|
||||||
|
|
||||||
|
@ -5496,7 +5544,7 @@ layout = [[sg.Text('')],
|
||||||
sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'),
|
sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'),
|
||||||
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
|
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
|
||||||
|
|
||||||
window = sg.Window('Running Timer', layout, no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True)
|
window = sg.Window('Running Timer', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True).Layout(layout)
|
||||||
|
|
||||||
# ---------------- main loop ----------------
|
# ---------------- main loop ----------------
|
||||||
current_time = 0
|
current_time = 0
|
||||||
|
@ -5514,9 +5562,9 @@ while (True):
|
||||||
|
|
||||||
Previously this program was implemented using a sleep in the loop to control the clock tick. This version uses the new timeout parameter. The result is a window that reacts quicker then the one with the sleep and the accuracy is just as good.
|
Previously this program was implemented using a sleep in the loop to control the clock tick. This version uses the new timeout parameter. The result is a window that reacts quicker then the one with the sleep and the accuracy is just as good.
|
||||||
|
|
||||||
## Instead of a Non-blocking Read --- Use `change_submits = True` or `return_keyboard_events = True`
|
## Instead of a Non-blocking Read --- Use `enable_events = True` or `return_keyboard_events = True`
|
||||||
|
|
||||||
Any time you are thinking "I want an X Element to cause a Y Element to do something", then you want to use the `change_submits` option.
|
Any time you are thinking "I want an X Element to cause a Y Element to do something", then you want to use the `enable_events` option.
|
||||||
|
|
||||||
***Instead of polling, try options that cause the window to return to you.*** By using non-blocking windows, you are *polling*. You can indeed create your application by polling. It will work. But you're going to be maxing out your processor and may even take longer to react to an event than if you used another technique.
|
***Instead of polling, try options that cause the window to return to you.*** By using non-blocking windows, you are *polling*. You can indeed create your application by polling. It will work. But you're going to be maxing out your processor and may even take longer to react to an event than if you used another technique.
|
||||||
|
|
||||||
|
@ -5540,7 +5588,7 @@ import PySimpleGUI as sg
|
||||||
layout = [ [sg.Text('My layout', key='_TEXT_')],
|
layout = [ [sg.Text('My layout', key='_TEXT_')],
|
||||||
[sg.Button('Read')]]
|
[sg.Button('Read')]]
|
||||||
|
|
||||||
window = sg.Window('My new window', layout)
|
window = sg.Window('My new window').Layout(layout)
|
||||||
|
|
||||||
while True: # Event Loop
|
while True: # Event Loop
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
@ -5559,7 +5607,7 @@ layout = [ [sg.Text('My layout', key='_TEXT_')],
|
||||||
[sg.Button('Read')]
|
[sg.Button('Read')]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = sg.Window('My new window', layout).Finalize()
|
window = sg.Window('My new window').Layout(layout).Finalize()
|
||||||
|
|
||||||
window.Element('_TEXT_').Update('My new text value')
|
window.Element('_TEXT_').Update('My new text value')
|
||||||
|
|
||||||
|
@ -5598,7 +5646,7 @@ layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_
|
||||||
sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
|
sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
|
||||||
|
|
||||||
sz = fontSize
|
sz = fontSize
|
||||||
window = sg.Window("Font size selector", layout, grab_anywhere=False)
|
window = sg.Window("Font size selector", grab_anywhere=False).Layout(layout)
|
||||||
# Event Loop
|
# Event Loop
|
||||||
while True:
|
while True:
|
||||||
event, values= window.Read()
|
event, values= window.Read()
|
||||||
|
@ -5711,6 +5759,21 @@ Use realtime keyboard capture by calling
|
||||||
|
|
||||||
Beginning in version 3.01 you can add a MenuBar to your window. You specify the menus in much the same way as you do window layouts, with lists. Menu selections are returned as events and as of 3.17, also as in the values dictionary. The value returned will be the entire menu entry, including the key if you specified one.
|
Beginning in version 3.01 you can add a MenuBar to your window. You specify the menus in much the same way as you do window layouts, with lists. Menu selections are returned as events and as of 3.17, also as in the values dictionary. The value returned will be the entire menu entry, including the key if you specified one.
|
||||||
|
|
||||||
|
Menu Element is the Element that provides a Menu Bar that goes across the top of the window, just below titlebar.
|
||||||
|
Here is an example layout. The "&" are shortcut keys ALT+key.
|
||||||
|
Is a List of - "Item String" + List
|
||||||
|
Where Item String is what will be displayed on the Menubar itself.
|
||||||
|
The List that follows the item represents the items that are shown then Menu item is clicked
|
||||||
|
Notice how an "entry" in a mennu can be a list which means it branches out and shows another menu, etc. (resursive)
|
||||||
|
menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']],
|
||||||
|
['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ],
|
||||||
|
['&Debugger', ['Popout', 'Launch Debugger']],
|
||||||
|
['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']],
|
||||||
|
['&Help', '&About...'], ]
|
||||||
|
Finally, "keys" can be added to entires so make them unique. The "Save" entry has a key associated with it. You
|
||||||
|
can see it has a "::" which signifies the beginning of a key. The user will not see the key portion when the
|
||||||
|
menu is shown. The key portion is returned as part of the event.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
menu_def = [['File', ['Open', 'Save', 'Exit',]],
|
menu_def = [['File', ['Open', 'Save', 'Exit',]],
|
||||||
['Edit', ['Paste', ['Special', 'Normal',], 'Undo'],],
|
['Edit', ['Paste', ['Special', 'Normal',], 'Undo'],],
|
||||||
|
@ -5723,7 +5786,7 @@ Note the placement of ',' and of []. It's tricky to get the nested menus correc
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
Update a menubar - can change the menu definition and visibility
|
Update a menubar - can change the menu definition and visibility. The entire menu has to be specified
|
||||||
|
|
||||||
```
|
```
|
||||||
Update(menu_definition=None, visible=None)
|
Update(menu_definition=None, visible=None)
|
||||||
|
@ -5733,7 +5796,7 @@ Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|menu_definition|List[[str]] New menu defintion|
|
|menu_definition|List[List[Tuple[str, List[str]]]|
|
||||||
|visible|(bool) control visibility of element|
|
|visible|(bool) control visibility of element|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -5827,7 +5890,7 @@ layout = [[ sg.Text('Window 1'),],
|
||||||
[sg.Text('', key='_OUTPUT_')],
|
[sg.Text('', key='_OUTPUT_')],
|
||||||
[sg.Button('Launch 2'), sg.Button('Exit')]]
|
[sg.Button('Launch 2'), sg.Button('Exit')]]
|
||||||
|
|
||||||
win1 = sg.Window('Window 1', layout)
|
win1 = sg.Window('Window 1').Layout(layout)
|
||||||
|
|
||||||
win2_active = False
|
win2_active = False
|
||||||
while True:
|
while True:
|
||||||
|
@ -5841,7 +5904,7 @@ while True:
|
||||||
layout2 = [[sg.Text('Window 2')],
|
layout2 = [[sg.Text('Window 2')],
|
||||||
[sg.Button('Exit')]]
|
[sg.Button('Exit')]]
|
||||||
|
|
||||||
win2 = sg.Window('Window 2', layout2)
|
win2 = sg.Window('Window 2').Layout(layout2)
|
||||||
|
|
||||||
if win2_active:
|
if win2_active:
|
||||||
ev2, vals2 = win2.Read(timeout=100)
|
ev2, vals2 = win2.Read(timeout=100)
|
||||||
|
@ -5862,7 +5925,7 @@ layout = [[ sg.Text('Window 1'),],
|
||||||
[sg.Text('', key='_OUTPUT_')],
|
[sg.Text('', key='_OUTPUT_')],
|
||||||
[sg.Button('Launch 2')]]
|
[sg.Button('Launch 2')]]
|
||||||
|
|
||||||
win1 = sg.Window('Window 1', layout)
|
win1 = sg.Window('Window 1').Layout(layout)
|
||||||
win2_active=False
|
win2_active=False
|
||||||
while True:
|
while True:
|
||||||
ev1, vals1 = win1.Read(timeout=100)
|
ev1, vals1 = win1.Read(timeout=100)
|
||||||
|
@ -5876,7 +5939,7 @@ while True:
|
||||||
layout2 = [[sg.Text('Window 2')], # note must create a layout from scratch every time. No reuse
|
layout2 = [[sg.Text('Window 2')], # note must create a layout from scratch every time. No reuse
|
||||||
[sg.Button('Exit')]]
|
[sg.Button('Exit')]]
|
||||||
|
|
||||||
win2 = sg.Window('Window 2', layout2)
|
win2 = sg.Window('Window 2').Layout(layout2)
|
||||||
while True:
|
while True:
|
||||||
ev2, vals2 = win2.Read()
|
ev2, vals2 = win2.Read()
|
||||||
if ev2 is None or ev2 == 'Exit':
|
if ev2 is None or ev2 == 'Exit':
|
||||||
|
|
277
readme.md
277
readme.md
|
@ -1275,7 +1275,8 @@ With a little trickery you can provide a way to break out of your loop using the
|
||||||
***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.
|
***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.
|
||||||
|
|
||||||
# Debug Output
|
# Debug Output
|
||||||
Another call in the 'Easy' families of APIs is `EasyPrint`. It will output to a debug window. If the debug window isn't open, then the first call will open it. No need to do anything but stick a 'print' call in your code. You can even replace your 'print' calls with calls to EasyPrint by simply sticking the statement
|
|
||||||
|
Another call in the 'Easy' families of APIs is `EasyPrint`. As is with other commonly used PySimpleGUI calls, there are other names for the same call. You can use `Print` or `eprint` in addition to `EasyPrint`. They all do the same thing, output to a debug window. If the debug window isn't open, then the first call will open it. No need to do anything but stick an 'sg.Print' call in your code. You can even replace your 'print' calls with calls to EasyPrint by simply sticking the statement
|
||||||
|
|
||||||
```python
|
```python
|
||||||
print = sg.EasyPrint
|
print = sg.EasyPrint
|
||||||
|
@ -1283,7 +1284,7 @@ print = sg.EasyPrint
|
||||||
|
|
||||||
at the top of your code.
|
at the top of your code.
|
||||||
|
|
||||||
There are a number of names for the same EasyPrint function. `Print` is one of the better ones to use as it's easy to remember. It is simply `print` with a capital P.
|
`Print` is one of the better ones to use as it's easy to remember. It is simply `print` with a capital P. `sg.Print('this will go to the debug window')`
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
@ -1308,22 +1309,22 @@ Just like the standard print call, `EasyPrint` supports the `sep` and `end` keyw
|
||||||
|
|
||||||
You can change the size of the debug window using the `SetOptions` call with the `debug_win_size` parameter.
|
You can change the size of the debug window using the `SetOptions` call with the `debug_win_size` parameter.
|
||||||
|
|
||||||
There is an option to tell PySimpleGUI to reroute all of your stdout and stderr output to this window. To do so call EasyPrint with the parameter `do_not_reroute_stdout` set to True. After calling it once with this parameter set to True, all future calls to a normal`print` will go to the debug window.
|
There is an option to tell PySimpleGUI to reroute all of your stdout and stderr output to this window. To do so call EasyPrint with the parameter `do_not_reroute_stdout` set to `False`. After calling it once with this parameter set to True, all future calls to a normal`print` will go to the debug window.
|
||||||
|
|
||||||
If you close the debug window it will re-open the next time you Print to it.
|
If you close the debug window it will re-open the next time you Print to it. If you wish to close the window using your code, then you can call either `EasyPrintClose()` or `PrintClose()`
|
||||||
|
|
||||||
---
|
---
|
||||||
# Custom window API Calls (Your First window)
|
# Custom window API Calls (Your First window)
|
||||||
|
|
||||||
This is the FUN part of the programming of this GUI. In order to really get the most out of the API, you should be using an IDE that supports auto complete or will show you the definition of the function. This will make customizing go smoother.
|
This is the FUN part of the programming of this GUI. In order to really get the most out of the API, you should be using an IDE that supports auto complete or will show you the definition of the function. This will make customizing go smoother.
|
||||||
|
|
||||||
This first section on custom windows is for your typical, blocking, non-persistent window. By this I mean, when you "show" the window, the function will not return until the user has clicked a button or closed the window. When this happens, the window will be automatically closed.
|
This first section on custom windows is for your typical, blocking, non-persistent window. By this I mean, when you "show" the window, the function will not return until the user has clicked a button or closed the window with an X.
|
||||||
|
|
||||||
Two other types of windows exist.
|
Two other types of windows exist.
|
||||||
1. Persistent window - rather than closing on button clicks, the show window function returns and the window continues to be visible. This is good for applications like a chat window.
|
1. Persistent window - the `Window.Read()` method returns and the window continues to be visible. This is good for applications like a chat window or a timer or anything that stays active on the screen for a while.
|
||||||
2. Asynchronous window - the trickiest of the lot. Great care must be exercised. Examples are an MP3 player or status dashboard. Async windows are updated (refreshed) on a periodic basis.
|
2. Asynchronous window - the trickiest of the lot. Great care must be exercised. Examples are an MP3 player or status dashboard. Async windows are updated (refreshed) on a periodic basis. You can spot them easily as they will have a `timeout` parameter on the call to read. `event, values = window.Read(timeout=100)`
|
||||||
|
|
||||||
It's both not enjoyable nor helpful to immediately jump into tweaking each and every little thing available to you.
|
It's both not enjoyable nor helpful to immediately jump into tweaking each and every little thing available to you. Make some simple windows. Use the Cookbook and the Demo Programs as a way to learn and as a "starting point".
|
||||||
|
|
||||||
## The window Designer
|
## The window Designer
|
||||||
|
|
||||||
|
@ -1390,11 +1391,13 @@ layout = [[sg.Text('Enter a Number')],
|
||||||
[sg.Input()],
|
[sg.Input()],
|
||||||
[sg.OK()] ]
|
[sg.OK()] ]
|
||||||
|
|
||||||
event, (number,) = sg.Window('Enter a number example', layout).Read()
|
event, values = sg.Window('Enter a number example', layout).Read()
|
||||||
|
|
||||||
sg.Popup(event, number)
|
sg.Popup(event, values[0])
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Your call to `Read` will return a dictionary, but will "look like a list" in how you access it. The first input field will be entry 0, the next one is 1, etc. Later you'll learn about the `key` parameter which allows you to use your own values to identify elements instead of them being numbered for you.
|
||||||
|
|
||||||
### Example 2 - Get a filename
|
### Example 2 - Get a filename
|
||||||
Let's say you've got a utility you've written that operates on some input file and you're ready to use a GUI to enter than filename rather than the command line. Follow the same steps as the previous example - draw your window on paper, break it up into rows, label the elements.
|
Let's say you've got a utility you've written that operates on some input file and you're ready to use a GUI to enter than filename rather than the command line. Follow the same steps as the previous example - draw your window on paper, break it up into rows, label the elements.
|
||||||
|
|
||||||
|
@ -1410,9 +1413,9 @@ layout = [[sg.Text('Filename')],
|
||||||
[sg.Input(), sg.FileBrowse()],
|
[sg.Input(), sg.FileBrowse()],
|
||||||
[sg.OK(), sg.Cancel()] ]
|
[sg.OK(), sg.Cancel()] ]
|
||||||
|
|
||||||
event, (number,) = sg.Window('Get filename example', layout).Read()
|
event, values = sg.Window('Get filename example', layout).Read()
|
||||||
|
|
||||||
sg.Popup(event, number)
|
sg.Popup(event, values[0])
|
||||||
```
|
```
|
||||||
|
|
||||||
Read on for detailed instructions on the calls that show the window and return your results.
|
Read on for detailed instructions on the calls that show the window and return your results.
|
||||||
|
@ -1421,25 +1424,25 @@ Read on for detailed instructions on the calls that show the window and return y
|
||||||
|
|
||||||
All of your PySimpleGUI programs will utilize one of these 2 design patterns depending on the type of window you're implementing.
|
All of your PySimpleGUI programs will utilize one of these 2 design patterns depending on the type of window you're implementing.
|
||||||
|
|
||||||
## Pattern 1 - "One-shot Window" - Read into list or dictionary (**The Most Common** Pattern)
|
## Pattern 1 - "One-shot Window" - Read a window one time then close it
|
||||||
|
|
||||||
This will be the most common pattern you'll follow if you are not using an "event loop" (not reading the window multiple times). The window is read and closes.
|
This will be the most common pattern you'll follow if you are not using an "event loop" (not reading the window multiple times). The window is read and closed.
|
||||||
|
|
||||||
It's unusual to assign the values returned from the read call directly into user variables. Usually the variables are grouped together into a list or dictionary of multiple return values.
|
The input fields in your window will be returned to you as a dictionary (syntactically it looks just like a list lookup)
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
window_rows = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
|
layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')],
|
||||||
[sg.InputText(), sg.FileBrowse()],
|
[sg.InputText(), sg.FileBrowse()],
|
||||||
[sg.Submit(), sg.Cancel()]]
|
[sg.Submit(), sg.Cancel()]]
|
||||||
|
|
||||||
window = sg.Window('SHA-1 & 256 Hash', window_rows)
|
window = sg.Window('SHA-1 & 256 Hash', layout)
|
||||||
|
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
window.Close()
|
window.Close()
|
||||||
|
|
||||||
source_filename = values[0]
|
source_filename = values[0] # the first input element is values[0]
|
||||||
```
|
```
|
||||||
|
|
||||||
## Pattern 2 A - Persistent window (multiple reads using an event loop)
|
## Pattern 2 A - Persistent window (multiple reads using an event loop)
|
||||||
|
@ -1452,7 +1455,7 @@ This code will present a window and will print values until the user clicks the
|
||||||
import PySimpleGUI as sg
|
import PySimpleGUI as sg
|
||||||
|
|
||||||
layout = [[sg.Text('Persistent window')],
|
layout = [[sg.Text('Persistent window')],
|
||||||
[sg.Input(do_not_clear=True)],
|
[sg.Input()],
|
||||||
[sg.Button('Read'), sg.Exit()]]
|
[sg.Button('Read'), sg.Exit()]]
|
||||||
|
|
||||||
window = sg.Window('Window that stays open', layout)
|
window = sg.Window('Window that stays open', layout)
|
||||||
|
@ -1468,11 +1471,13 @@ window.Close()
|
||||||
|
|
||||||
## Pattern 2 B - Persistent window (multiple reads using an event loop + updates data in window)
|
## Pattern 2 B - Persistent window (multiple reads using an event loop + updates data in window)
|
||||||
|
|
||||||
This is a slightly more complex, but maybe more realistic version that reads input from the user and displays that input as text in the window. Your program is likely to be doing both of those activities so this will give you a big jump-start.
|
This is a slightly more complex, but maybe more realistic version that reads input from the user and displays that input as text in the window. Your program is likely to be doing both of those activities (input and output) so this will give you a big jump-start.
|
||||||
|
|
||||||
Do not worry yet what all of these statements mean. Just copy it so you can begin to play with it, make some changes. Experiment to see how thing work.
|
Do not worry yet what all of these statements mean. Just copy it so you can begin to play with it, make some changes. Experiment to see how thing work.
|
||||||
|
|
||||||
A final note... the parameter `do_not_clear` in the input call determines the action of the input field after a button event. If this value is True, the input value remains visible following button clicks. If False, then the input field is CLEARED of whatever was input. If you are building a "Form" type of window with data entry, you likely want False, the default setting (you can remove the parameter completely).
|
A final note... the parameter `do_not_clear` in the input call determines the action of the input field after a button event. If this value is True, the input value remains visible following button clicks. If False, then the input field is CLEARED of whatever was input. If you are building a "Form" type of window with data entry, you likely want False. The default is to NOT clear the input element (`do_not_clear=True`).
|
||||||
|
|
||||||
|
This example introduces the concept of "keys". Keys are super important in PySimpleGUI as they enable you to identify and work with Elements using names you want to use. Keys can be ANYTHING, except `None`. To access an input element's data that is read in the example below, you will use `values['_IN_']` instead of `values[0]` like before.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import sys
|
import sys
|
||||||
|
@ -1482,7 +1487,7 @@ else:
|
||||||
import PySimpleGUI27 as sg
|
import PySimpleGUI27 as sg
|
||||||
|
|
||||||
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ],
|
layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ],
|
||||||
[sg.Input(do_not_clear=True, key='_IN_')],
|
[sg.Input(key='_IN_')],
|
||||||
[sg.Button('Show'), sg.Button('Exit')]]
|
[sg.Button('Show'), sg.Button('Exit')]]
|
||||||
|
|
||||||
window = sg.Window('Window Title', layout)
|
window = sg.Window('Window Title', layout)
|
||||||
|
@ -1499,6 +1504,12 @@ while True: # Event Loop
|
||||||
window.Close()
|
window.Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Qt Designer
|
||||||
|
|
||||||
|
There actually is a PySimpleGUI Window Designer that uses Qt's window designer. It's outside the scope of this document however. You'll find the project here: https://github.com/nngogol/PySimpleGUIDesigner
|
||||||
|
|
||||||
|
I hope to start using it more soon.
|
||||||
|
|
||||||
## How GUI Programming in Python Should Look? At least for beginners ?
|
## How GUI Programming in Python Should Look? At least for beginners ?
|
||||||
|
|
||||||
While one goal was making it simple to create a GUI another just as important goal was to do it in a Pythonic manner. Whether it achieved these goals is debatable, but it was an attempt just the same.
|
While one goal was making it simple to create a GUI another just as important goal was to do it in a Pythonic manner. Whether it achieved these goals is debatable, but it was an attempt just the same.
|
||||||
|
@ -1518,6 +1529,9 @@ layout = [[sg.Text('Rename files or folders')],
|
||||||
window = sg.Window('Rename Files or Folders', layout)
|
window = sg.Window('Rename Files or Folders', layout)
|
||||||
|
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
|
||||||
|
folder_path, file_path = values[0], values[1] # get the data from the values dictionary
|
||||||
|
print(folder_path, file_path)
|
||||||
```
|
```
|
||||||
|
|
||||||

|

|
||||||
|
@ -1543,20 +1557,20 @@ And what about those return values? Most people simply want to show a window, g
|
||||||
|
|
||||||
For return values the window is scanned from top to bottom, left to right. Each field that's an input field will occupy a spot in the return values.
|
For return values the window is scanned from top to bottom, left to right. Each field that's an input field will occupy a spot in the return values.
|
||||||
|
|
||||||
In our example window, there are 2 fields, so the return values from this window will be a list with 2 values in it.
|
In our example window, there are 2 fields, so the return values from this window will be a dictionary with 2 values in it. Remember, if you do not specify a `key` when creating an element, one will be created for you. They are ints starting with 0. In this example, we have 2 input elements. They will be addressable as values[0] and values[1]
|
||||||
|
|
||||||
```python
|
```python
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
folder_path, file_path = values
|
folder_path, file_path = values[0], values[1]
|
||||||
```
|
```
|
||||||
|
|
||||||
In one statement we both show the window and read the user's inputs. In the next the *list* of return values is split into individual variables `folder_path` and `file_path`.
|
In one statement we both show the window and read the user's inputs. In the next line of code the *dictionary* of return values is split into individual variables `folder_path` and `file_path`.
|
||||||
|
|
||||||
Isn't this what a Python programmer looking for a GUI wants? Something easy to work with to get the values and move on to the rest of the program, where the real action is taking place. Why write pages of GUI code when the same layout can be achieved with PySimpleGUI in 3 or 4 lines of code. 4 lines or 40? Most would choose 4.
|
Isn't this what a Python programmer looking for a GUI wants? Something easy to work with to get the values and move on to the rest of the program, where the real action is taking place. Why write pages of GUI code when the same layout can be achieved with PySimpleGUI in 3 or 4 lines of code. 4 lines or 40? Most would choose 4.
|
||||||
|
|
||||||
## Return values
|
## Return values
|
||||||
|
|
||||||
As of version 2.8 there are 2 forms of return values, list and dictionary.
|
There are 2 return values from a call to `Window.Read()`, an `event` that caused the `Read` to return and `values` a list or dictionary of values. If there are no elements with keys in the layout, then it will be a list. However, some elements, like some buttons, have a key automatically added to them. **It's best to use keys on all of your input type elements.**
|
||||||
|
|
||||||
### Two Return Values
|
### Two Return Values
|
||||||
|
|
||||||
|
@ -1566,7 +1580,7 @@ All Window Read calls return 2 values. By convention a read statement is writte
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
```
|
```
|
||||||
|
|
||||||
You don't HAVE to write your reads in this way. You can name your variables however you want. But if you want to code them in a way that other programmers using PySimpleGUI are used to, then use these statements.
|
You don't HAVE to write your reads in this way. You can name your variables however you want. But if you want to code them in a way that other programmers using PySimpleGUI are used to, then use this statement.
|
||||||
|
|
||||||
## Events
|
## Events
|
||||||
|
|
||||||
|
@ -1595,7 +1609,9 @@ For Windows that have specifically enabled these. Please see the appropriate se
|
||||||
|
|
||||||
### Window closed event
|
### Window closed event
|
||||||
|
|
||||||
Another convention to follow is the check for windows being closed with an X. This is an important event to catch. If you don't check for this and you attempt to use the window, your program will crash. Please check for closed window and exit your program gracefully.
|
Another convention to follow is the check for windows being closed with an X. *This is an important event to catch*. If you don't check for this and you attempt to use the window, your program will crash. Please check for closed window and exit your program gracefully. Your users will like you for it.
|
||||||
|
|
||||||
|
Close your windows when you're done with them even though exiting the program will also close them. tkinter can generate an error/warning sometimes if you don't close the window.
|
||||||
|
|
||||||
To check for a closed window use this line of code:
|
To check for a closed window use this line of code:
|
||||||
|
|
||||||
|
@ -1610,7 +1626,25 @@ while True:
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
if event is None:
|
if event is None:
|
||||||
break
|
break
|
||||||
|
window.Close()
|
||||||
```
|
```
|
||||||
|
|
||||||
|
You will very often see the examples and demo programs write this check as:
|
||||||
|
|
||||||
|
```python
|
||||||
|
event, values = window.Read()
|
||||||
|
if event in (None, 'Exit'):
|
||||||
|
break
|
||||||
|
```
|
||||||
|
|
||||||
|
This if statement is the same as:
|
||||||
|
```python
|
||||||
|
if event is None or event == 'Exit':
|
||||||
|
break
|
||||||
|
```
|
||||||
|
|
||||||
|
Instead of `'Exit'` use the name of the button you want to exit the window (Cancel, Quit, etc)
|
||||||
|
|
||||||
### Button Click Events
|
### Button Click Events
|
||||||
|
|
||||||
By default buttons will always return a click event, or in the case of realtime buttons, a button down event. You don't have to do anything to enable button clicks. To disable the events, disable the button using its Update method.
|
By default buttons will always return a click event, or in the case of realtime buttons, a button down event. You don't have to do anything to enable button clicks. To disable the events, disable the button using its Update method.
|
||||||
|
@ -1875,6 +1909,8 @@ You can learn more about these async / non-blocking windows toward the end of th
|
||||||
# Window Object - Beginning a window
|
# Window Object - Beginning a window
|
||||||
The first step is to create the window object using the desired window customization.
|
The first step is to create the window object using the desired window customization.
|
||||||
|
|
||||||
|
**IMPORTANT** - Many of the `Window` methods require you to either call `Window.Read` or `Window.Finalize` before you call the method. This is because these 2 calls are what actually creates the window using the underlying GUI Framework. Prior to one of those calls, the methods are likely to crash as they will not yet have their underlying widgets created.
|
||||||
|
|
||||||
Represents a single Window
|
Represents a single Window
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -2187,7 +2223,7 @@ Minimize()
|
||||||
|
|
||||||
Move the upper left corner of this window to the x,y coordinates provided
|
Move the upper left corner of this window to the x,y coordinates provided
|
||||||
|
|
||||||
```python
|
```
|
||||||
Move(x, y)
|
Move(x, y)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -2366,9 +2402,9 @@ To keep a window on top of all other windows on the screen, set keep_on_top = Tr
|
||||||
|
|
||||||
PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call.
|
PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call.
|
||||||
|
|
||||||
## Window Methods
|
## Window Methods That Complete Formation of Window
|
||||||
|
|
||||||
There are a number of operations you can do on a window after you've created the window. You call these after creating your Windows object.
|
There are a number of operations you can do on a window after you've created the window. You call these after creating your Windows object. Most Window methods are not usable until you call one of these.
|
||||||
|
|
||||||
#### Layout(rows)
|
#### Layout(rows)
|
||||||
|
|
||||||
|
@ -2394,9 +2430,9 @@ If you set the timeout = 0, then the Read will immediately return rather than wa
|
||||||
|
|
||||||
#### ReadNonBlocking() (NO LONGER USED)
|
#### ReadNonBlocking() (NO LONGER USED)
|
||||||
|
|
||||||
While this call will technically still work, it is being removed. If you want to get the same result, call Read with timeout = 0.
|
Some of the old code examples showed calling this function. You should now call it now. If you want to get the same result, call Read with `timeout = 0`.
|
||||||
|
|
||||||
The only time you will see this call is in OLD CODE. Please file an Issue if you see this call in any code or in any documentation. It must go away never to be seen again.
|
Please file an Issue if you see this call in any code or in any documentation. It must go away never to be seen again.
|
||||||
|
|
||||||
# Elements
|
# Elements
|
||||||
"Elements" are the building blocks used to create windows. Some GUI APIs use the term "Widget" to describe these graphic elements.
|
"Elements" are the building blocks used to create windows. Some GUI APIs use the term "Widget" to describe these graphic elements.
|
||||||
|
@ -2443,19 +2479,26 @@ Some parameters that you will see on almost all Elements are:
|
||||||
- colors - Color name or #RRGGBB string
|
- colors - Color name or #RRGGBB string
|
||||||
- pad - Amount of padding to put around element
|
- pad - Amount of padding to put around element
|
||||||
- enable_events - Turns on the element specific events
|
- enable_events - Turns on the element specific events
|
||||||
|
- visible - Make elements appear and disappear
|
||||||
|
|
||||||
#### Tooltip
|
#### Tooltip
|
||||||
Tooltips are text boxes that popup next to an element if you hold your mouse over the top of it. If you want to be extra kind to your window's user, then you can create tooltips for them by setting the parameter `tooltip` to some text string. You will need to supply your own line breaks / text wrapping. If you don't want to manually add them, then take a look at the standard library package `textwrap`.
|
Tooltips are text boxes that popup next to an element if you hold your mouse over the top of it. If you want to be extra kind to your window's user, then you can create tooltips for them by setting the parameter `tooltip` to some text string. You will need to supply your own line breaks / text wrapping. If you don't want to manually add them, then take a look at the standard library package `textwrap`.
|
||||||
|
|
||||||
Tooltips are one of those "polish" items that really dress-up a GUI and show's a level of sophistication. Go ahead, impress people, throw some tooltips into your GUI.
|
Tooltips are one of those "polish" items that really dress-up a GUI and show's a level of sophistication. Go ahead, impress people, throw some tooltips into your GUI. You can change the color of the background of the tooltip on the tkinter version of PySimpleGUI by setting `TOOLTIP_BACKGROUND_COLOR` to the color string of your choice. The default value for the color is:
|
||||||
|
`TOOLTIP_BACKGROUND_COLOR = "#ffffe0"`
|
||||||
|
|
||||||
#### Size
|
#### Size
|
||||||
Specifies the amount of room reserved for the Element. For elements that are character based, such a Text, it is (# characters, # rows). Sometimes it is a pixel measurement such as the Image element. And sometimes a mix like on the Slider element (characters long by pixels wide).
|
Specifies the amount of room reserved for the Element. For elements that are character based, such a Text, it is (# characters, # rows). Sometimes it is a pixel measurement such as the Image element. And sometimes a mix like on the Slider element (characters long by pixels wide).
|
||||||
|
|
||||||
|
Some elements, Text and Button, have an auto-size setting that is `on` by default. It will size the element based on the contents. The result is that buttons and text fields will be the size of the string creating them. You can turn it off. For example, for Buttons, the effect will be that all buttons will be the same size in that window.
|
||||||
|
|
||||||
#### Colors
|
#### Colors
|
||||||
A string representing color. Anytime colors are involved, you can specify the tkinter color name such as 'lightblue' or an RGB hex value '#RRGGBB'. For buttons, the color parameter is a tuple (text color, background color)
|
A string representing color. Anytime colors are involved, you can specify the tkinter color name such as 'lightblue' or an RGB hex value '#RRGGBB'. For buttons, the color parameter is a tuple (text color, background color)
|
||||||
|
|
||||||
|
Anytime colors are written as a tuple in PySimpleGUI, the way to figure out which color is the background is to replace the "," with the word "on". ('white', 'red') specifies a button that is "white on red". Works anywhere there's a color tuple.
|
||||||
|
|
||||||
#### Pad
|
#### Pad
|
||||||
|
|
||||||
The amount of room around the element in pixels. The default value is (5,3) which means leave 5 pixels on each side of the x-axis and 3 pixels on each side of the y-axis. You can change this on a global basis using a call to SetOptions, or on an element basis.
|
The amount of room around the element in pixels. The default value is (5,3) which means leave 5 pixels on each side of the x-axis and 3 pixels on each side of the y-axis. You can change this on a global basis using a call to SetOptions, or on an element basis.
|
||||||
|
|
||||||
If you want more pixels on one side than the other, then you can split the number into 2 number. If you want 200 pixels on the left side, and 3 pixels on the right, the pad would be ((200,3), 3). In this example, only the x-axis is split.
|
If you want more pixels on one side than the other, then you can split the number into 2 number. If you want 200 pixels on the left side, and 3 pixels on the right, the pad would be ((200,3), 3). In this example, only the x-axis is split.
|
||||||
|
@ -2494,6 +2537,16 @@ Then to get the input value from the read it would be: `values['mykey']`
|
||||||
|
|
||||||
You also use the same key if you want to call Update on an element. Please see the section below on Updates to understand that usage.
|
You also use the same key if you want to call Update on an element. Please see the section below on Updates to understand that usage.
|
||||||
|
|
||||||
|
Keys can be ANYTHING. Let's say you have a window with a grid of input elements. You could use their row and column location as a key (a tuple)
|
||||||
|
|
||||||
|
`key=(row, col)`
|
||||||
|
|
||||||
|
Then when you read the `values` variable that's returned to you from calling `Window.Read()`, the key in the `values` variable will be whatever you used to create the element. In this case you would read the values as:
|
||||||
|
`values[(row, col)]`
|
||||||
|
|
||||||
|
Most of the time they are simple text strings. In the Demo Programs, keys are written with this convention:
|
||||||
|
`_KEY_NAME_` (underscore at beginning and end with all caps letters). You don't have to follow that convention. It's used so that you can quickly spot when a key is being used.
|
||||||
|
|
||||||
#### Visible
|
#### Visible
|
||||||
Beginning in version 3.17 you can create Elements that are initially invisible that you can later make visible.
|
Beginning in version 3.17 you can create Elements that are initially invisible that you can later make visible.
|
||||||
|
|
||||||
|
@ -2503,17 +2556,13 @@ Later when you want to make that Element visible you simply call the Element's `
|
||||||
|
|
||||||
This feature works best on Qt, but does work on the tkinter version as well. The visible parameter can also be used with the Column and Frame "container" Elements.
|
This feature works best on Qt, but does work on the tkinter version as well. The visible parameter can also be used with the Column and Frame "container" Elements.
|
||||||
|
|
||||||
### Output Element
|
|
||||||
Building a window is simply making lists of Elements. Each list is a row in the overall GUI dialog box. The definition looks something like this:
|
|
||||||
|
|
||||||
```
|
|
||||||
layout = [ [row 1 element, row 1 element],
|
|
||||||
[row 2 element, row 2 element, row 2 element] ]
|
|
||||||
```
|
|
||||||
The code is a crude representation of the GUI, laid out in text.
|
|
||||||
## Shortcut Functions / Multiple Function Names
|
## Shortcut Functions / Multiple Function Names
|
||||||
|
|
||||||
Many of the main method calls and Element names have shortcuts. This enables you to code much quicker once you are used to using the SDK. The Text Element, for example, has 3 different names `Text`, `Txt` or`T`. InputText can also be written `Input` or `In` . `FindElement` was recently renamed to `Element` because it's a commonly used function.
|
Perhaps not the best idea, but one that's done none the less is the naming of methods and functions. Some of the more "Heavily Travelled Elements" have "shortcuts".
|
||||||
|
|
||||||
|
In other words, I am lazy and don't like to type. The result is multiple ways to do exactly the same thing. Typically, the Demo Programs and other examples use the full name, or at least a longer name. Thankfully PyCharm will show you the same documentation regardless which you use.
|
||||||
|
|
||||||
|
This enables you to code much quicker once you are used to using the SDK. The Text Element, for example, has 3 different names `Text`, `Txt` or`T`. InputText can also be written `Input` or `In` . The shortcuts aren't limited to Elements. The `Window` method `Window.FindElement` can be written as `Window.Element` because it's such a commonly used function.
|
||||||
|
|
||||||
## Text Element | `T == Txt == Text`
|
## Text Element | `T == Txt == Text`
|
||||||
Basic Element. It displays text. That's it.
|
Basic Element. It displays text. That's it.
|
||||||
|
@ -2617,14 +2666,18 @@ Individual colors are specified using either the color names as defined in tkint
|
||||||
"#RRGGBB" or "darkblue"
|
"#RRGGBB" or "darkblue"
|
||||||
|
|
||||||
### `auto_size_text `
|
### `auto_size_text `
|
||||||
A `True` value for `auto_size_text`, when placed on Text Elements, indicates that the width of the Element should be shrunk do the width of the text. The default setting is True.
|
A `True` value for `auto_size_text`, when placed on Text Elements, indicates that the width of the Element should be shrunk do the width of the text. The default setting is True. You need to remember this when you create `Text` elements that you are using for output.
|
||||||
|
|
||||||
|
`Text('', key='_TXTOUT_)` will create a `Text` Element that has 0 length. If you try to output a string that's 5 characters, it won't be shown in the window because there isn't enough room. The remedy is to manually set the size to what you expect to output
|
||||||
|
|
||||||
|
`Text('', size=(15,1), key='_TXTOUT_)` creates a `Text` Element that can hold 15 characters.
|
||||||
|
|
||||||
### Chortcut functions
|
### Chortcut functions
|
||||||
The shorthand functions for `Text` are `Txt` and `T`
|
The shorthand functions for `Text` are `Txt` and `T`
|
||||||
|
|
||||||
### Events `enable_events`
|
### Events `enable_events`
|
||||||
|
|
||||||
If you set the parameter `enable_events` or `click_submits` then you will get an event if the user clicks on the Text.
|
If you set the parameter `enable_events` then you will get an event if the user clicks on the Text.
|
||||||
|
|
||||||
## Multiline Element
|
## Multiline Element
|
||||||
This Element doubles as both an input and output Element.
|
This Element doubles as both an input and output Element.
|
||||||
|
@ -3104,7 +3157,7 @@ Parameter Descriptions:
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
ListBoxes can cause a window to return from a Read call. If the flag change_submits is set, then when a user makes a selection, the Read immediately returns.
|
ListBoxes can cause a window to return from a Read call. If the flag `enable_events` is set, then when a user makes a selection, the Read immediately returns.
|
||||||
|
|
||||||
Another way ListBoxes can cause Reads to return is if the flag bind_return_key is set. If True, then if the user presses the return key while an entry is selected, then the Read returns. Also, if this flag is set, if the user double-clicks an entry it will return from the Read.
|
Another way ListBoxes can cause Reads to return is if the flag bind_return_key is set. If True, then if the user presses the return key while an entry is selected, then the Read returns. Also, if this flag is set, if the user double-clicks an entry it will return from the Read.
|
||||||
|
|
||||||
|
@ -3839,7 +3892,7 @@ gui_rows = [[sg.Text('Robotics Remote Control')],
|
||||||
[sg.Quit(button_color=('black', 'orange'))]
|
[sg.Quit(button_color=('black', 'orange'))]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = sg.Window('Robotics Remote Control', auto_size_text=True).Layout(gui_rows)
|
window = sg.Window('Robotics Remote Control', gui_rows)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Some place later in your code...
|
# Some place later in your code...
|
||||||
|
@ -3849,7 +3902,7 @@ window = sg.Window('Robotics Remote Control', auto_size_text=True).Layout(gui_ro
|
||||||
# your program's main loop
|
# your program's main loop
|
||||||
while (True):
|
while (True):
|
||||||
# This is the code that reads and updates your window
|
# This is the code that reads and updates your window
|
||||||
event, values = window.Read(timeout=0)
|
event, values = window.Read(timeout=50)
|
||||||
if event is not None:
|
if event is not None:
|
||||||
print(event)
|
print(event)
|
||||||
if event == 'Quit' or values is None:
|
if event == 'Quit' or values is None:
|
||||||
|
@ -4025,7 +4078,7 @@ layout = [[sg.Text('A custom progress meter')],
|
||||||
[sg.Cancel()]]
|
[sg.Cancel()]]
|
||||||
|
|
||||||
# create the window`
|
# create the window`
|
||||||
window = sg.Window('Custom Progress Meter').Layout(layout)
|
window = sg.Window('Custom Progress Meter', layout)
|
||||||
progress_bar = window.FindElement('progressbar')
|
progress_bar = window.FindElement('progressbar')
|
||||||
# loop that would normally do something useful
|
# loop that would normally do something useful
|
||||||
for i in range(10000):
|
for i in range(10000):
|
||||||
|
@ -4071,7 +4124,7 @@ Parameter Descriptions:
|
||||||
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
||||||
|visible|(bool) set visibility state of the element|
|
|visible|(bool) set visibility state of the element|
|
||||||
|
|
||||||
## Output Elements
|
## Output Element
|
||||||
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.
|
||||||
|
|
||||||
Note that you will NOT see what you `print` until you call either window.Read or window.Refresh. If you want to immediately see what was printed, call window.Refresh() immediately after your print statement.
|
Note that you will NOT see what you `print` until you call either window.Read or window.Refresh. If you want to immediately see what was printed, call window.Refresh() immediately after your print statement.
|
||||||
|
@ -4140,9 +4193,9 @@ def ChatBot():
|
||||||
sg.RButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])),
|
sg.RButton('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])),
|
||||||
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
|
sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]]
|
||||||
|
|
||||||
window = sg.Window('Chat Window', default_element_size=(30, 2)).Layout(layout)
|
window = sg.Window('Chat Window', layout, default_element_size=(30, 2))
|
||||||
|
|
||||||
# ---===--- Loop taking in user input then printing so will show up in Output Element --- #
|
# ---===--- Loop taking in user input and using it to query HowDoI web oracle --- #
|
||||||
while True:
|
while True:
|
||||||
event, value = window.Read()
|
event, value = window.Read()
|
||||||
if event == 'SEND':
|
if event == 'SEND':
|
||||||
|
@ -4184,8 +4237,7 @@ Parameter Descriptions:
|
||||||
|---|---|
|
|---|---|
|
||||||
|layout|List[List[Element]] Layout that will be shown in the Column container|
|
|layout|List[List[Element]] Layout that will be shown in the Column container|
|
||||||
|background_color|(str) color of background of entire Column|
|
|background_color|(str) color of background of entire Column|
|
||||||
|size|Tuple[int, int] (width, height) size in pixels (doesn't work quite right, sometimes
|
|size|Tuple[int, int] (width, height) size in pixels (doesn't work quite right, sometimes only 1 dimension is set by tkinter|
|
||||||
only 1 dimension is set by tkinter|
|
|
||||||
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
||||||
|scrollable|(bool) if True then scrollbars will be added to the column|
|
|scrollable|(bool) if True then scrollbars will be added to the column|
|
||||||
|vertical_scroll_only|(bool) if Truen then no horizontal scrollbar will be shown|
|
|vertical_scroll_only|(bool) if Truen then no horizontal scrollbar will be shown|
|
||||||
|
@ -4222,7 +4274,7 @@ layout = [[sg.Slider(range=(1,100), default_value=10, orientation='v', size=(8,2
|
||||||
# Display the window and get values
|
# Display the window and get values
|
||||||
# If you're willing to not use the "context manager" design pattern, then it's possible
|
# If you're willing to not use the "context manager" design pattern, then it's possible
|
||||||
# to collapse the window display and read down to a single line of code.
|
# to collapse the window display and read down to a single line of code.
|
||||||
event, values = sg.Window('Compact 1-line window with column').Layout(layout).Read()
|
event, values = sg.Window('Compact 1-line window with column', layout).Read()
|
||||||
|
|
||||||
sg.Popup(event, values, line_width=200)
|
sg.Popup(event, values, line_width=200)
|
||||||
```
|
```
|
||||||
|
@ -4291,7 +4343,7 @@ layout = [
|
||||||
[sg.Submit(), sg.Cancel()]
|
[sg.Submit(), sg.Cancel()]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = sg.Window('Frame with buttons', font=("Helvetica", 12)).Layout(layout)
|
window = sg.Window('Frame with buttons', layout, font=("Helvetica", 12))
|
||||||
```
|
```
|
||||||
|
|
||||||
## Canvas Element
|
## Canvas Element
|
||||||
|
@ -4334,6 +4386,7 @@ One such integration is with Matploplib and Pyplot. There is a Demo program wri
|
||||||
tooltip - tooltip text)
|
tooltip - tooltip text)
|
||||||
|
|
||||||
The order of operations to obtain a tkinter Canvas Widget is:
|
The order of operations to obtain a tkinter Canvas Widget is:
|
||||||
|
```python
|
||||||
|
|
||||||
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
|
figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds
|
||||||
# define the window layout
|
# define the window layout
|
||||||
|
@ -4342,13 +4395,14 @@ The order of operations to obtain a tkinter Canvas Widget is:
|
||||||
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
|
[sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]]
|
||||||
|
|
||||||
# create the window and show it without the plot
|
# create the window and show it without the plot
|
||||||
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI').Layout(layout).Finalize()
|
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout).Finalize()
|
||||||
|
|
||||||
# add the plot to the window
|
# add the plot to the window
|
||||||
fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig)
|
fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig)
|
||||||
|
|
||||||
# show it all again and get buttons
|
# show it all again and get buttons
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
```
|
||||||
|
|
||||||
To get a tkinter Canvas Widget from PySimpleGUI, follow these steps:
|
To get a tkinter Canvas Widget from PySimpleGUI, follow these steps:
|
||||||
* Add Canvas Element to your window
|
* Add Canvas Element to your window
|
||||||
|
@ -4553,8 +4607,7 @@ Parameter Descriptions:
|
||||||
|bottom_right|Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle|
|
|bottom_right|Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle|
|
||||||
|extent|(float) Andle to end drawing. Used in conjunction with start_angle|
|
|extent|(float) Andle to end drawing. Used in conjunction with start_angle|
|
||||||
|start_angle|(float) Angle to begin drawing. Used in conjunction with extent|
|
|start_angle|(float) Angle to begin drawing. Used in conjunction with extent|
|
||||||
|style|(str) Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last',
|
|style|(str) Valid choices are One of these Style strings- 'pieslice', 'chord', 'arc', 'first', 'last', 'butt', 'projecting', 'round', 'bevel', 'miter'|
|
||||||
'butt', 'projecting', 'round', 'bevel', 'miter'|
|
|
||||||
|arc_color|(str) color to draw arc with|
|
|arc_color|(str) color to draw arc with|
|
||||||
|||
|
|||
|
||||||
| **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the arc |
|
| **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the arc |
|
||||||
|
@ -4760,17 +4813,21 @@ Changes some of the settings for the Table Element. Must call `Window.Read` or `
|
||||||
Update(values=None,
|
Update(values=None,
|
||||||
num_rows=None,
|
num_rows=None,
|
||||||
visible=None,
|
visible=None,
|
||||||
select_rows=None)
|
select_rows=None,
|
||||||
|
alternating_row_color=None,
|
||||||
|
row_colors=None)
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameter Descriptions:
|
Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|values||
|
|values|List[List[Any]] A new 2-dimensional table to show|
|
||||||
|num_rows||
|
|num_rows|(int) How many rows to display at a time|
|
||||||
|visible|(bool) control visibility of element|
|
|visible|(bool) if True then will be visible|
|
||||||
|select_rows||
|
|select_rows|List[int] List of rows to select as if user did|
|
||||||
|
|alternating_row_color|(str) the color to make every other row|
|
||||||
|
|row_colors|List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)|
|
||||||
|
|
||||||
---
|
---
|
||||||
### Known visualization problem....
|
### Known visualization problem....
|
||||||
|
@ -5001,37 +5058,28 @@ Parameter Descriptions:
|
||||||
|
|
||||||
### Reading Tab Groups
|
### Reading Tab Groups
|
||||||
|
|
||||||
Tab Groups now return a value when a Read returns. They return which tab is currently selected. There is also a change_submits parameter that can be set that causes a Read to return if a Tab in that group is selected / changed. The key or title belonging to the Tab that was switched to will be returned as the value
|
Tab Groups now return a value when a Read returns. They return which tab is currently selected. There is also a `enable_events` parameter that can be set that causes a Read to return if a Tab in that group is selected / changed. The key or title belonging to the Tab that was switched to will be returned as the value
|
||||||
|
|
||||||
### Methods
|
### Methods
|
||||||
|
|
||||||
Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior
|
Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior
|
||||||
|
|
||||||
```
|
```
|
||||||
Update(values=None,
|
Update(disabled=None, visible=None)
|
||||||
key=None,
|
|
||||||
value=None,
|
|
||||||
text=None,
|
|
||||||
icon=None,
|
|
||||||
visible=None)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Parameter Descriptions:
|
Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|values||
|
|disabled|(bool) disable or enable state of the element|
|
||||||
|key|Used with window.FindElement and with return values to uniquely identify this element|
|
|
||||||
|value||
|
|
||||||
|text||
|
|
||||||
|icon||
|
|
||||||
|visible|(bool) control visibility of element|
|
|visible|(bool) control visibility of element|
|
||||||
|
|
||||||
## Pane Element
|
## Pane Element
|
||||||
|
|
||||||
New in version 3.20 is the Pane Element, a super-cool tkinter feature. You won't find this one in PySimpleGUIQt, only PySimpleGUI. It's difficult to describe one of these things. Think of them as "Tabs without labels" that you can slide.
|
New in version 3.20 is the Pane Element, a super-cool tkinter feature. You won't find this one in PySimpleGUIQt, only PySimpleGUI. It's difficult to describe one of these things. Think of them as "Tabs without labels" that you can slide.
|
||||||
|
|
||||||
A sliding Pane that is unique to tkinter
|
A sliding Pane that is unique to tkinter. Uses Columns to create individual panes
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
@ -5053,17 +5101,17 @@ Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|pane_list||
|
|pane_list|List[Column] Must be a list of Column Elements. Each Column supplied becomes one pane that's shown|
|
||||||
|background_color|color of background|
|
|background_color|(str) color of background|
|
||||||
|size|(w,h) w=characters-wide, h=rows-high|
|
|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high How much room to reserve for the Pane|
|
||||||
|pad|Amount of padding to put around element|
|
|pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))|
|
||||||
|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')|
|
|orientation|(str) 'horizontal' or 'vertical' or ('h' or 'v'). Direction the Pane should slide|
|
||||||
|show_handle|(Default = True)|
|
|show_handle|(bool) if True, the handle is drawn that makes it easier to grab and slide|
|
||||||
|relief|relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`|
|
|relief|(enum) relief style. Values are same as other elements that use relief values. `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`|
|
||||||
|handle_size||
|
|handle_size|(int) Size of the handle in pixels|
|
||||||
|border_width|width of border around element|
|
|border_width|(int) width of border around element in pixels|
|
||||||
|key|Used with window.FindElement and with return values to uniquely identify this element|
|
|key|(any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window|
|
||||||
|visible|set visibility state of the element (Default = True)|
|
|visible|(bool) set visibility state of the element|
|
||||||
|
|
||||||
***Each "Pane" of a Pane Element must be a Column Element***. The parameter `pane_list` is a list of Column Elements.
|
***Each "Pane" of a Pane Element must be a Column Element***. The parameter `pane_list` is a list of Column Elements.
|
||||||
|
|
||||||
|
@ -5373,7 +5421,7 @@ layout = [[sg.Text('Persistent window')],
|
||||||
[sg.Input()],
|
[sg.Input()],
|
||||||
[sg.RButton('Read'), sg.Exit()]]
|
[sg.RButton('Read'), sg.Exit()]]
|
||||||
|
|
||||||
window = sg.Window('Window that stays open', layout)
|
window = sg.Window('Window that stays open').Layout(layout)
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
@ -5441,18 +5489,18 @@ TIMEOUT_KEY = '__timeout__'
|
||||||
If you wanted to test for "no event" in your loop, it would be written like this:
|
If you wanted to test for "no event" in your loop, it would be written like this:
|
||||||
```python
|
```python
|
||||||
while True:
|
while True:
|
||||||
event, value = window.Read(timeout=100)
|
event, value = window.Read(timeout=0)
|
||||||
if event is None:
|
if event is None:
|
||||||
break # the use has closed the window
|
break # the use has closed the window
|
||||||
if event == sg.TIMEOUT_KEY:
|
if event == sg.TIMEOUT_KEY:
|
||||||
print("No event happened")
|
print("Nothing happened")
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a sleep in your loop, you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly.
|
||||||
|
|
||||||
|
Non-blocking is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine.
|
||||||
|
|
||||||
Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over.
|
There is a hybrid approach... a read with a timeout. You'll score much higher points on the impressive meter if you're able to use a lot less CPU time by using this type of read.
|
||||||
|
|
||||||
If you have a ZERO timeout value in the `Read` call in your loop, you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Set your `timeout` parameter to a non-zero value like 100 which is going to return to you every 100 ms. That's a reasonable number to use as you're likely not thrashing the CPU.
|
|
||||||
|
|
||||||
The most legit time to use a non-blocking window is when you're working directly with hardware. Maybe you're driving a serial bus. If you look at the Event Loop in the Demo_OpenCV_Webcam.py program, you'll see that the read is a non-blocking read. However, there is a place in the event loop where blocking occurs. The point in the loop where you will block is the call to read frames from the webcam. When a frame is available you want to quickly deliver it to the output device, so you don't want your GUI blocking. You want the read from the hardware to block.
|
The most legit time to use a non-blocking window is when you're working directly with hardware. Maybe you're driving a serial bus. If you look at the Event Loop in the Demo_OpenCV_Webcam.py program, you'll see that the read is a non-blocking read. However, there is a place in the event loop where blocking occurs. The point in the loop where you will block is the call to read frames from the webcam. When a frame is available you want to quickly deliver it to the output device, so you don't want your GUI blocking. You want the read from the hardware to block.
|
||||||
|
|
||||||
|
@ -5496,7 +5544,7 @@ layout = [[sg.Text('')],
|
||||||
sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'),
|
sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'),
|
||||||
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
|
sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]]
|
||||||
|
|
||||||
window = sg.Window('Running Timer', layout, no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True)
|
window = sg.Window('Running Timer', no_titlebar=True, auto_size_buttons=False, keep_on_top=True, grab_anywhere=True).Layout(layout)
|
||||||
|
|
||||||
# ---------------- main loop ----------------
|
# ---------------- main loop ----------------
|
||||||
current_time = 0
|
current_time = 0
|
||||||
|
@ -5514,9 +5562,9 @@ while (True):
|
||||||
|
|
||||||
Previously this program was implemented using a sleep in the loop to control the clock tick. This version uses the new timeout parameter. The result is a window that reacts quicker then the one with the sleep and the accuracy is just as good.
|
Previously this program was implemented using a sleep in the loop to control the clock tick. This version uses the new timeout parameter. The result is a window that reacts quicker then the one with the sleep and the accuracy is just as good.
|
||||||
|
|
||||||
## Instead of a Non-blocking Read --- Use `change_submits = True` or `return_keyboard_events = True`
|
## Instead of a Non-blocking Read --- Use `enable_events = True` or `return_keyboard_events = True`
|
||||||
|
|
||||||
Any time you are thinking "I want an X Element to cause a Y Element to do something", then you want to use the `change_submits` option.
|
Any time you are thinking "I want an X Element to cause a Y Element to do something", then you want to use the `enable_events` option.
|
||||||
|
|
||||||
***Instead of polling, try options that cause the window to return to you.*** By using non-blocking windows, you are *polling*. You can indeed create your application by polling. It will work. But you're going to be maxing out your processor and may even take longer to react to an event than if you used another technique.
|
***Instead of polling, try options that cause the window to return to you.*** By using non-blocking windows, you are *polling*. You can indeed create your application by polling. It will work. But you're going to be maxing out your processor and may even take longer to react to an event than if you used another technique.
|
||||||
|
|
||||||
|
@ -5540,7 +5588,7 @@ import PySimpleGUI as sg
|
||||||
layout = [ [sg.Text('My layout', key='_TEXT_')],
|
layout = [ [sg.Text('My layout', key='_TEXT_')],
|
||||||
[sg.Button('Read')]]
|
[sg.Button('Read')]]
|
||||||
|
|
||||||
window = sg.Window('My new window', layout)
|
window = sg.Window('My new window').Layout(layout)
|
||||||
|
|
||||||
while True: # Event Loop
|
while True: # Event Loop
|
||||||
event, values = window.Read()
|
event, values = window.Read()
|
||||||
|
@ -5559,7 +5607,7 @@ layout = [ [sg.Text('My layout', key='_TEXT_')],
|
||||||
[sg.Button('Read')]
|
[sg.Button('Read')]
|
||||||
]
|
]
|
||||||
|
|
||||||
window = sg.Window('My new window', layout).Finalize()
|
window = sg.Window('My new window').Layout(layout).Finalize()
|
||||||
|
|
||||||
window.Element('_TEXT_').Update('My new text value')
|
window.Element('_TEXT_').Update('My new text value')
|
||||||
|
|
||||||
|
@ -5598,7 +5646,7 @@ layout = [[sg.Spin([sz for sz in range(6, 172)], font=('Helvetica 20'), initial_
|
||||||
sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
|
sg.Text("Aa", size=(2, 1), font="Helvetica " + str(fontSize), key='text')]]
|
||||||
|
|
||||||
sz = fontSize
|
sz = fontSize
|
||||||
window = sg.Window("Font size selector", layout, grab_anywhere=False)
|
window = sg.Window("Font size selector", grab_anywhere=False).Layout(layout)
|
||||||
# Event Loop
|
# Event Loop
|
||||||
while True:
|
while True:
|
||||||
event, values= window.Read()
|
event, values= window.Read()
|
||||||
|
@ -5711,6 +5759,21 @@ Use realtime keyboard capture by calling
|
||||||
|
|
||||||
Beginning in version 3.01 you can add a MenuBar to your window. You specify the menus in much the same way as you do window layouts, with lists. Menu selections are returned as events and as of 3.17, also as in the values dictionary. The value returned will be the entire menu entry, including the key if you specified one.
|
Beginning in version 3.01 you can add a MenuBar to your window. You specify the menus in much the same way as you do window layouts, with lists. Menu selections are returned as events and as of 3.17, also as in the values dictionary. The value returned will be the entire menu entry, including the key if you specified one.
|
||||||
|
|
||||||
|
Menu Element is the Element that provides a Menu Bar that goes across the top of the window, just below titlebar.
|
||||||
|
Here is an example layout. The "&" are shortcut keys ALT+key.
|
||||||
|
Is a List of - "Item String" + List
|
||||||
|
Where Item String is what will be displayed on the Menubar itself.
|
||||||
|
The List that follows the item represents the items that are shown then Menu item is clicked
|
||||||
|
Notice how an "entry" in a mennu can be a list which means it branches out and shows another menu, etc. (resursive)
|
||||||
|
menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']],
|
||||||
|
['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ],
|
||||||
|
['&Debugger', ['Popout', 'Launch Debugger']],
|
||||||
|
['&Toolbar', ['Command &1', 'Command &2', 'Command &3', 'Command &4']],
|
||||||
|
['&Help', '&About...'], ]
|
||||||
|
Finally, "keys" can be added to entires so make them unique. The "Save" entry has a key associated with it. You
|
||||||
|
can see it has a "::" which signifies the beginning of a key. The user will not see the key portion when the
|
||||||
|
menu is shown. The key portion is returned as part of the event.
|
||||||
|
|
||||||
```python
|
```python
|
||||||
menu_def = [['File', ['Open', 'Save', 'Exit',]],
|
menu_def = [['File', ['Open', 'Save', 'Exit',]],
|
||||||
['Edit', ['Paste', ['Special', 'Normal',], 'Undo'],],
|
['Edit', ['Paste', ['Special', 'Normal',], 'Undo'],],
|
||||||
|
@ -5723,7 +5786,7 @@ Note the placement of ',' and of []. It's tricky to get the nested menus correc
|
||||||
|
|
||||||
## Methods
|
## Methods
|
||||||
|
|
||||||
Update a menubar - can change the menu definition and visibility
|
Update a menubar - can change the menu definition and visibility. The entire menu has to be specified
|
||||||
|
|
||||||
```
|
```
|
||||||
Update(menu_definition=None, visible=None)
|
Update(menu_definition=None, visible=None)
|
||||||
|
@ -5733,7 +5796,7 @@ Parameter Descriptions:
|
||||||
|
|
||||||
|Name|Meaning|
|
|Name|Meaning|
|
||||||
|---|---|
|
|---|---|
|
||||||
|menu_definition|List[[str]] New menu defintion|
|
|menu_definition|List[List[Tuple[str, List[str]]]|
|
||||||
|visible|(bool) control visibility of element|
|
|visible|(bool) control visibility of element|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
@ -5827,7 +5890,7 @@ layout = [[ sg.Text('Window 1'),],
|
||||||
[sg.Text('', key='_OUTPUT_')],
|
[sg.Text('', key='_OUTPUT_')],
|
||||||
[sg.Button('Launch 2'), sg.Button('Exit')]]
|
[sg.Button('Launch 2'), sg.Button('Exit')]]
|
||||||
|
|
||||||
win1 = sg.Window('Window 1', layout)
|
win1 = sg.Window('Window 1').Layout(layout)
|
||||||
|
|
||||||
win2_active = False
|
win2_active = False
|
||||||
while True:
|
while True:
|
||||||
|
@ -5841,7 +5904,7 @@ while True:
|
||||||
layout2 = [[sg.Text('Window 2')],
|
layout2 = [[sg.Text('Window 2')],
|
||||||
[sg.Button('Exit')]]
|
[sg.Button('Exit')]]
|
||||||
|
|
||||||
win2 = sg.Window('Window 2', layout2)
|
win2 = sg.Window('Window 2').Layout(layout2)
|
||||||
|
|
||||||
if win2_active:
|
if win2_active:
|
||||||
ev2, vals2 = win2.Read(timeout=100)
|
ev2, vals2 = win2.Read(timeout=100)
|
||||||
|
@ -5862,7 +5925,7 @@ layout = [[ sg.Text('Window 1'),],
|
||||||
[sg.Text('', key='_OUTPUT_')],
|
[sg.Text('', key='_OUTPUT_')],
|
||||||
[sg.Button('Launch 2')]]
|
[sg.Button('Launch 2')]]
|
||||||
|
|
||||||
win1 = sg.Window('Window 1', layout)
|
win1 = sg.Window('Window 1').Layout(layout)
|
||||||
win2_active=False
|
win2_active=False
|
||||||
while True:
|
while True:
|
||||||
ev1, vals1 = win1.Read(timeout=100)
|
ev1, vals1 = win1.Read(timeout=100)
|
||||||
|
@ -5876,7 +5939,7 @@ while True:
|
||||||
layout2 = [[sg.Text('Window 2')], # note must create a layout from scratch every time. No reuse
|
layout2 = [[sg.Text('Window 2')], # note must create a layout from scratch every time. No reuse
|
||||||
[sg.Button('Exit')]]
|
[sg.Button('Exit')]]
|
||||||
|
|
||||||
win2 = sg.Window('Window 2', layout2)
|
win2 = sg.Window('Window 2').Layout(layout2)
|
||||||
while True:
|
while True:
|
||||||
ev2, vals2 = win2.Read()
|
ev2, vals2 = win2.Read()
|
||||||
if ev2 is None or ev2 == 'Exit':
|
if ev2 is None or ev2 == 'Exit':
|
||||||
|
|
Loading…
Reference in New Issue