Getting up to date....

This commit is contained in:
PySimpleGUI 2021-01-31 13:27:17 -05:00
parent 9efd1a44aa
commit ef7b146596
3 changed files with 188 additions and 188 deletions

View File

@ -31,11 +31,11 @@ As long as you know you're sticking with tkinter for the short term, it's safe t
## The Non-PEP8 Methods and Functions
Why the need for these bindings? Simply put, the PySimpleGUI SDK has a PEP8 violation in the method and function names. PySimpleGUI uses CamelCase names for methods and functions. PEP8 suggests using snake_case_variables instead.
Why the need for these bindings? Simply put, the PySimpleGUI SDK has a PEP8 violation in the method and function names. PySimpleGUI uses CamelCase names for methods and functions. PEP8 suggests using snake_case_variables instead.
This has not caused any problems and few complaints, but it's important the the interfaces into PySimpleGUI be compliant. Perhaps one of the reasons for lack of complaints is that the Qt library also uses SnakeCase for its methods. This practice has the effect of labelling a package as being "not Pythonic" and also suggests that this package was originally used in another language and then ported to Python. This is exactly the situation with Qt. It was written for C++ and the interfaces continue to use C++ conventions.
***PySimpleGUI was written in Python, for Python.*** The reason for the name problem was one of ignorance. The PEP8 convention wasn't understood by the developers when PySimpleGUI was designed and implemented.
***PySimpleGUI was written in Python, for Python.*** The reason for the name problem was one of ignorance. The PEP8 convention wasn't understood by the developers when PySimpleGUI was designed and implemented.
You can, and will be able to for some time, use both names. However, at some point in the future, the CamelCase names will disappear. A utility is planned to do the conversion for the developer when the old names are remove from PySimpleGUI.
@ -60,7 +60,7 @@ For the time being, class variables will remain the way they are currently. It
Think of Popups as your first windows, sorta like your first bicycle. It worked well, but was limited. It probably wasn't long before you wanted more features and it seemed too limiting for your newly found sense of adventure.
When you've reached the point with Popups that you are thinking of filing a GitHub "Enhancement Issue" to get the Popup call extended to include a new feature that you think would be helpful.... not just to you but others is what you had in mind, right? For the good of others.
When you've reached the point with Popups that you are thinking of filing a GitHub "Enhancement Issue" to get the Popup call extended to include a new feature that you think would be helpful.... not just to you but others is what you had in mind, right? For the good of others.
Well, don't file that enhancement request. Instead, it's at THIS time that you should immediately turn to the section entitled "Custom Window API Calls - Your First Window". Congratulations, you just graduated and are now an official "GUI Designer". Oh, never mind that you only started learning Python 2 weeks ago, you're a real GUI Designer now so buck up and start acting like one. Write a popup function of your own. And then, compact that function down to a **single line of code**. Yes, these popups can be written in 1 line of code. The secret is to use the `close` parameter on your call to `window.read()`
@ -68,15 +68,15 @@ But, for now, let's stick with these 1-line window calls, the Popups. This is
popup_animated
popup_annoying
popup_auto_close
popup_auto_close
popup_cancel
popup_error
popup_get_file
popup_get_folder
popup_get_file
popup_get_folder
popup_get_text
popup_no_border
popup_no_buttons
popup_no_frame
popup_no_frame
popup_no_titlebar
popup_no_wait
popup_notify
@ -178,15 +178,15 @@ sg.popup_scrolled(my_text)
![scrolledtextbox 2](https://user-images.githubusercontent.com/13696193/43667324-712aa0d4-9745-11e8-83a9-a0d0570d0865.jpg)
The `popup_scrolled` will auto-fit the window size to the size of the text. Specify `None` in the height field of a `size` parameter to get auto-sized height.
The `popup_scrolled` will auto-fit the window size to the size of the text. Specify `None` in the height field of a `size` parameter to get auto-sized height.
This call will create a scrolled box 80 characters wide and a height dependent upon the number of lines of text.
This call will create a scrolled box 80 characters wide and a height dependent upon the number of lines of text.
`sg.popup_scrolled(my_text, size=(80, None))`
`sg.popup_scrolled(my_text, size=(80, None))`
Note that the default max number of lines before scrolling happens is set to 50. At 50 lines the scrolling will begin.
Note that the default max number of lines before scrolling happens is set to 50. At 50 lines the scrolling will begin.
If `non_blocking` parameter is set, then the call will not blocking waiting for the user to close the window. Execution will immediately return to the user. Handy when you want to dump out debug info without disrupting the program flow.
If `non_blocking` parameter is set, then the call will not blocking waiting for the user to close the window. Execution will immediately return to the user. Handy when you want to dump out debug info without disrupting the program flow.
### Non-Blocking Popups - popup_no_wait and the non_blocking parameter
@ -195,7 +195,7 @@ If `non_blocking` parameter is set, then the call will not blocking waiting for
The `popup` call `popup_no_wait` or `popup_non_blocking` will create a popup window and then immediately return control back to you. You can turn other popup calls into non-blocking popups if they have a `non_blocking` parameter. Setting `non_blocking` to True will cause the function to return immediately rather than waiting for the window to be closed.
This function is very handy for when you're **debugging** and want to display something as output but don't want to change the programs's overall timing by blocking. Think of it like a `print` statement. There are no return values on one of these Popups.
This function is very handy for when you're **debugging** and want to display something as output but don't want to change the programs's overall timing by blocking. Think of it like a `print` statement. There are no return values on one of these Popups.
### Popup Parameter Combinations
@ -206,7 +206,7 @@ So that you don't have to specify a potentially long list common parameters ther
## Popup Input
There are Popup calls for single-item inputs. These follow the pattern of `popup_get` followed by the type of item to get. There are 3 of these input Popups to choose from, each with settings enabling customization.
There are Popup calls for single-item inputs. These follow the pattern of `popup_get` followed by the type of item to get. There are 3 of these input Popups to choose from, each with settings enabling customization.
- `popup_get_text` - get a single line of text
- `popup_get_file` - get a filename
@ -238,7 +238,7 @@ Gets one or more filenames from the user. There are options to configure the ty
<!-- <+func.popup_get_file+> -->
If configured as an Open File Popup then (save_as is not True) the dialog box will look like this.
If configured as an Open File Popup then (save_as is not True) the dialog box will look like this.
![snag-0060](https://user-images.githubusercontent.com/13696193/46761050-9831c680-cca1-11e8-8de9-68b15efe2c46.jpg)
@ -546,7 +546,7 @@ This is a slightly more complex, but maybe more realistic version that reads inp
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.
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 (almost) ANYTHING, except `None` or a List (a tuple is fine). 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.
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 (almost) ANYTHING, except `None` or a List (a tuple is fine). 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
import PySimpleGUI as sg
@ -575,7 +575,7 @@ window.close()
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.
I hope to start using it more soon.
## How GUI Programming in Python Should Look? At least for beginners ?
@ -607,9 +607,9 @@ print(folder_path, file_path)
![image](https://user-images.githubusercontent.com/46163555/70470775-cd01ff00-1a99-11ea-8b9c-8b33c8880c99.png)
The first line of code after the import is a call to `theme`.
The first line of code after the import is a call to `theme`.
Until Dec 2019 the way a "theme" was specific in PySimpleGUI was to call `change_look_and_feel`. That call has been replaced by the more simple function `theme`.
Until Dec 2019 the way a "theme" was specific in PySimpleGUI was to call `change_look_and_feel`. That call has been replaced by the more simple function `theme`.
### Window contents (The Layout)
@ -690,7 +690,7 @@ For Windows that have specifically enabled these. Please see the appropriate se
### Window closed event
Another convention to follow is the check for windows being closed with an X. *This is an critically important event to catch*. If you don't check for this and you attempt to use the window, your program will crash, or silently consume 100% of your CPU. Please check for closed window and exit your program gracefully. Your users will like you for it.
Another convention to follow is the check for windows being closed with an X. *This is an critically important event to catch*. If you don't check for this and you attempt to use the window, your program will crash, or silently consume 100% of your CPU. 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. For other ports, such as PySimpleGUIWeb, not closing the Window will potentially cause your program to continue to run in the background.
@ -962,7 +962,7 @@ This is a complex window with quite a bit of custom sizing to make things line u
This window may look "ugly" to you which is because no effort has been made to make it look nice. It's purely functional. There are 30 Elements in the window. THIRTY Elements. Considering what it does, it's miraculous or in the least incredibly impressive. Why? Because in less than 50 lines of code that window was created, shown, collected the results and showed the results in another window.
50 lines. It'll take you 50 lines of tkinter or Qt code to get the first 3 elements of the window written, if you can even do that.
50 lines. It'll take you 50 lines of tkinter or Qt code to get the first 3 elements of the window written, if you can even do that.
No, let's be clear here... this window will take a massive amount of code using the conventional Python GUI packages. It's a fact and if you care to prove me wrong, then by ALL means PLEASE do it. Please write this window using tkinter, Qt, or WxPython and send the code!
@ -978,7 +978,7 @@ Clicking the Submit button caused the window call to return. The call to Popup
**`Note, event values can be None`**. The value for `event` will be the text that is displayed on the button element when it was created or the key for the button. If the user closed the window using the "X" in the upper right corner of the window, then `event` will be `sg.WIN_CLOSED` which is equal to `None`. It is ***vitally*** ***important*** that your code contain the proper checks for `sg.WIN_CLOSED`.
**`Note, event values can be None`**. The value for `event` will be the text that is displayed on the button element when it was created or the key for the button. If the user closed the window using the "X" in the upper right corner of the window, then `event` will be `sg.WIN_CLOSED` which is equal to `None`. It is ***vitally*** ***important*** that your code contain the proper checks for `sg.WIN_CLOSED`.
For "persistent windows", **always give your users a way out of the window**. Otherwise you'll end up with windows that never properly close. It's literally 2 lines of code that you'll find in every Demo Program. While you're at it, make sure a `window.close()` call is after your event loop so that your window closes for sure.
@ -998,7 +998,7 @@ If, on the other hand, your operation is not under your control or you are unabl
### The "Old Way"
There are a couple of demo programs available for you to see how to do this. You basically put your work into a thread. When the thread is completed, it tells the GUI by sending a message through a queue. The event loop will run with a timer set to a value that represents how "responsive" you want your GUI to be to the work completing.
There are a couple of demo programs available for you to see how to do this. You basically put your work into a thread. When the thread is completed, it tells the GUI by sending a message through a queue. The event loop will run with a timer set to a value that represents how "responsive" you want your GUI to be to the work completing.
### The "New Way" - `Window.write_event_value`
@ -1021,17 +1021,17 @@ import PySimpleGUI as sg
"""
Threaded Demo - Uses Window.write_event_value communications
Requires PySimpleGUI.py version 4.25.0 and later
This is a really important demo to understand if you're going to be using multithreading in PySimpleGUI.
Older mechanisms for multi-threading in PySimpleGUI relied on polling of a queue. The management of a communications
queue is now performed internally to PySimpleGUI.
The importance of using the new window.write_event_value call cannot be emphasized enough. It will hav a HUGE impact, in
a positive way, on your code to move to this mechanism as your code will simply "pend" waiting for an event rather than polling.
Copyright 2020 PySimpleGUI.org
"""
@ -1208,7 +1208,7 @@ theme_previewer
# Window Object - Beginning a window
The first step is to create the window object using the desired window customizations.
The first step is to create the window object using the desired window customizations.
## Modal Windows (only applied to tkinter port currently
)
@ -1218,7 +1218,7 @@ NOTE - as of PySimpleGUI 4.25.0 Modal Windows are supported! By default the `po
## Making your window modal
To make a Modal Wio=ndow you have 2 options.
To make a Modal Wio=ndow you have 2 options.
1. Set the `moodel=True` parameter in your Window calls.
@ -1241,8 +1241,8 @@ PySimpleGUI computes the exact center of your window and centers the window on t
#### Multiple Monitors and Linux
The auto-centering (default) location for your PySimpleGUI window may not be correct if you have multiple monitors on a Linux system. On Windows multiple monitors appear to work ok as the primary monitor the tkinter utilizes and reports on.
The auto-centering (default) location for your PySimpleGUI window may not be correct if you have multiple monitors on a Linux system. On Windows multiple monitors appear to work ok as the primary monitor the tkinter utilizes and reports on.
Linux users with multiple monitors that have a problem when running with the default location will need to specify the location the window should be placed when creating the window by setting the `location` parameter.
### Window Size
@ -1408,7 +1408,7 @@ If it feels like this layout section is too much too soon, then come back to thi
While you've not learned about Elements yet, it makes sense for this section to be up front so that you'll have learned how to use the elements prior to learning how each element works. At this point in your PySimpleGUI education, it is better for you to grasp time efficient ways of working with Elements than what each Element does. By learning now how to assemble Elements now, you'll have a good model to put the elements you learn into.
There are *several* aspects of PySimpleGUI that make it more "Pythonic" than other Python GUI SDKs. One of the areas that is unique to PySimpleGUI is how a window's "layout" is defined, specified or built. A window's "layout" is simply a list of lists of elements. As you've already learned, these lists combine to form a complete window. This method of defining a window is super-powerful because lists are core to the Python language as a whole and thus are very easy to create and manipulate.
There are *several* aspects of PySimpleGUI that make it more "Pythonic" than other Python GUI SDKs. One of the areas that is unique to PySimpleGUI is how a window's "layout" is defined, specified or built. A window's "layout" is simply a list of lists of elements. As you've already learned, these lists combine to form a complete window. This method of defining a window is super-powerful because lists are core to the Python language as a whole and thus are very easy to create and manipulate.
Think about that for a moment and compare/contrast with Qt, tkinter, etc.. With PySimpleGUI the location of your element in a matrix determines where that Element is shown in the window. It's so ***simple*** and that makes it incredibly powerful. Want to switch a row in your GUI that has text with the one below it that has an input element? No problem, swap the lines of code and you're done.
@ -1416,7 +1416,7 @@ Layouts were designed to be visual. The idea is for you to be able to envision h
In the process of creating your window, you can manipulate these lists of elements without having an impact on the elements or on your window. Until you perform a "layout" of the list, they are nothing more than lists containing objects (they just happen to be your window's elements).
Many times your window definition / layout will be a static, straightforward to create.
Many times your window definition / layout will be a static, straightforward to create.
However, window layouts are not limited to being one of these statically defined list of Elements.
@ -1487,7 +1487,7 @@ BUT, we're not done yet!
This is **Python**, we're using lists to build something up, so we should be looking at ****list comprehensions****. Let's change the `for` loop into a list comprehension. Recall that our `for` loop was used to concatenate 6 rows into a layout.
```python
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
```
Here we've moved the `for` loop to inside of the list definition (a list comprehension)
@ -1497,7 +1497,7 @@ Here we've moved the `for` loop to inside of the list definition (a list compreh
We have our rows built using the list comprehension, now we just need the buttons. They can be easily "tacked onto the end" by simple addition.
```python
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
layout += [[sg.Button('Save'), sg.Button('Exit')]]
```
@ -1542,7 +1542,7 @@ event, values = sg.Window('To Do List Example', layout=[[sg.Text(f'{i}. '), sg.I
## Example - List Comprehension to Build Rows - Table Simulation - Grid of Inputs
In this example we're building a "table" that is 4 wide by 10 high using `Input` elements
In this example we're building a "table" that is 4 wide by 10 high using `Input` elements
The end results we're seeking is something like this:
@ -1687,9 +1687,9 @@ Using your new `CBtn` Element, you could rewrite the row of buttons above as:
[CBtn('1'), CBtn('2'), CBtn('3'), CBtn('log'), CBtn('ln'), CBtn('-')],
```
See the tremendous amount of code you do not have to write! USE this construct any time you find yourself copying an element many times.
See the tremendous amount of code you do not have to write! USE this construct any time you find yourself copying an element many times.
But let's not stop there.
But let's not stop there.
Since we've been discussing list comprehensions, let's use them to create this row. The way to do that is to make a list of the symbols that go across the row make a loop that steps through that list. The result is a list that looks like this:
@ -1794,7 +1794,7 @@ You will find information on Elements and all other classes and functions are lo
## Keys
***Keys are a super important concept to understand in PySimpleGUI.***
***Keys are a super important concept to understand in PySimpleGUI.***
If you are going to do anything beyond the basic stuff with your GUI, then you need to understand keys.
@ -1823,7 +1823,7 @@ You also use the same key if you want to call Update on an element. Please see
window['key']
```
While you'll often see keys written as strings in examples in this document, know that keys can be ***ANYTHING***.
While you'll often see keys written as strings in examples in this document, know that 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)
@ -1835,7 +1835,7 @@ Then when you read the `values` variable that's returned to you from calling `Wi
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) or the most recent convention is to use a dash at the beginning and end (e.g. `'-KEY_NAME-'`). You don't have to follow the convention, but it's not a bad one to follow as other users are used to seeing this format and it's easy to spot when element keys are being used.
If you have an element object, to find its key, access the member variable `.Key` for the element. This assumes you've got the element in a variable already.
If you have an element object, to find its key, access the member variable `.Key` for the element. This assumes you've got the element in a variable already.
```python
text_elem = sg.Text('', key='-TEXT-')
@ -1845,9 +1845,9 @@ the_key = text_elem.Key
### Default Keys
If you fail to place a key on an Element, then one will be created for you automatically.
If you fail to place a key on an Element, then one will be created for you automatically.
For `Buttons`, the text on the button is that button's key. `Text` elements will default to the text's string (for when events are enabled and the text is clicked)
For `Buttons`, the text on the button is that button's key. `Text` elements will default to the text's string (for when events are enabled and the text is clicked)
If the element is one of the input elements (one that will cause an generate an entry in the return values dictionary) and you fail to specify one, then a number will be assigned to it beginning with the number 0. The effect will be as if the values are represented as a list even if a dictionary is used.
@ -1973,7 +1973,7 @@ Keys can be a variety of types, including tuples. In this particular program we
### Example 3 - No close match found
In this example, as you can see in the error popup, there was such a mismatch that no substitution could be performed.
In this example, as you can see in the error popup, there was such a mismatch that no substitution could be performed.
![SNAG-0886](https://user-images.githubusercontent.com/46163555/88705707-e6fe5980-d0dd-11ea-8fcc-bc024298705d.jpg)
@ -2055,7 +2055,7 @@ Tooltips are one of those "polish" items that really dress-up a GUI and show's a
Info on setting default element sizes is discussed in the Window section above.
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.
@ -2118,7 +2118,7 @@ See the section above that has full information about keys.
Beginning in version 3.17 you can create Elements that are initially invisible that you can later make visible.
To create an invisible Element, place the element in the layout like you normally would and add the parameter
To create an invisible Element, place the element in the layout like you normally would and add the parameter
`visible=False`.
@ -2128,9 +2128,9 @@ This feature works best on Qt, but does work on the tkinter version as well. Th
Note - Tkinter elements behave differently than Qt elements in how they arrange themselves when going from invisible to visible.
tkinter elements tend to STACK themselves.
tkinter elements tend to STACK themselves.
One workaround is to place the element in a Column with other elements on its row. This will hold the place of the row it is to be placed on. It will move the element to the end of the row however.
One workaround is to place the element in a Column with other elements on its row. This will hold the place of the row it is to be placed on. It will move the element to the end of the row however.
If you want to not only make the element invisible, on tkinter you can call `Element.
@ -2139,11 +2139,11 @@ Qt elements tend to hold their place really well and the window resizes itself n
## Shortcut Functions / Multiple Function Names
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" (and methods/functions) have "shortcuts".
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" (and methods/functions) 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` .
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. BUT, even that has now been shortened to `window[key]`
@ -2166,7 +2166,7 @@ layout = [
![simple text](https://user-images.githubusercontent.com/13696193/44959877-e9d97b00-aec3-11e8-9d24-b4405ee4a148.jpg)
When creating a Text Element that you will later update, make sure you reserve enough characters for the new text. When a Text Element is created without a size parameter, it is created to exactly fit the characters provided.
When creating a Text Element that you will later update, make sure you reserve enough characters for the new text. When a Text Element is created without a size parameter, it is created to exactly fit the characters provided.
With proportional spaced fonts (normally the default) the pixel size of one set of characters will differ from the pixel size of a different set of characters even though the set is of the same number of characters. In other words, not all letters use the same number of pixels. Look at the text you're reading right now and you will see this. An "i" takes up a less space then an "A".
@ -2177,7 +2177,7 @@ With proportional spaced fonts (normally the default) the pixel size of one set
## `Window.FindElement(key)` shortened to `Window[key]`
There's been a fantastic leap forward in making PySimpleGUI code more compact.
There's been a fantastic leap forward in making PySimpleGUI code more compact.
Instead of writing:
```python
@ -2197,9 +2197,9 @@ MANY Thanks is owed to the nngogol that suggested and showed me how to do this.
## `Element.update()` -> `Element()` shortcut
This has to be one of the strangest syntactical constructs I've ever written.
This has to be one of the strangest syntactical constructs I've ever written.
It is best used in combination with `FindElement` (see prior section on how to shortcut `FindElement`).
It is best used in combination with `FindElement` (see prior section on how to shortcut `FindElement`).
Normally to change an element, you "find" it, then call its `update` method. The code usually looks like this, as you saw in the previous section:
@ -2237,7 +2237,7 @@ event, values = window.read()
It is confusing looking however so when used, it might be a good idea to write a comment at the end of the statement to help out the poor beginner programmer coming along behind you.
Because it's such a foreign construct that someone with 1 week of Python classes will not recognize, the demos will continue to use the `.update` method.
Because it's such a foreign construct that someone with 1 week of Python classes will not recognize, the demos will continue to use the `.update` method.
It does not have to be used in conjuction with `FindElement`. The call works on any previously made Element. Sometimes elements are created, stored into a variable and then that variable is used in the layout. For example.
@ -2267,7 +2267,7 @@ Individual colors are specified using either the color names as defined in tkint
"#RRGGBB" or "darkblue"
### `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. You need to remember this when you create `Text` elements that you are using for output.
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. Notice that for Text elements with an empty string, no string value needs to be indicated. The default value for strings is `''` for Text Elements. 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
@ -2540,7 +2540,7 @@ These Pre-made buttons are some of the most important elements of all because th
- SaveAs
- Open
### "Chooser" Buttons
### "Chooser" Buttons
These buttons are used to show dialog boxes that choose something like a filename, date, color, etc.. that are filled into an `InputText` Element (or some other "target".... see below regarding targets)
@ -2662,7 +2662,7 @@ Your button images need to be in PNG or GIF format. When you make a button with
`TRANSPARENT_BUTTON` - **Important** - This is a legacy value that is misleading. It is currently defined as this constant value:
```python
TRANSPARENT_BUTTON = ('#F0F0F0', '#F0F0F0')
TRANSPARENT_BUTTON = ('#F0F0F0', '#F0F0F0')
```
As you can see it is simply a tuple of 2 gray colors. The effect is that the button text and the button background color to a specific shade of gray. Way back in time, before you could change the background colors and all windows were gray, this value worked. But now that your button can be on any background color, you'll want to set the buttons color to match the background so that your button blends with the background color.
@ -2695,7 +2695,7 @@ sg.Button('Pause', button_color=(sg.theme_background_color(), sg.theme_backgroun
border_width=0)
```
Experimentation is sometimes required for these concepts to really sink in and they can vary depending on the underlying GUI framework.
Experimentation is sometimes required for these concepts to really sink in and they can vary depending on the underlying GUI framework.
Button Images do work so play with them. You can use PIL to change the size of your images before passing to PySimpleGUI.
@ -2906,7 +2906,7 @@ Starting in version 2.9 you'll be able to do more complex layouts by using the C
Columns are specified, like all "container elements", in exactly the same way as a window, as a list of lists.
Columns are needed when you want to specify more than 1 element in a single row.
Columns are needed when you want to specify more than 1 element in a single row.
For example, this layout has a single slider element that spans several rows followed by 7 `Text` and `Input` elements on the same row.
@ -2966,7 +2966,7 @@ This is currently only available in the primary PySimpleGUI port.
They can also be used to justify a group of elements in a particular way.
Placing `Column` elements inside `Columns` elements make it possible to create a multitude of
Placing `Column` elements inside `Columns` elements make it possible to create a multitude of
@ -3110,7 +3110,7 @@ graph.DeleteFigure(my_circle)
### Mouse Events Inside Graph Elements
If you have enabled events for your Graph Element, then you can receive mouse click events. If you additionally enable `drag_submits` in your creation of the Graph Element, then you will also get events when you "DRAG" inside of a window. A "Drag" is defined as a left button down and then the mouse is moved.
If you have enabled events for your Graph Element, then you can receive mouse click events. If you additionally enable `drag_submits` in your creation of the Graph Element, then you will also get events when you "DRAG" inside of a window. A "Drag" is defined as a left button down and then the mouse is moved.
When a drag event happens, the event will be the Graph Element's key. The `value` returned in the values dictionary is a tuple of the (x,y) location of the mouse currently.
@ -3174,7 +3174,7 @@ data = [['' for row in range(15)]for col in range(6)]
### Events from Tables
There are two ways to get events generated from Table Element.
There are two ways to get events generated from Table Element.
`change_submits` event generated as soon as a row is clicked on
`bind_return_key` event generate when a row is double clicked or the return key is press while on a row.
@ -3233,7 +3233,7 @@ Just like windows and the other container elements, the `Tab` Element has a layo
`Tab` layouts look exactly like Window layouts, that is they are **a list of lists of Elements**.
*How you place a Tab element into a window is different than all other elements.* You cannot place a Tab directly into a Window's layout.
*How you place a Tab element into a window is different than all other elements.* You cannot place a Tab directly into a Window's layout.
Also, tabs cannot be made invisible at this time. They have a visibility parameter but calling update will not change it.
@ -3362,7 +3362,7 @@ SystemTray(menu=None, filename=None, data=None, data_base64=None, tooltip=None,
:param filename: filename for icon
:param data: in-ram image for icon
:param data_base64: basee-64 data for icon
:param tooltip: tooltip string
:param tooltip: tooltip string
:param metadata: (Any) User metadata that can be set to ANYTHING
'''
```
@ -3574,14 +3574,14 @@ This is a blocking call so expect it to take a few seconds if you're fading the
# Global Settings
There are multiple ways to customize PySimpleGUI. The call with the most granularity (allows access to specific and precise settings). The `ChangeLookAndFeel` call is in reality a single call to `SetOptions` where it changes 13 different settings.
There are multiple ways to customize PySimpleGUI. The call with the most granularity (allows access to specific and precise settings). The `ChangeLookAndFeel` call is in reality a single call to `SetOptions` where it changes 13 different settings.
**Mac Users** - You can't call `ChangeLookAndFeel` but you can call `SetOptions` with any sets of values you want. Nothing is being blocked or filtered.
**These settings apply to all windows that are created in the future.**
`SetOptions`. The options and Element options will take precedence over these settings. Settings can be thought of as levels of settings with the window-level being the highest and the Element-level the lowest. Thus the levels are:
- Global
- Window
- Element
@ -3623,7 +3623,7 @@ window.close()
## Read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
Read with a timeout is a very good thing for your GUIs to use in a non-blocking read situation. If your device can wait for a little while, then use this kind of read. The longer you're able to add to the timeout value, the less CPU time you'll be taking.
Read with a timeout is a very good thing for your GUIs to use in a non-blocking read situation. If your device can wait for a little while, then use this kind of read. The longer you're able to add to the timeout value, the less CPU time you'll be taking.
The idea to wait for some number of milliseconds before returning. It's a trivial way to make a window that runs on a periodic basis.
@ -3642,7 +3642,7 @@ while True: # Event Loop
time.sleep(.1) # sleep 1/10 second DO NOT PUT SLEEPS IN YOUR EVENT LOOP!
```
This program will quickly test for user input, then deal with the hardware. Then it'll sleep for 100ms, while your gui is non-responsive, then it'll check in with your GUI again.
This program will quickly test for user input, then deal with the hardware. Then it'll sleep for 100ms, while your gui is non-responsive, then it'll check in with your GUI again.
The better way using PySimpleGUI... using the Read Timeout mechanism, the sleep goes away.
@ -3680,7 +3680,7 @@ You may find some PySimpleGUI programs that set the timeout value to zero. This
A true non-blocking (timeout=0) read is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine or a read with a timeout would work.
It's valid to use a timeout value of zero if you're in need of every bit of CPU horsepower in your application. Maybe your loop is doing something super-CPU intensive and you can't afford for the GUI to use any CPU time. This is the kind of situation where a timeout of zero is appropriate.
It's valid to use a timeout value of zero if you're in need of every bit of CPU horsepower in your application. Maybe your loop is doing something super-CPU intensive and you can't afford for the GUI to use any CPU time. This is the kind of situation where a timeout of zero is appropriate.
Be a good computing citizen. Run with a non-zero timeout so that other programs on your CPU will have time to run.
@ -3833,7 +3833,7 @@ window = sg.Window('My new window', layout, finalize=True)
window['-TEXT-'].update('My new text value')
while True: # Event Loop
event, values = window.read()
event, values = window.read()
if event == sg.WIN_CLOSED:
break
```
@ -3935,7 +3935,7 @@ It is possible to change the normal arrow cursor into something else by setting
One of the best examples is URLs. Users are accustomed to seeing a hand cursor when the mouse is moved over a link. By setting the cursor to a hand for a Text element that has text that is in the format of a URL, it signals to the user that it's a link that can be clicked.
The `set_cursor` method is used to set the cursor for an element. Perform an element look-up or use a variable containing an element, and call the `set_cursor` method, passing in a string that selects the cursor. The valid cursor names are documented in the tkinter docs as this call maps directly to a tkinter call.
The `set_cursor` method is used to set the cursor for an element. Perform an element look-up or use a variable containing an element, and call the `set_cursor` method, passing in a string that selects the cursor. The valid cursor names are documented in the tkinter docs as this call maps directly to a tkinter call.
These cursor strings were obtained from the Tk manual and are what you pass into the `set_cursor` methods.
@ -4115,7 +4115,7 @@ This would work to make a menu bar from a series of these individual menu defint
menu_bar = [right_click_menu_1, right_click_menu_2, button_menu_def ]
```
And, of course, the direction works the opposite too. You can take a Menu Bar definition and pull out an individual menu item to create a right click or button menu.
And, of course, the direction works the opposite too. You can take a Menu Bar definition and pull out an individual menu item to create a right click or button menu.
@ -4287,7 +4287,7 @@ This timeout value of 200 means that your debugger GUI will be updated 5 times a
Let's say you're in a situation where a very intermettent bug has just happened and the debugger would really help you, but you don't have a timeout on your `windows.read()` call. It's OK. Recall that the way the debugger gets its "cycles" is to borrow from your `Read` calls. What you need to do is alternate between using the debugger and then generating another pass through your event loop.
Maybe it's an OK button that will cause your loop to execute again (without exiting). If so, you can use it to help move the debugger along.
Maybe it's an OK button that will cause your loop to execute again (without exiting). If so, you can use it to help move the debugger along.
Yes, this is a major pain in the ass, but it's not THAT bad and compared to nothing in a time of crisis and this is potentially your "savior tool" that's going to save your ass, pressing that OK button a few times is going to look like nothing to you. You just want to dump out the value of a variable that holds an instance of your class!
@ -4333,7 +4333,7 @@ There are 3 ways of opening the Popout window.
#### When you are asked for the "Location of your PySimpleGUI package or PySimpleGUI.py file" do this
If you wish to use the debugger to find the location of THIS running program's PySimpleGUI package / the PySimpleGUI.py file, then all you need to do is:
* Press the `BREAK` key on your keyboard.
* Press the `BREAK` key on your keyboard.
* This is sometimes labelled as the `Cancel` key
* May also have `Pause` printed on key
* On some US keyboards, it is located next to `Scroll Lock` and/or above `PageUp` key
@ -4402,22 +4402,22 @@ We can see the variables we checked as well as the defined expression `values[0]
![SNAG-0441](https://user-images.githubusercontent.com/13696193/62797507-e7a37780-baa9-11e9-93c4-6ff0c8acb11d.jpg)
This tab is provided to you as a way to interact with your running program on a real-time basis.
This tab is provided to you as a way to interact with your running program on a real-time basis.
If you want to quickly look at the values of variables, nearly ANY variables, then type the information into one of the 3 spaces provided to "Watch" either variables or experessions. In this example, the variable window was typed into the first slow.
If you want to quickly look at the values of variables, nearly ANY variables, then type the information into one of the 3 spaces provided to "Watch" either variables or experessions. In this example, the variable window was typed into the first slow.
***Immediately*** after typing the character 'w', the information to the right was displayed. No button needs to be clicked. You merely neeed to type in a valid experession and it will be displayed to you.... and it will be displayed on an on-going, constantly-refreshing-basis.
![SNAG-0447](https://user-images.githubusercontent.com/13696193/62797393-a0b58200-baa9-11e9-8016-1cadca4d97e7.jpg)
If the area to the right of the input field is too small, then you can click on the "Detail" button and you will be shown a popup, scrolled window with all of the information displayed as if it were printed.
If the area to the right of the input field is too small, then you can click on the "Detail" button and you will be shown a popup, scrolled window with all of the information displayed as if it were printed.
I'm sure you've had the lovely experience of printing an object. When clicking the "Detail" button next to the `window` variable being shown, this window is shown:
![SNAG-0449](https://user-images.githubusercontent.com/13696193/62801423-b0d25f00-bab3-11e9-829a-aebb429521cd.jpg)
Oh, Python, -sigh-. I just want to see my `window` object printed.
Oh, Python, -sigh-. I just want to see my `window` object printed.
#### `Obj` Button to the Rescue!
@ -4430,13 +4430,13 @@ PySimpleGUI has a fun and very useful function that is discussed in the docs nam
While not **really** a Python REPL prompt, this window's `REPL >>>` prompt is meant to act as much like one as possible. Here you can enter experessions and code too.
The uses for this prompt are so numerous and diverse that listing them all won't be attempted.
The uses for this prompt are so numerous and diverse that listing them all won't be attempted.
### Your "XRay" and "Endoscope" into Your Program
Think of this prompt as a way to get specific diagnostics information about your ***running*** program. It cannot be stressed enough that the power and the usefullness of this tool is in its ability to diagnose a running program, after you've already started it running.
Think of this prompt as a way to get specific diagnostics information about your ***running*** program. It cannot be stressed enough that the power and the usefullness of this tool is in its ability to diagnose a running program, after you've already started it running.
### Execute Code
### Execute Code
In addition to displaying information, getting paths to packages, finding version information, you can execute code from the PySimpleGUI Debugger's `REPL >>>` prompt. You can type in any expression as well as any **executable statement**.
@ -4447,7 +4447,7 @@ The result is that you are shown a popup window with the text you supplied.
### KNOW Answers to Questions About Your Program
Using this runtime tool, you can be confident in the data you collect. Right?
Using this runtime tool, you can be confident in the data you collect. Right?
***There's no better way to find what version of a package that your program is using than to ask your program.*** This is so true. Think about it. Rather than go into PyCharm, look at your project's "Virtual Environment", follow some path to get to a window that lists packages installed for that project, get the verstion and your're done, right? Well, maybe. But are you CERTAIN your program is using THAT version of the package in question?
@ -4506,7 +4506,7 @@ While using JSON files to save and load a settings dictionary isn't very difficu
There have already been some demo programs written that use JSON files to store settings. You can expect that this capability will begin to show up in more demos in the future since it's now part of PySimpleGUI.
User settings are stored in a Python dictionary which is saved to / loaded from disk. Individual settings are thus keys into a dictionary. You do not need to explicitly read nor write the file. Changing any entry will cause the file to be saved. Reading any entry will cause the file to be read if it hasn't already been read.
User settings are stored in a Python dictionary which is saved to / loaded from disk. Individual settings are thus keys into a dictionary. You do not need to explicitly read nor write the file. Changing any entry will cause the file to be saved. Reading any entry will cause the file to be read if it hasn't already been read.
## Two Interfaces
@ -4546,7 +4546,7 @@ File operations involve working with the JSON file itself. They include:
* Load/save the file (these are somewhat optional as the saving loading/saving is done automatically)
* Deleting the settings file
* Checking if settings file exists
Generally speaking, a setting is specified with a key which is generally a string. Settings operations are for working with the individual settings and include:
* Get the value of a setting (returns a default value if not found)
* Set the value of a setting (also saves the settings to disk)
@ -4567,7 +4567,7 @@ In addition to the filename having a default value, the path to the file also ha
When calling the User Settings APIs, if a parameter is named `filename`, you can specify a full path or just the filename. This will save you the trouble of having to split up your path and filename in your code. If you specify only the path, the the filename will be added to that path and named as defined earlier.
Like the rest of PySimpleGUI, the idea is for you to write as little code as possible. The default values for the filename and path should be fine for you to use. They will be stored in a location on your system that is meant to store user settings.
Like the rest of PySimpleGUI, the idea is for you to write as little code as possible. The default values for the filename and path should be fine for you to use. They will be stored in a location on your system that is meant to store user settings.
### Setting Filename
@ -4576,7 +4576,7 @@ If you want to see what the current filename is for your settings, then you can
To make the code for specifying the folder and filename as simple as possible, the 2 parts are separated in the call specifying the name of the settings file. However, it is possible to supply a full and complete folder + filename as well.
The default filename for your settings file is the name of the file that makes the call to the User Settings API's with the `.py` extension changed to a `.json` extension. If your source file is called `demo.py`, then your settings filename will be `demo.json`.
The default filename for your settings file is the name of the file that makes the call to the User Settings API's with the `.py` extension changed to a `.json` extension. If your source file is called `demo.py`, then your settings filename will be `demo.json`.
#### Setting only the filename
@ -4631,13 +4631,13 @@ Calling `user_settings_filename` with no parameters will return the full path an
### File Loading / Saving
Generally speaking you will not need to load or save your settings file. It is automatically saved after every change.
Generally speaking you will not need to load or save your settings file. It is automatically saved after every change.
Note that reading a setting can also cause the file to be written. If you read a setting and the setting did not exist, then your call to `user_settings_get_entry` will return the default value you specified. As a result, the dictionary is updated with this default value and in return the file is written with this value as well.
One of the situations where you may want to explicitly read/load the settings file is if you're expecting it to be modified by another program.
Like so much of PySimpleGUI, as much as possible is automatically done on your behalf. This includes the requirement of saving and loading your settings file. Even naming your settings file is optional.
Like so much of PySimpleGUI, as much as possible is automatically done on your behalf. This includes the requirement of saving and loading your settings file. Even naming your settings file is optional.
## The `UserSettings` Class Interface
@ -4755,7 +4755,7 @@ def main():
```
Then you'll get an error when trying to set the '-test-' entry because `'...'` is not a valid path.
```
*** Error saving settings to file:***
...\scratch_1065.json [Errno 2] No such file or directory: '...\\scratch_1065.json'
@ -4771,7 +4771,7 @@ You should be able to easily figure out these errors as they are file operations
### Silenting the Errors
If you're the type that doesn't want to see any error messages printed out on your console, then you can silence the error output.
If you're the type that doesn't want to see any error messages printed out on your console, then you can silence the error output.
When using the class interface, there is a parameter `silent_on_error` that you can set to `True`.
@ -4864,7 +4864,7 @@ while True:
window.close()
```
If you were to place these 2 examples in the same file so that one ran after the other, you will find that the same settings file is used and thus the value saved in the first example will be read by the second one.
If you were to place these 2 examples in the same file so that one ran after the other, you will find that the same settings file is used and thus the value saved in the first example will be read by the second one.
There was one additional line of code added:
@ -4885,7 +4885,7 @@ There are a number of demo programs that show how to use UserSettings to create
If you're using the default path, remember that previous runs of your file may have old settings that are still in your settings file. It can get confusing when you've forgotten that you previously wrote a setting. Not seeing the filename can have drawbacks like this.
Also, because the settings automatically save after every update, it can be easy to accidently overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
Also, because the settings automatically save after every update, it can be easy to accidently overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
To save your Python dictionary to a settings file, simply call `user_settings_write_new_dictionary(dict)`, passing in your dictionary as the parameter.
@ -4895,7 +4895,7 @@ To save your Python dictionary to a settings file, simply call `user_settings_wr
# Extending PySimpleGUI
PySimpleGUI doesn't and can't provide every single setting available in the underlying GUI framework. Not all tkinter options are available for a `Text` Element. Same with PySimpleGUIQt and the other ports.
PySimpleGUI doesn't and can't provide every single setting available in the underlying GUI framework. Not all tkinter options are available for a `Text` Element. Same with PySimpleGUIQt and the other ports.
There are a few of reasons for this.
@ -4907,13 +4907,13 @@ However, PySimpleGUI programs are ***not*** dead ends!! Writing PySimpleGUI cod
## Widget Access
Most of the user extensions / enhancements are at the "Element" level. You want some Element to do a trick that you cannot do using the existing PySimpleGUI APIs. It's just not possible. What to do?
Most of the user extensions / enhancements are at the "Element" level. You want some Element to do a trick that you cannot do using the existing PySimpleGUI APIs. It's just not possible. What to do?
What you need is access to the underlying GUI framework's "Widget". The good news is that you HAVE that access ready and waiting for you, for all of the ports of PySimpleGUI, not just the tkinter one.
### `Element.Widget` is The GUI Widget
The class variable `Widget` contains the tkinter, Qt, WxPython, or Remi widget. With that variable you can modify that widget directly.
The class variable `Widget` contains the tkinter, Qt, WxPython, or Remi widget. With that variable you can modify that widget directly.
***You must first `Read` or `Finalize` the window before accessing the `Widget` class variable***
@ -4942,7 +4942,7 @@ So far there have been 2 uses of this capability. One already mentioned is addi
A recent Issue posted was that focus was always being set on a button in a tab when you switch tabs in tkinter. The user didn't want this to happen as it was putting an ugly black line around their nicely made graphical button.
There is no current way in PySimpleGUI to "disable focus" on an Element. That's essentially what was needed, the ability to tell tkinter that this widget should never get focus.
There is no current way in PySimpleGUI to "disable focus" on an Element. That's essentially what was needed, the ability to tell tkinter that this widget should never get focus.
There is a way to tell tkinter that a widget should not get focus. The downside is that if you use your tab key to navigate, that element will never get focus. So, it's not only blocking focus for this automatic problem, but blocking it for all uses. Of course you can still click on the button.
@ -5097,4 +5097,4 @@ window.close()
[Tkinter bindings documentation](https://tcl.tk/man/tcl8.6/TkCmd/bind.htm#M18)
------------------
------------------

View File

@ -4830,7 +4830,7 @@ hide_row()
### print
Print like Python normally prints except route the output to a multline element and also add colors if desired
Print like Python normally prints except route the output to a multiline element and also add colors if desired
colors -(str, str) or str. A combined text/background color definition in a single parameter

View File

@ -1317,11 +1317,11 @@ As long as you know you're sticking with tkinter for the short term, it's safe t
## The Non-PEP8 Methods and Functions
Why the need for these bindings? Simply put, the PySimpleGUI SDK has a PEP8 violation in the method and function names. PySimpleGUI uses CamelCase names for methods and functions. PEP8 suggests using snake_case_variables instead.
Why the need for these bindings? Simply put, the PySimpleGUI SDK has a PEP8 violation in the method and function names. PySimpleGUI uses CamelCase names for methods and functions. PEP8 suggests using snake_case_variables instead.
This has not caused any problems and few complaints, but it's important the the interfaces into PySimpleGUI be compliant. Perhaps one of the reasons for lack of complaints is that the Qt library also uses SnakeCase for its methods. This practice has the effect of labelling a package as being "not Pythonic" and also suggests that this package was originally used in another language and then ported to Python. This is exactly the situation with Qt. It was written for C++ and the interfaces continue to use C++ conventions.
***PySimpleGUI was written in Python, for Python.*** The reason for the name problem was one of ignorance. The PEP8 convention wasn't understood by the developers when PySimpleGUI was designed and implemented.
***PySimpleGUI was written in Python, for Python.*** The reason for the name problem was one of ignorance. The PEP8 convention wasn't understood by the developers when PySimpleGUI was designed and implemented.
You can, and will be able to for some time, use both names. However, at some point in the future, the CamelCase names will disappear. A utility is planned to do the conversion for the developer when the old names are remove from PySimpleGUI.
@ -1345,7 +1345,7 @@ For the time being, class variables will remain the way they are currently. It
Think of Popups as your first windows, sorta like your first bicycle. It worked well, but was limited. It probably wasn't long before you wanted more features and it seemed too limiting for your newly found sense of adventure.
When you've reached the point with Popups that you are thinking of filing a GitHub "Enhancement Issue" to get the Popup call extended to include a new feature that you think would be helpful.... not just to you but others is what you had in mind, right? For the good of others.
When you've reached the point with Popups that you are thinking of filing a GitHub "Enhancement Issue" to get the Popup call extended to include a new feature that you think would be helpful.... not just to you but others is what you had in mind, right? For the good of others.
Well, don't file that enhancement request. Instead, it's at THIS time that you should immediately turn to the section entitled "Custom Window API Calls - Your First Window". Congratulations, you just graduated and are now an official "GUI Designer". Oh, never mind that you only started learning Python 2 weeks ago, you're a real GUI Designer now so buck up and start acting like one. Write a popup function of your own. And then, compact that function down to a **single line of code**. Yes, these popups can be written in 1 line of code. The secret is to use the `close` parameter on your call to `window.read()`
@ -1353,15 +1353,15 @@ But, for now, let's stick with these 1-line window calls, the Popups. This is
popup_animated
popup_annoying
popup_auto_close
popup_auto_close
popup_cancel
popup_error
popup_get_file
popup_get_folder
popup_get_file
popup_get_folder
popup_get_text
popup_no_border
popup_no_buttons
popup_no_frame
popup_no_frame
popup_no_titlebar
popup_no_wait
popup_notify
@ -1553,21 +1553,21 @@ sg.popup_scrolled(my_text)
![scrolledtextbox 2](https://user-images.githubusercontent.com/13696193/43667324-712aa0d4-9745-11e8-83a9-a0d0570d0865.jpg)
The `popup_scrolled` will auto-fit the window size to the size of the text. Specify `None` in the height field of a `size` parameter to get auto-sized height.
The `popup_scrolled` will auto-fit the window size to the size of the text. Specify `None` in the height field of a `size` parameter to get auto-sized height.
This call will create a scrolled box 80 characters wide and a height dependent upon the number of lines of text.
This call will create a scrolled box 80 characters wide and a height dependent upon the number of lines of text.
`sg.popup_scrolled(my_text, size=(80, None))`
`sg.popup_scrolled(my_text, size=(80, None))`
Note that the default max number of lines before scrolling happens is set to 50. At 50 lines the scrolling will begin.
Note that the default max number of lines before scrolling happens is set to 50. At 50 lines the scrolling will begin.
If `non_blocking` parameter is set, then the call will not blocking waiting for the user to close the window. Execution will immediately return to the user. Handy when you want to dump out debug info without disrupting the program flow.
If `non_blocking` parameter is set, then the call will not blocking waiting for the user to close the window. Execution will immediately return to the user. Handy when you want to dump out debug info without disrupting the program flow.
### Non-Blocking Popups - popup_no_wait and the non_blocking parameter
The `popup` call `popup_no_wait` or `popup_non_blocking` will create a popup window and then immediately return control back to you. You can turn other popup calls into non-blocking popups if they have a `non_blocking` parameter. Setting `non_blocking` to True will cause the function to return immediately rather than waiting for the window to be closed.
This function is very handy for when you're **debugging** and want to display something as output but don't want to change the programs's overall timing by blocking. Think of it like a `print` statement. There are no return values on one of these Popups.
This function is very handy for when you're **debugging** and want to display something as output but don't want to change the programs's overall timing by blocking. Think of it like a `print` statement. There are no return values on one of these Popups.
### Popup Parameter Combinations
@ -1575,7 +1575,7 @@ So that you don't have to specify a potentially long list common parameters ther
## Popup Input
There are Popup calls for single-item inputs. These follow the pattern of `popup_get` followed by the type of item to get. There are 3 of these input Popups to choose from, each with settings enabling customization.
There are Popup calls for single-item inputs. These follow the pattern of `popup_get` followed by the type of item to get. There are 3 of these input Popups to choose from, each with settings enabling customization.
- `popup_get_text` - get a single line of text
- `popup_get_file` - get a filename
@ -1698,7 +1698,7 @@ Parameter Descriptions:
| bool | modal | If True then makes the popup will behave like a Modal window... all other windows are non-operational until this one is closed. Default = True |
| str or None | **RETURN** | string representing the file(s) chosen, None if cancelled or window closed with X
If configured as an Open File Popup then (save_as is not True) the dialog box will look like this.
If configured as an Open File Popup then (save_as is not True) the dialog box will look like this.
![snag-0060](https://user-images.githubusercontent.com/13696193/46761050-9831c680-cca1-11e8-8de9-68b15efe2c46.jpg)
@ -2112,7 +2112,7 @@ This is a slightly more complex, but maybe more realistic version that reads inp
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.
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 (almost) ANYTHING, except `None` or a List (a tuple is fine). 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.
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 (almost) ANYTHING, except `None` or a List (a tuple is fine). 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
import PySimpleGUI as sg
@ -2141,7 +2141,7 @@ window.close()
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.
I hope to start using it more soon.
## How GUI Programming in Python Should Look? At least for beginners ?
@ -2173,9 +2173,9 @@ print(folder_path, file_path)
![image](https://user-images.githubusercontent.com/46163555/70470775-cd01ff00-1a99-11ea-8b9c-8b33c8880c99.png)
The first line of code after the import is a call to `theme`.
The first line of code after the import is a call to `theme`.
Until Dec 2019 the way a "theme" was specific in PySimpleGUI was to call `change_look_and_feel`. That call has been replaced by the more simple function `theme`.
Until Dec 2019 the way a "theme" was specific in PySimpleGUI was to call `change_look_and_feel`. That call has been replaced by the more simple function `theme`.
### Window contents (The Layout)
@ -2254,7 +2254,7 @@ For Windows that have specifically enabled these. Please see the appropriate se
### Window closed event
Another convention to follow is the check for windows being closed with an X. *This is an critically important event to catch*. If you don't check for this and you attempt to use the window, your program will crash, or silently consume 100% of your CPU. Please check for closed window and exit your program gracefully. Your users will like you for it.
Another convention to follow is the check for windows being closed with an X. *This is an critically important event to catch*. If you don't check for this and you attempt to use the window, your program will crash, or silently consume 100% of your CPU. 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. For other ports, such as PySimpleGUIWeb, not closing the Window will potentially cause your program to continue to run in the background.
@ -2517,7 +2517,7 @@ This is a complex window with quite a bit of custom sizing to make things line u
This window may look "ugly" to you which is because no effort has been made to make it look nice. It's purely functional. There are 30 Elements in the window. THIRTY Elements. Considering what it does, it's miraculous or in the least incredibly impressive. Why? Because in less than 50 lines of code that window was created, shown, collected the results and showed the results in another window.
50 lines. It'll take you 50 lines of tkinter or Qt code to get the first 3 elements of the window written, if you can even do that.
50 lines. It'll take you 50 lines of tkinter or Qt code to get the first 3 elements of the window written, if you can even do that.
No, let's be clear here... this window will take a massive amount of code using the conventional Python GUI packages. It's a fact and if you care to prove me wrong, then by ALL means PLEASE do it. Please write this window using tkinter, Qt, or WxPython and send the code!
@ -2529,7 +2529,7 @@ Clicking the Submit button caused the window call to return. The call to Popup
![image](https://user-images.githubusercontent.com/13696193/62234737-47f33480-b399-11e9-8a2c-087cc49868cd.png)
**`Note, event values can be None`**. The value for `event` will be the text that is displayed on the button element when it was created or the key for the button. If the user closed the window using the "X" in the upper right corner of the window, then `event` will be `sg.WIN_CLOSED` which is equal to `None`. It is ***vitally*** ***important*** that your code contain the proper checks for `sg.WIN_CLOSED`.
**`Note, event values can be None`**. The value for `event` will be the text that is displayed on the button element when it was created or the key for the button. If the user closed the window using the "X" in the upper right corner of the window, then `event` will be `sg.WIN_CLOSED` which is equal to `None`. It is ***vitally*** ***important*** that your code contain the proper checks for `sg.WIN_CLOSED`.
For "persistent windows", **always give your users a way out of the window**. Otherwise you'll end up with windows that never properly close. It's literally 2 lines of code that you'll find in every Demo Program. While you're at it, make sure a `window.close()` call is after your event loop so that your window closes for sure.
@ -2549,7 +2549,7 @@ If, on the other hand, your operation is not under your control or you are unabl
### The "Old Way"
There are a couple of demo programs available for you to see how to do this. You basically put your work into a thread. When the thread is completed, it tells the GUI by sending a message through a queue. The event loop will run with a timer set to a value that represents how "responsive" you want your GUI to be to the work completing.
There are a couple of demo programs available for you to see how to do this. You basically put your work into a thread. When the thread is completed, it tells the GUI by sending a message through a queue. The event loop will run with a timer set to a value that represents how "responsive" you want your GUI to be to the work completing.
### The "New Way" - `Window.write_event_value`
@ -2748,7 +2748,7 @@ theme_previewer
# Window Object - Beginning a window
The first step is to create the window object using the desired window customizations.
The first step is to create the window object using the desired window customizations.
## Modal Windows (only applied to tkinter port currently
)
@ -2758,7 +2758,7 @@ NOTE - as of PySimpleGUI 4.25.0 Modal Windows are supported! By default the `po
## Making your window modal
To make a Modal Wio=ndow you have 2 options.
To make a Modal Wio=ndow you have 2 options.
1. Set the `moodel=True` parameter in your Window calls.
@ -2778,7 +2778,7 @@ PySimpleGUI computes the exact center of your window and centers the window on t
#### Multiple Monitors and Linux
The auto-centering (default) location for your PySimpleGUI window may not be correct if you have multiple monitors on a Linux system. On Windows multiple monitors appear to work ok as the primary monitor the tkinter utilizes and reports on.
The auto-centering (default) location for your PySimpleGUI window may not be correct if you have multiple monitors on a Linux system. On Windows multiple monitors appear to work ok as the primary monitor the tkinter utilizes and reports on.
Linux users with multiple monitors that have a problem when running with the default location will need to specify the location the window should be placed when creating the window by setting the `location` parameter.
@ -2939,7 +2939,7 @@ If it feels like this layout section is too much too soon, then come back to thi
While you've not learned about Elements yet, it makes sense for this section to be up front so that you'll have learned how to use the elements prior to learning how each element works. At this point in your PySimpleGUI education, it is better for you to grasp time efficient ways of working with Elements than what each Element does. By learning now how to assemble Elements now, you'll have a good model to put the elements you learn into.
There are *several* aspects of PySimpleGUI that make it more "Pythonic" than other Python GUI SDKs. One of the areas that is unique to PySimpleGUI is how a window's "layout" is defined, specified or built. A window's "layout" is simply a list of lists of elements. As you've already learned, these lists combine to form a complete window. This method of defining a window is super-powerful because lists are core to the Python language as a whole and thus are very easy to create and manipulate.
There are *several* aspects of PySimpleGUI that make it more "Pythonic" than other Python GUI SDKs. One of the areas that is unique to PySimpleGUI is how a window's "layout" is defined, specified or built. A window's "layout" is simply a list of lists of elements. As you've already learned, these lists combine to form a complete window. This method of defining a window is super-powerful because lists are core to the Python language as a whole and thus are very easy to create and manipulate.
Think about that for a moment and compare/contrast with Qt, tkinter, etc.. With PySimpleGUI the location of your element in a matrix determines where that Element is shown in the window. It's so ***simple*** and that makes it incredibly powerful. Want to switch a row in your GUI that has text with the one below it that has an input element? No problem, swap the lines of code and you're done.
@ -2947,7 +2947,7 @@ Layouts were designed to be visual. The idea is for you to be able to envision h
In the process of creating your window, you can manipulate these lists of elements without having an impact on the elements or on your window. Until you perform a "layout" of the list, they are nothing more than lists containing objects (they just happen to be your window's elements).
Many times your window definition / layout will be a static, straightforward to create.
Many times your window definition / layout will be a static, straightforward to create.
However, window layouts are not limited to being one of these statically defined list of Elements.
@ -3014,7 +3014,7 @@ BUT, we're not done yet!
This is **Python**, we're using lists to build something up, so we should be looking at ****list comprehensions****. Let's change the `for` loop into a list comprehension. Recall that our `for` loop was used to concatenate 6 rows into a layout.
```python
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
```
Here we've moved the `for` loop to inside of the list definition (a list comprehension)
@ -3024,7 +3024,7 @@ Here we've moved the `for` loop to inside of the list definition (a list compreh
We have our rows built using the list comprehension, now we just need the buttons. They can be easily "tacked onto the end" by simple addition.
```python
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
layout = [[sg.Text(f'{i}. '), sg.In(key=i)] for i in range(1,6)]
layout += [[sg.Button('Save'), sg.Button('Exit')]]
```
@ -3068,7 +3068,7 @@ event, values = sg.Window('To Do List Example', layout=[[sg.Text(f'{i}. '), sg.I
## Example - List Comprehension to Build Rows - Table Simulation - Grid of Inputs
In this example we're building a "table" that is 4 wide by 10 high using `Input` elements
In this example we're building a "table" that is 4 wide by 10 high using `Input` elements
The end results we're seeking is something like this:
@ -3211,9 +3211,9 @@ Using your new `CBtn` Element, you could rewrite the row of buttons above as:
[CBtn('1'), CBtn('2'), CBtn('3'), CBtn('log'), CBtn('ln'), CBtn('-')],
```
See the tremendous amount of code you do not have to write! USE this construct any time you find yourself copying an element many times.
See the tremendous amount of code you do not have to write! USE this construct any time you find yourself copying an element many times.
But let's not stop there.
But let's not stop there.
Since we've been discussing list comprehensions, let's use them to create this row. The way to do that is to make a list of the symbols that go across the row make a loop that steps through that list. The result is a list that looks like this:
@ -3317,7 +3317,7 @@ You will find information on Elements and all other classes and functions are lo
## Keys
***Keys are a super important concept to understand in PySimpleGUI.***
***Keys are a super important concept to understand in PySimpleGUI.***
If you are going to do anything beyond the basic stuff with your GUI, then you need to understand keys.
@ -3345,7 +3345,7 @@ You also use the same key if you want to call Update on an element. Please see
window['key']
```
While you'll often see keys written as strings in examples in this document, know that keys can be ***ANYTHING***.
While you'll often see keys written as strings in examples in this document, know that 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)
@ -3357,7 +3357,7 @@ Then when you read the `values` variable that's returned to you from calling `Wi
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) or the most recent convention is to use a dash at the beginning and end (e.g. `'-KEY_NAME-'`). You don't have to follow the convention, but it's not a bad one to follow as other users are used to seeing this format and it's easy to spot when element keys are being used.
If you have an element object, to find its key, access the member variable `.Key` for the element. This assumes you've got the element in a variable already.
If you have an element object, to find its key, access the member variable `.Key` for the element. This assumes you've got the element in a variable already.
```python
text_elem = sg.Text('', key='-TEXT-')
@ -3367,9 +3367,9 @@ the_key = text_elem.Key
### Default Keys
If you fail to place a key on an Element, then one will be created for you automatically.
If you fail to place a key on an Element, then one will be created for you automatically.
For `Buttons`, the text on the button is that button's key. `Text` elements will default to the text's string (for when events are enabled and the text is clicked)
For `Buttons`, the text on the button is that button's key. `Text` elements will default to the text's string (for when events are enabled and the text is clicked)
If the element is one of the input elements (one that will cause an generate an entry in the return values dictionary) and you fail to specify one, then a number will be assigned to it beginning with the number 0. The effect will be as if the values are represented as a list even if a dictionary is used.
@ -3489,7 +3489,7 @@ Keys can be a variety of types, including tuples. In this particular program we
### Example 3 - No close match found
In this example, as you can see in the error popup, there was such a mismatch that no substitution could be performed.
In this example, as you can see in the error popup, there was such a mismatch that no substitution could be performed.
![SNAG-0886](https://user-images.githubusercontent.com/46163555/88705707-e6fe5980-d0dd-11ea-8fcc-bc024298705d.jpg)
@ -3564,7 +3564,7 @@ Tooltips are one of those "polish" items that really dress-up a GUI and show's a
Info on setting default element sizes is discussed in the Window section above.
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.
@ -3625,7 +3625,7 @@ See the section above that has full information about keys.
Beginning in version 3.17 you can create Elements that are initially invisible that you can later make visible.
To create an invisible Element, place the element in the layout like you normally would and add the parameter
To create an invisible Element, place the element in the layout like you normally would and add the parameter
`visible=False`.
@ -3635,9 +3635,9 @@ This feature works best on Qt, but does work on the tkinter version as well. Th
Note - Tkinter elements behave differently than Qt elements in how they arrange themselves when going from invisible to visible.
tkinter elements tend to STACK themselves.
tkinter elements tend to STACK themselves.
One workaround is to place the element in a Column with other elements on its row. This will hold the place of the row it is to be placed on. It will move the element to the end of the row however.
One workaround is to place the element in a Column with other elements on its row. This will hold the place of the row it is to be placed on. It will move the element to the end of the row however.
If you want to not only make the element invisible, on tkinter you can call `Element.
@ -3645,11 +3645,11 @@ Qt elements tend to hold their place really well and the window resizes itself n
## Shortcut Functions / Multiple Function Names
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" (and methods/functions) have "shortcuts".
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" (and methods/functions) 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` .
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. BUT, even that has now been shortened to `window[key]`
@ -3667,7 +3667,7 @@ layout = [
![simple text](https://user-images.githubusercontent.com/13696193/44959877-e9d97b00-aec3-11e8-9d24-b4405ee4a148.jpg)
When creating a Text Element that you will later update, make sure you reserve enough characters for the new text. When a Text Element is created without a size parameter, it is created to exactly fit the characters provided.
When creating a Text Element that you will later update, make sure you reserve enough characters for the new text. When a Text Element is created without a size parameter, it is created to exactly fit the characters provided.
With proportional spaced fonts (normally the default) the pixel size of one set of characters will differ from the pixel size of a different set of characters even though the set is of the same number of characters. In other words, not all letters use the same number of pixels. Look at the text you're reading right now and you will see this. An "i" takes up a less space then an "A".
@ -3675,7 +3675,7 @@ With proportional spaced fonts (normally the default) the pixel size of one set
## `Window.FindElement(key)` shortened to `Window[key]`
There's been a fantastic leap forward in making PySimpleGUI code more compact.
There's been a fantastic leap forward in making PySimpleGUI code more compact.
Instead of writing:
```python
@ -3694,9 +3694,9 @@ MANY Thanks is owed to the nngogol that suggested and showed me how to do this.
## `Element.update()` -> `Element()` shortcut
This has to be one of the strangest syntactical constructs I've ever written.
This has to be one of the strangest syntactical constructs I've ever written.
It is best used in combination with `FindElement` (see prior section on how to shortcut `FindElement`).
It is best used in combination with `FindElement` (see prior section on how to shortcut `FindElement`).
Normally to change an element, you "find" it, then call its `update` method. The code usually looks like this, as you saw in the previous section:
@ -3732,7 +3732,7 @@ event, values = window.read()
It is confusing looking however so when used, it might be a good idea to write a comment at the end of the statement to help out the poor beginner programmer coming along behind you.
Because it's such a foreign construct that someone with 1 week of Python classes will not recognize, the demos will continue to use the `.update` method.
Because it's such a foreign construct that someone with 1 week of Python classes will not recognize, the demos will continue to use the `.update` method.
It does not have to be used in conjuction with `FindElement`. The call works on any previously made Element. Sometimes elements are created, stored into a variable and then that variable is used in the layout. For example.
@ -3761,7 +3761,7 @@ Individual colors are specified using either the color names as defined in tkint
"#RRGGBB" or "darkblue"
### `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. You need to remember this when you create `Text` elements that you are using for output.
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. Notice that for Text elements with an empty string, no string value needs to be indicated. The default value for strings is `''` for Text Elements. 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
@ -4009,7 +4009,7 @@ These Pre-made buttons are some of the most important elements of all because th
- SaveAs
- Open
### "Chooser" Buttons
### "Chooser" Buttons
These buttons are used to show dialog boxes that choose something like a filename, date, color, etc.. that are filled into an `InputText` Element (or some other "target".... see below regarding targets)
@ -4126,7 +4126,7 @@ Your button images need to be in PNG or GIF format. When you make a button with
`TRANSPARENT_BUTTON` - **Important** - This is a legacy value that is misleading. It is currently defined as this constant value:
```python
TRANSPARENT_BUTTON = ('#F0F0F0', '#F0F0F0')
TRANSPARENT_BUTTON = ('#F0F0F0', '#F0F0F0')
```
As you can see it is simply a tuple of 2 gray colors. The effect is that the button text and the button background color to a specific shade of gray. Way back in time, before you could change the background colors and all windows were gray, this value worked. But now that your button can be on any background color, you'll want to set the buttons color to match the background so that your button blends with the background color.
@ -4159,7 +4159,7 @@ sg.Button('Pause', button_color=(sg.theme_background_color(), sg.theme_backgroun
border_width=0)
```
Experimentation is sometimes required for these concepts to really sink in and they can vary depending on the underlying GUI framework.
Experimentation is sometimes required for these concepts to really sink in and they can vary depending on the underlying GUI framework.
Button Images do work so play with them. You can use PIL to change the size of your images before passing to PySimpleGUI.
@ -4352,7 +4352,7 @@ Starting in version 2.9 you'll be able to do more complex layouts by using the C
Columns are specified, like all "container elements", in exactly the same way as a window, as a list of lists.
Columns are needed when you want to specify more than 1 element in a single row.
Columns are needed when you want to specify more than 1 element in a single row.
For example, this layout has a single slider element that spans several rows followed by 7 `Text` and `Input` elements on the same row.
@ -4408,7 +4408,7 @@ This is currently only available in the primary PySimpleGUI port.
They can also be used to justify a group of elements in a particular way.
Placing `Column` elements inside `Columns` elements make it possible to create a multitude of
Placing `Column` elements inside `Columns` elements make it possible to create a multitude of
## Sizer Element
@ -4539,7 +4539,7 @@ graph.DeleteFigure(my_circle)
### Mouse Events Inside Graph Elements
If you have enabled events for your Graph Element, then you can receive mouse click events. If you additionally enable `drag_submits` in your creation of the Graph Element, then you will also get events when you "DRAG" inside of a window. A "Drag" is defined as a left button down and then the mouse is moved.
If you have enabled events for your Graph Element, then you can receive mouse click events. If you additionally enable `drag_submits` in your creation of the Graph Element, then you will also get events when you "DRAG" inside of a window. A "Drag" is defined as a left button down and then the mouse is moved.
When a drag event happens, the event will be the Graph Element's key. The `value` returned in the values dictionary is a tuple of the (x,y) location of the mouse currently.
@ -4600,7 +4600,7 @@ data = [['' for row in range(15)]for col in range(6)]
### Events from Tables
There are two ways to get events generated from Table Element.
There are two ways to get events generated from Table Element.
`change_submits` event generated as soon as a row is clicked on
`bind_return_key` event generate when a row is double clicked or the return key is press while on a row.
@ -4657,7 +4657,7 @@ Just like windows and the other container elements, the `Tab` Element has a layo
`Tab` layouts look exactly like Window layouts, that is they are **a list of lists of Elements**.
*How you place a Tab element into a window is different than all other elements.* You cannot place a Tab directly into a Window's layout.
*How you place a Tab element into a window is different than all other elements.* You cannot place a Tab directly into a Window's layout.
Also, tabs cannot be made invisible at this time. They have a visibility parameter but calling update will not change it.
@ -4774,7 +4774,7 @@ SystemTray(menu=None, filename=None, data=None, data_base64=None, tooltip=None,
:param filename: filename for icon
:param data: in-ram image for icon
:param data_base64: basee-64 data for icon
:param tooltip: tooltip string
:param tooltip: tooltip string
:param metadata: (Any) User metadata that can be set to ANYTHING
'''
```
@ -4965,7 +4965,7 @@ This is a blocking call so expect it to take a few seconds if you're fading the
# Global Settings
There are multiple ways to customize PySimpleGUI. The call with the most granularity (allows access to specific and precise settings). The `ChangeLookAndFeel` call is in reality a single call to `SetOptions` where it changes 13 different settings.
There are multiple ways to customize PySimpleGUI. The call with the most granularity (allows access to specific and precise settings). The `ChangeLookAndFeel` call is in reality a single call to `SetOptions` where it changes 13 different settings.
**Mac Users** - You can't call `ChangeLookAndFeel` but you can call `SetOptions` with any sets of values you want. Nothing is being blocked or filtered.
@ -5012,7 +5012,7 @@ window.close()
## Read(timeout = t, timeout_key=TIMEOUT_KEY, close=False)
Read with a timeout is a very good thing for your GUIs to use in a non-blocking read situation. If your device can wait for a little while, then use this kind of read. The longer you're able to add to the timeout value, the less CPU time you'll be taking.
Read with a timeout is a very good thing for your GUIs to use in a non-blocking read situation. If your device can wait for a little while, then use this kind of read. The longer you're able to add to the timeout value, the less CPU time you'll be taking.
The idea to wait for some number of milliseconds before returning. It's a trivial way to make a window that runs on a periodic basis.
@ -5031,7 +5031,7 @@ while True: # Event Loop
time.sleep(.1) # sleep 1/10 second DO NOT PUT SLEEPS IN YOUR EVENT LOOP!
```
This program will quickly test for user input, then deal with the hardware. Then it'll sleep for 100ms, while your gui is non-responsive, then it'll check in with your GUI again.
This program will quickly test for user input, then deal with the hardware. Then it'll sleep for 100ms, while your gui is non-responsive, then it'll check in with your GUI again.
The better way using PySimpleGUI... using the Read Timeout mechanism, the sleep goes away.
@ -5067,7 +5067,7 @@ You may find some PySimpleGUI programs that set the timeout value to zero. This
A true non-blocking (timeout=0) read is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine or a read with a timeout would work.
It's valid to use a timeout value of zero if you're in need of every bit of CPU horsepower in your application. Maybe your loop is doing something super-CPU intensive and you can't afford for the GUI to use any CPU time. This is the kind of situation where a timeout of zero is appropriate.
It's valid to use a timeout value of zero if you're in need of every bit of CPU horsepower in your application. Maybe your loop is doing something super-CPU intensive and you can't afford for the GUI to use any CPU time. This is the kind of situation where a timeout of zero is appropriate.
Be a good computing citizen. Run with a non-zero timeout so that other programs on your CPU will have time to run.
@ -5211,7 +5211,7 @@ window = sg.Window('My new window', layout, finalize=True)
window['-TEXT-'].update('My new text value')
while True: # Event Loop
event, values = window.read()
event, values = window.read()
if event == sg.WIN_CLOSED:
break
```
@ -5308,7 +5308,7 @@ It is possible to change the normal arrow cursor into something else by setting
One of the best examples is URLs. Users are accustomed to seeing a hand cursor when the mouse is moved over a link. By setting the cursor to a hand for a Text element that has text that is in the format of a URL, it signals to the user that it's a link that can be clicked.
The `set_cursor` method is used to set the cursor for an element. Perform an element look-up or use a variable containing an element, and call the `set_cursor` method, passing in a string that selects the cursor. The valid cursor names are documented in the tkinter docs as this call maps directly to a tkinter call.
The `set_cursor` method is used to set the cursor for an element. Perform an element look-up or use a variable containing an element, and call the `set_cursor` method, passing in a string that selects the cursor. The valid cursor names are documented in the tkinter docs as this call maps directly to a tkinter call.
These cursor strings were obtained from the Tk manual and are what you pass into the `set_cursor` methods.
@ -5482,7 +5482,7 @@ This would work to make a menu bar from a series of these individual menu defint
menu_bar = [right_click_menu_1, right_click_menu_2, button_menu_def ]
```
And, of course, the direction works the opposite too. You can take a Menu Bar definition and pull out an individual menu item to create a right click or button menu.
And, of course, the direction works the opposite too. You can take a Menu Bar definition and pull out an individual menu item to create a right click or button menu.
# Running Multiple Windows
@ -5647,7 +5647,7 @@ This timeout value of 200 means that your debugger GUI will be updated 5 times a
Let's say you're in a situation where a very intermettent bug has just happened and the debugger would really help you, but you don't have a timeout on your `windows.read()` call. It's OK. Recall that the way the debugger gets its "cycles" is to borrow from your `Read` calls. What you need to do is alternate between using the debugger and then generating another pass through your event loop.
Maybe it's an OK button that will cause your loop to execute again (without exiting). If so, you can use it to help move the debugger along.
Maybe it's an OK button that will cause your loop to execute again (without exiting). If so, you can use it to help move the debugger along.
Yes, this is a major pain in the ass, but it's not THAT bad and compared to nothing in a time of crisis and this is potentially your "savior tool" that's going to save your ass, pressing that OK button a few times is going to look like nothing to you. You just want to dump out the value of a variable that holds an instance of your class!
@ -5691,7 +5691,7 @@ There are 3 ways of opening the Popout window.
#### When you are asked for the "Location of your PySimpleGUI package or PySimpleGUI.py file" do this
If you wish to use the debugger to find the location of THIS running program's PySimpleGUI package / the PySimpleGUI.py file, then all you need to do is:
* Press the `BREAK` key on your keyboard.
* Press the `BREAK` key on your keyboard.
* This is sometimes labelled as the `Cancel` key
* May also have `Pause` printed on key
* On some US keyboards, it is located next to `Scroll Lock` and/or above `PageUp` key
@ -5754,21 +5754,21 @@ We can see the variables we checked as well as the defined expression `values[0]
![SNAG-0441](https://user-images.githubusercontent.com/13696193/62797507-e7a37780-baa9-11e9-93c4-6ff0c8acb11d.jpg)
This tab is provided to you as a way to interact with your running program on a real-time basis.
This tab is provided to you as a way to interact with your running program on a real-time basis.
If you want to quickly look at the values of variables, nearly ANY variables, then type the information into one of the 3 spaces provided to "Watch" either variables or experessions. In this example, the variable window was typed into the first slow.
If you want to quickly look at the values of variables, nearly ANY variables, then type the information into one of the 3 spaces provided to "Watch" either variables or experessions. In this example, the variable window was typed into the first slow.
***Immediately*** after typing the character 'w', the information to the right was displayed. No button needs to be clicked. You merely neeed to type in a valid experession and it will be displayed to you.... and it will be displayed on an on-going, constantly-refreshing-basis.
![SNAG-0447](https://user-images.githubusercontent.com/13696193/62797393-a0b58200-baa9-11e9-8016-1cadca4d97e7.jpg)
If the area to the right of the input field is too small, then you can click on the "Detail" button and you will be shown a popup, scrolled window with all of the information displayed as if it were printed.
If the area to the right of the input field is too small, then you can click on the "Detail" button and you will be shown a popup, scrolled window with all of the information displayed as if it were printed.
I'm sure you've had the lovely experience of printing an object. When clicking the "Detail" button next to the `window` variable being shown, this window is shown:
![SNAG-0449](https://user-images.githubusercontent.com/13696193/62801423-b0d25f00-bab3-11e9-829a-aebb429521cd.jpg)
Oh, Python, -sigh-. I just want to see my `window` object printed.
Oh, Python, -sigh-. I just want to see my `window` object printed.
#### `Obj` Button to the Rescue!
@ -5780,13 +5780,13 @@ PySimpleGUI has a fun and very useful function that is discussed in the docs nam
While not **really** a Python REPL prompt, this window's `REPL >>>` prompt is meant to act as much like one as possible. Here you can enter experessions and code too.
The uses for this prompt are so numerous and diverse that listing them all won't be attempted.
The uses for this prompt are so numerous and diverse that listing them all won't be attempted.
### Your "XRay" and "Endoscope" into Your Program
Think of this prompt as a way to get specific diagnostics information about your ***running*** program. It cannot be stressed enough that the power and the usefullness of this tool is in its ability to diagnose a running program, after you've already started it running.
Think of this prompt as a way to get specific diagnostics information about your ***running*** program. It cannot be stressed enough that the power and the usefullness of this tool is in its ability to diagnose a running program, after you've already started it running.
### Execute Code
### Execute Code
In addition to displaying information, getting paths to packages, finding version information, you can execute code from the PySimpleGUI Debugger's `REPL >>>` prompt. You can type in any expression as well as any **executable statement**.
@ -5797,7 +5797,7 @@ The result is that you are shown a popup window with the text you supplied.
### KNOW Answers to Questions About Your Program
Using this runtime tool, you can be confident in the data you collect. Right?
Using this runtime tool, you can be confident in the data you collect. Right?
***There's no better way to find what version of a package that your program is using than to ask your program.*** This is so true. Think about it. Rather than go into PyCharm, look at your project's "Virtual Environment", follow some path to get to a window that lists packages installed for that project, get the verstion and your're done, right? Well, maybe. But are you CERTAIN your program is using THAT version of the package in question?
@ -5856,7 +5856,7 @@ While using JSON files to save and load a settings dictionary isn't very difficu
There have already been some demo programs written that use JSON files to store settings. You can expect that this capability will begin to show up in more demos in the future since it's now part of PySimpleGUI.
User settings are stored in a Python dictionary which is saved to / loaded from disk. Individual settings are thus keys into a dictionary. You do not need to explicitly read nor write the file. Changing any entry will cause the file to be saved. Reading any entry will cause the file to be read if it hasn't already been read.
User settings are stored in a Python dictionary which is saved to / loaded from disk. Individual settings are thus keys into a dictionary. You do not need to explicitly read nor write the file. Changing any entry will cause the file to be saved. Reading any entry will cause the file to be read if it hasn't already been read.
## Two Interfaces
@ -5915,7 +5915,7 @@ In addition to the filename having a default value, the path to the file also ha
When calling the User Settings APIs, if a parameter is named `filename`, you can specify a full path or just the filename. This will save you the trouble of having to split up your path and filename in your code. If you specify only the path, the the filename will be added to that path and named as defined earlier.
Like the rest of PySimpleGUI, the idea is for you to write as little code as possible. The default values for the filename and path should be fine for you to use. They will be stored in a location on your system that is meant to store user settings.
Like the rest of PySimpleGUI, the idea is for you to write as little code as possible. The default values for the filename and path should be fine for you to use. They will be stored in a location on your system that is meant to store user settings.
### Setting Filename
@ -5923,7 +5923,7 @@ If you want to see what the current filename is for your settings, then you can
To make the code for specifying the folder and filename as simple as possible, the 2 parts are separated in the call specifying the name of the settings file. However, it is possible to supply a full and complete folder + filename as well.
The default filename for your settings file is the name of the file that makes the call to the User Settings API's with the `.py` extension changed to a `.json` extension. If your source file is called `demo.py`, then your settings filename will be `demo.json`.
The default filename for your settings file is the name of the file that makes the call to the User Settings API's with the `.py` extension changed to a `.json` extension. If your source file is called `demo.py`, then your settings filename will be `demo.json`.
#### Setting only the filename
@ -5974,13 +5974,13 @@ Calling `user_settings_filename` with no parameters will return the full path an
### File Loading / Saving
Generally speaking you will not need to load or save your settings file. It is automatically saved after every change.
Generally speaking you will not need to load or save your settings file. It is automatically saved after every change.
Note that reading a setting can also cause the file to be written. If you read a setting and the setting did not exist, then your call to `user_settings_get_entry` will return the default value you specified. As a result, the dictionary is updated with this default value and in return the file is written with this value as well.
One of the situations where you may want to explicitly read/load the settings file is if you're expecting it to be modified by another program.
Like so much of PySimpleGUI, as much as possible is automatically done on your behalf. This includes the requirement of saving and loading your settings file. Even naming your settings file is optional.
Like so much of PySimpleGUI, as much as possible is automatically done on your behalf. This includes the requirement of saving and loading your settings file. Even naming your settings file is optional.
## The `UserSettings` Class Interface
@ -6111,7 +6111,7 @@ You should be able to easily figure out these errors as they are file operations
### Silenting the Errors
If you're the type that doesn't want to see any error messages printed out on your console, then you can silence the error output.
If you're the type that doesn't want to see any error messages printed out on your console, then you can silence the error output.
When using the class interface, there is a parameter `silent_on_error` that you can set to `True`.
@ -6203,7 +6203,7 @@ while True:
window.close()
```
If you were to place these 2 examples in the same file so that one ran after the other, you will find that the same settings file is used and thus the value saved in the first example will be read by the second one.
If you were to place these 2 examples in the same file so that one ran after the other, you will find that the same settings file is used and thus the value saved in the first example will be read by the second one.
There was one additional line of code added:
@ -6222,7 +6222,7 @@ There are a number of demo programs that show how to use UserSettings to create
If you're using the default path, remember that previous runs of your file may have old settings that are still in your settings file. It can get confusing when you've forgotten that you previously wrote a setting. Not seeing the filename can have drawbacks like this.
Also, because the settings automatically save after every update, it can be easy to accidently overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
Also, because the settings automatically save after every update, it can be easy to accidently overwrite a previously saved setting. If you want to avoid this, then perhaps it's best that you work with a dictionary within your code and then explicitly save your dictionary when you're ready to commit it to disk.
To save your Python dictionary to a settings file, simply call `user_settings_write_new_dictionary(dict)`, passing in your dictionary as the parameter.
@ -6230,7 +6230,7 @@ To save your Python dictionary to a settings file, simply call `user_settings_wr
# Extending PySimpleGUI
PySimpleGUI doesn't and can't provide every single setting available in the underlying GUI framework. Not all tkinter options are available for a `Text` Element. Same with PySimpleGUIQt and the other ports.
PySimpleGUI doesn't and can't provide every single setting available in the underlying GUI framework. Not all tkinter options are available for a `Text` Element. Same with PySimpleGUIQt and the other ports.
There are a few of reasons for this.
@ -6242,13 +6242,13 @@ However, PySimpleGUI programs are ***not*** dead ends!! Writing PySimpleGUI cod
## Widget Access
Most of the user extensions / enhancements are at the "Element" level. You want some Element to do a trick that you cannot do using the existing PySimpleGUI APIs. It's just not possible. What to do?
Most of the user extensions / enhancements are at the "Element" level. You want some Element to do a trick that you cannot do using the existing PySimpleGUI APIs. It's just not possible. What to do?
What you need is access to the underlying GUI framework's "Widget". The good news is that you HAVE that access ready and waiting for you, for all of the ports of PySimpleGUI, not just the tkinter one.
### `Element.Widget` is The GUI Widget
The class variable `Widget` contains the tkinter, Qt, WxPython, or Remi widget. With that variable you can modify that widget directly.
The class variable `Widget` contains the tkinter, Qt, WxPython, or Remi widget. With that variable you can modify that widget directly.
***You must first `Read` or `Finalize` the window before accessing the `Widget` class variable***
@ -6276,7 +6276,7 @@ So far there have been 2 uses of this capability. One already mentioned is addi
A recent Issue posted was that focus was always being set on a button in a tab when you switch tabs in tkinter. The user didn't want this to happen as it was putting an ugly black line around their nicely made graphical button.
There is no current way in PySimpleGUI to "disable focus" on an Element. That's essentially what was needed, the ability to tell tkinter that this widget should never get focus.
There is no current way in PySimpleGUI to "disable focus" on an Element. That's essentially what was needed, the ability to tell tkinter that this widget should never get focus.
There is a way to tell tkinter that a widget should not get focus. The downside is that if you use your tab key to navigate, that element will never get focus. So, it's not only blocking focus for this automatic problem, but blocking it for all uses. Of course you can still click on the button.