From e9d6b975957f3ccf23eaf2098a2791c8171023c0 Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Fri, 8 Nov 2019 17:32:00 -0500 Subject: [PATCH] The latest readme components --- readme_creator/1_HEADER_top_part.md | 113 +- readme_creator/2_readme.md | 905 ++++++- readme_creator/4_Release_notes.md | 38 +- readme_creator/PySimpleGUIlib.py | 636 +++-- readme_creator/readme.md | 3911 +++++++++++++++++++++++++-- readme_creator/show_all_tags.py | 2 +- 6 files changed, 5039 insertions(+), 566 deletions(-) diff --git a/readme_creator/1_HEADER_top_part.md b/readme_creator/1_HEADER_top_part.md index 177afc26..246903fe 100644 --- a/readme_creator/1_HEADER_top_part.md +++ b/readme_creator/1_HEADER_top_part.md @@ -27,41 +27,78 @@ HOW DO I INSERT IMAGES ??? ![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) + [![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) tkinter - [![Downloads ](https://pepy.tech/badge/pysimplegui27)](https://pepy.tech/project/pysimplegui27) tkinter 2.7 - [![Downloads](https://pepy.tech/badge/pysimpleguiqt)](https://pepy.tech/project/pysimpleguiqt) Qt - [![Downloads](https://pepy.tech/badge/pysimpleguiwx)](https://pepy.tech/project/pysimpleguiWx) WxPython - [![Downloads](https://pepy.tech/badge/pysimpleguiweb)](https://pepy.tech/project/pysimpleguiWeb) Web (Remi) ![Documentation Status](https://readthedocs.org/projects/pysimplegui/badge/?version=latest) - ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) - ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.5.0-red.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.1-blue.svg?longCache=true&style=for-the-badge) -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.4.0-red.svg?longCache=true&style=for-the-badge) - -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.0-blue.svg?longCache=true&style=for-the-badge) - -![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.26.0-orange.svg?longCache=true&style=for-the-badge) - +![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.28.0-orange.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUIWx_version-0.11.0-orange.svg?longCache=true&style=for-the-badge) - ![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_Version-0.28.1-orange.svg?longCache=true&style=for-the-badge) # PySimpleGUI User's Manual -## This manual is crammed full of answers so start your search for answers here. Read/Search this PRIOR to opening an Issue on GitHub. + ## Python GUI For Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces -#### July-2019 Note - This readme is being generated from the PySimpleGUI.py file located on GitHub. As a result, some of the calls or parameters may not match the PySimpleGUI that you pip installed. +### This manual is crammed full of answers so start your search for answers here. Read/Search this prior to opening an Issue on GitHub. Press Control F and type. +--- + +# Jump-Start + +## Install + +``` +pip install pysimplegui +or +pip3 install pysimplegui +``` + +### This Code + +```python +import PySimpleGUI as sg +# All the stuff inside your window. +layout = [ [sg.Text('Some text on Row 1')], + [sg.Text('Enter something on Row 2'), sg.InputText()], + [sg.Button('Ok'), sg.Button('Cancel')] ] + +# Create the Window +window = sg.Window('Window Title', layout) +# Event Loop to process "events" and get the "values" of the inputs +while True: + event, values = window.read() + if event in (None, 'Cancel'): # if user closes window or clicks cancel + break + print('You entered ', values[0]) + +window.close() +``` + +### Makes This Window + +and returns the value input as well as the button clicked. + +![image](https://user-images.githubusercontent.com/13696193/61077153-cdfc0b00-a3eb-11e9-9e93-d6ec2ffb442a.png) + +### Any Questions? It's that simple. + +--- + + + + #### Looking for a GUI package? Are you.... @@ -102,6 +139,8 @@ HOW DO I INSERT IMAGES ??? * 170+ Demo Programs teach you how to integrate with many popular packages like OpenCV, Matplotlib, PyGame, etc. * 200 pages of documentation, a Cookbook, built-in help using docstrings, in short it's heavily documented +#### July-2019 Note - This readme is being generated from the PySimpleGUI.py file located on GitHub. As a result, some of the calls or parameters may not match the PySimpleGUI that you pip installed. + ## GUI Development does not have to be difficult nor painful. It can be FUN #### What users are saying about PySimpleGUI @@ -141,7 +180,7 @@ HOW DO I INSERT IMAGES ??? [Brief Tutorial](http://Tutorial.PySimpleGUI.org) -[Latest Demos and Master Branch on GitHub](http//www.PySimpleGUI.com) +[Latest Demos and Master Branch on GitHub](https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPrograms) [Repl.it Home for PySimpleGUI](https://repl.it/@PySimpleGUI) @@ -171,7 +210,7 @@ Bluntness is required here as the subtle approach has not worked in the past: Re-read that statement. This **will** be a serious problem for you if you're the type of person that finds it "quicker and easier to post on StackOverflow rather than reading documentation". -If you have not yet matured to the point you are able to undertand this skill or choose to not follow it, then please save ***everyone*** the pain of doing **for you** what you, as a developer, software engineer, or wanna be coder, must do on your own. It's a vital skill for you to learn. +If you have not yet matured to the point you are able to understand this skill or choose to not follow it, then please save ***everyone*** the pain of doing **for you** what you, as a developer, software engineer, or wanna be coder, must do on your own. It's a vital skill for you to learn. Want to be a "real engineer"? Then follow "real engineering practices" such as "reading". You are learning a NEW GUI package. You've not seen anything like it. Don't be so arrogant as to believe you will never need to read documentation. @@ -229,9 +268,15 @@ PySimpleGUI runs on Windows, Linux and Mac, just like tkinter, Qt, WxPython and As of 9/25/2018 **both Python 3 and Python 2.7 are supported** when using **tkinter version** of PySimpleGUI! The Python 3 version is named `PySimpleGUI`. The Python 2.7 version is `PySimpleGUI27`. They are installed separately and the imports are different. See instructions in Installation section for more info. **None** of the other ports can use Python 2. +###### Python 2.7 Code will be deleted from this GitHub on Dec 31, 2019 + Note that the 2.7 port will *cease to exist on this GitHub* on Jan 1, 2020. If you would like to know how much time you have to move over to the Python 3 version of PySimpleGUI, then go here: https://pythonclock.org/. The only thing that will be available is an unsupported PyPI release of PySimpleGUI27. -By "will cease to exist on this GitHub" I mean, it will be deleted entirely. No source code, no supporting programs. Nothing. If you're stuck using 2.7 in December, it would behoove you to fork the 2.7 code on Dec 31, 2019. Legacy Python doesn't have a permanent home here. +By "will cease to exist on this GitHub" I mean, it will be deleted entirely. No source code, no supporting programs. Nothing. If you're stuck using 2.7 in December, it would behoove you to fork the 2.7 code on Dec 31, 2019. Legacy Python doesn't have a permanent home here. It sounds cruel, but experts in security particularly says 2.7 is a huge risk. Furthering it use only hurts the computing world. + +#### Warning - tkinter + Python 3.7.3 and later, including 3.8 has problems + +The version of tkinter that is being supplied with the 3.7.3 and later versions of Python is known to have a problem with table colors. Basically, they don't work. As a result, if you want to use the plain PySimpleGUI running on tkinter, you should be using 3.7.2 or less. 3.6 is the version PySimpleGUI has chosen as the recommended version for most users. ## Output Devices @@ -480,22 +525,40 @@ So, [open an Issue](https://github.com/PySimpleGUI/PySimpleGUI/issues/new/choose ### PySimpleGUI Trolls -Yea, they're out there. Would have NEVER in a billion years guessed that there would be objection to this package, coming from a small, but vocal, number of people. I naively believed everyone would be supportive, see the value, hold hands around the fire, sing songs, and in the very least be truthful. But, this ain't Kansas and the Internet is well... WTF is it with people? +Yea, they're out there. Would have NEVER in a billion years guessed that there would be objection to this package, coming from a small, but vocal, number of people. I naively believed everyone would be supportive, see the value, hold hands around the fire, sing songs, and in the very least be truthful. But, this ain't Kansas and the Internet is well... -If someone is actively discouraging you from using this package, then know you are on the right track and you should give it a try. Stuff like this sometimes happens because the person works for a particular company or they have a GUI package of their own.... that's not popuplar, or they just like to tear things down. +If someone is actively discouraging you from using this package, then know you are on the right track and you should give it a try. Stuff like this sometimes happens because the person works for a particular company or they have a GUI package of their own.... that's not popuplar, or they like to tear things down or I dunno... people can be really weird and emotional. -I promise you're not going to be wrecked for life (as has been claimed). It will not cause you to be a bad programmer with bad habits. It will not ruin your career. It's not going to teach you bad habits. One person I know got a bonus based on a PySimpleGUI program he wrote. +I promise you're not going to be wrecked for life. It will not cause you to be a bad programmer with bad habits. It will not ruin your career. It's not going to teach you bad habits. One person I know got a bonus based on a PySimpleGUI program he wrote. -So fear not. ***How about success being the goal?*** Spend time polishing your GUI and working on your primary code instead of struggling your way through the mountains of documentation in the Qt library, trying to set the color of something. +***How about success being the goal?*** Spend time polishing your GUI and working on your primary code instead of struggling your way through the mountains of documentation in the Qt library, trying to set the color of something. How about getting your program done, working, and in use? -Start with PySimpleGUI, then in the future if you want to code directly in Qt to get more control, it's not like you won't be able to pick up Qt due to your PySimpleGUI knowledge. If anything, you'll have more knowledge going it than most people that are just starting because you'll have already built working GUIs, perhaps many of them and understand how to layout an efficient interface as well as having a good education in GUI Widgets and how they work. +Start with PySimpleGUI, then in the future if you want to code directly in Qt, it's not like you won't be able to learn something else due to your PySimpleGUI knowledge. Unable to write a `while` loop because you already learned using a `for` loop? That seems to be the logic. + +If anything, you'll have more knowledge than most people that are just starting because you'll have already built working GUIs, perhaps many of them and understand how to layout an efficient interface as well as having a good education in GUI Widgets and how they work. + +Here are the forces likely at work.... said Troll has been programming for a while now and really knows these GUI frameworks. Probably invested a lot of hours learning them and thus has some marketable skills (yes, follow the money). + +Enter snotty-nosed high-shool or first year programmer using PySimpleGUI that manages to make GUI windows with great ease... that look, well, pretty much the **same** as the windows Sir Troll ***was*** used to getting paid big bucks to make. What used to be a skill only a select few can do, now 1,000's, 10,000's, or 100,000s more programmers can do, quicker and easier. Bummer Mr. Troll. Bummer. + +"***It's supposed to be difficult to write a GUI***" was an actual reason listed why not to use PySimpleGUI by one person offering to help junior programmers learn Qt. Really? It's supposed to be difficult. Huh. Well, not in this Python universe. Maybe in C++ world it works that way?? + +Just know you're safe in trying and possibly even succeeding in the process. ### Target Audience -PySimpleGUI is trying to serve the 80% of GUI *problems*. The other 20% go straight to tkinter, Qt, WxPython, Remi, or whatever fills that need. That 80% is a huge problem space. Again, the "Simple" of PySimpleGUI describes how easy it is to use, not the nature of the problem space it solves. Note that people are not part of that description. It's not trying to solve GUI problems for 80% of the people trying it. PySimpleGUI tries to solve 80% of GUI ***problems***, regardless of the programmer's experience level. +PySimpleGUI is trying to serve the 80% of GUI *problems*. The other 20% go straight to tkinter, Qt, WxPython, Remi, or whatever fills that need. That 80% is **a huge problem space**. -PySimpleGUI is designed with both the beginner and the experienceed developer in mind. Why? Because both tend to like compact code. Most like people, we just want to get sh\*t done, right? +***The "Simple" of PySimpleGUI describes how easy it is to use, not the nature of the problem space it solves.*** Note that people are not part of that description. It's not trying to solve GUI problems for 80% of the people trying it. PySimpleGUI tries to solve 80% of GUI ***problems***, regardless of the programmer's experience level. + +Is file I/O in Python limited to only certain people? Is starting a thread, building a multi-threaded Python program incredibly difficult such that it takes a year to learn? No. It's quite easy. Like most things Python, you import the object from package and you use it. It is 2 lines of Python code to create and start a thread. + +Why can't it be 2 lines of code to show a GUI window? What's SO special about the Python GUI libraries that they require you to follow a specific Object Oriented model of development? Other parts and packages of Python don't tend to do that. + +The reason is because they didn't originate in Python. They are strangers in a strange land and they had to be "adapted". They started as C++ programs / SDKs, and remain that way too. There's a vaneer of Python slapped onto the top of them, but that sure didn't make them fit the language as well as they could have. + +PySimpleGUI is designed with both the beginner and the experienceed developer in mind. Why? Because both tend to like compact code. Most like people, we just want to get sh\*t done, right? And, why not do it in a way that's like how most of Python works? The beginners can begin working with GUIs ***in their first week of Python education***. The professionals can jump right into the deep end of the pool to use the entire array of Elements and their capabilities to build stuff like a database application. diff --git a/readme_creator/2_readme.md b/readme_creator/2_readme.md index 5f950fcf..4ba29076 100644 --- a/readme_creator/2_readme.md +++ b/readme_creator/2_readme.md @@ -340,7 +340,7 @@ This is the FUN part of the programming of this GUI. In order to really get the This first section on custom windows is for your typical, blocking, non-persistent window. By this I mean, when you "show" the window, the function will not return until the user has clicked a button or closed the window with an X. Two other types of windows exist. -1. Persistent window - the `Window.Read()` method returns and the window continues to be visible. This is good for applications like a chat window or a timer or anything that stays active on the screen for a while. +1. Persistent window - the `Window.read()` method returns and the window continues to be visible. This is good for applications like a chat window or a timer or anything that stays active on the screen for a while. 2. Asynchronous window - the trickiest of the lot. Great care must be exercised. Examples are an MP3 player or status dashboard. Async windows are updated (refreshed) on a periodic basis. You can spot them easily as they will have a `timeout` parameter on the call to read. `event, values = window.Read(timeout=100)` It's both not enjoyable nor helpful to immediately jump into tweaking each and every little thing available to you. Make some simple windows. Use the Cookbook and the Demo Programs as a way to learn and as a "starting point". @@ -433,7 +433,9 @@ layout = [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ] -event, values = sg.Window('Get filename example', layout).Read() +window sg.Window('Get filename example', layout) +event, values = window.read() +window.close() sg.Popup(event, values[0]) ``` @@ -459,8 +461,8 @@ layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], window = sg.Window('SHA-1 & 256 Hash', layout) -event, values = window.Read() -window.Close() +event, values = window.read() +window.close() source_filename = values[0] # the first input element is values[0] ``` @@ -481,12 +483,12 @@ layout = [[sg.Text('Persistent window')], window = sg.Window('Window that stays open', layout) while True: - event, values = window.Read() + event, values = window.read() if event is None or event == 'Exit': break print(event, values) -window.Close() +window.close() ``` ## Pattern 2 B - Persistent window (multiple reads using an event loop + updates data in window) @@ -500,28 +502,26 @@ A final note... the parameter `do_not_clear` in the input call determines the ac This example introduces the concept of "keys". Keys are super important in PySimpleGUI as they enable you to identify and work with Elements using names you want to use. Keys can be ANYTHING, except `None`. To access an input element's data that is read in the example below, you will use `values['_IN_']` instead of `values[0]` like before. ```python -import sys -if sys.version_info[0] >= 3: - import PySimpleGUI as sg -else: - import PySimpleGUI27 as sg +import PySimpleGUI as sg -layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ], - [sg.Input(key='_IN_')], - [sg.Button('Show'), sg.Button('Exit')]] +layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_')], + [sg.Input(key='_IN_')], + [sg.Button('Show'), sg.Button('Exit')]] window = sg.Window('Window Title', layout) -while True: # Event Loop - event, values = window.Read() - print(event, values) - if event is None or event == 'Exit': - break - if event == 'Show': - # change the "output" element to be the value of "input" element - window.Element('_OUTPUT_').Update(values['_IN_']) +while True: # Event Loop + event, values = window.read() # can also be written as event, values = window() + print(event, values) + if event is None or event == 'Exit': + break + if event == 'Show': + # change the "output" element to be the value of "input" element + window['_OUTPUT_'].update(values['_IN_']) + # above line can also be written without the update specified + window['_OUTPUT_'](values['_IN_']) -window.Close() +window.close() ``` ### Qt Designer @@ -548,8 +548,8 @@ layout = [[sg.Text('Rename files or folders')], window = sg.Window('Rename Files or Folders', layout) -event, values = window.Read() - +event, values = window.read() +window.close() folder_path, file_path = values[0], values[1] # get the data from the values dictionary print(folder_path, file_path) ``` @@ -566,9 +566,9 @@ Now let's look at how those 2 rows and the other two row from Python code: ```python layout = [[sg.Text('Rename files or folders')], - [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], - [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], - [sg.Submit(), sg.Cancel()]] + [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], + [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], + [sg.Submit(), sg.Cancel()]] ``` See how the source code mirrors the layout? You simply make lists for each row, then submit that table to PySimpleGUI to show and get values from. @@ -580,7 +580,7 @@ For return values the window is scanned from top to bottom, left to right. Each In our example window, there are 2 fields, so the return values from this window will be a dictionary with 2 values in it. Remember, if you do not specify a `key` when creating an element, one will be created for you. They are ints starting with 0. In this example, we have 2 input elements. They will be addressable as values[0] and values[1] ```python -event, values = window.Read() +event, values = window.read() folder_path, file_path = values[0], values[1] ``` @@ -591,14 +591,14 @@ Isn't this what a Python programmer looking for a GUI wants? Something easy to w ## Return values -There are 2 return values from a call to `Window.Read()`, an `event` that caused the `Read` to return and `values` a list or dictionary of values. If there are no elements with keys in the layout, then it will be a list. However, some elements, like some buttons, have a key automatically added to them. **It's best to use keys on all of your input type elements.** +There are 2 return values from a call to `Window.read()`, an `event` that caused the `Read` to return and `values` a list or dictionary of values. If there are no elements with keys in the layout, then it will be a list. However, some elements, like some buttons, have a key automatically added to them. **It's best to use keys on all of your input type elements.** ### Two Return Values All Window Read calls return 2 values. By convention a read statement is written: ```python -event, values = window.Read() +event, values = window.read() ``` You don't HAVE to write your reads in this way. You can name your variables however you want. But if you want to code them in a way that other programmers using PySimpleGUI are used to, then use this statement. @@ -644,7 +644,7 @@ Putting it all together we end up with an "event loop" that looks something like ```python while True: - event, values = window.Read() + event, values = window.read() if event is None: break window.Close() @@ -653,7 +653,7 @@ window.Close() You will very often see the examples and demo programs write this check as: ```python - event, values = window.Read() + event, values = window.read() if event in (None, 'Exit'): break ``` @@ -685,7 +685,7 @@ If your window has an event loop where it is read over and over, remember to giv ```python while True: - event, values = window.Read() + event, values = window.read() if event is None or event == 'Quit': break ``` @@ -694,7 +694,7 @@ Actually, the more "Pythonic version" is used in most Demo Programs and examples ```python while True: - event, values = window.Read() + event, values = window.read() if event in (None, 'Quit'): break ``` @@ -711,7 +711,6 @@ Some elements are capable of generating events when something happens to them. | --- | --- | | InputText | any change | | Combo | item chosen | -| Option menu | item chosen | | Listbox | selection changed | | Radio | selection changed | | Checkbox | selection changed | @@ -720,6 +719,8 @@ Some elements are capable of generating events when something happens to them. | Text | clicked | | Status Bar | clicked | | Graph | clicked | +| Graph | dragged | +| Graph | drag ended (mouse up) | | TabGroup | tab clicked | | Slider | slider moved | | Table | row selected | @@ -727,6 +728,7 @@ Some elements are capable of generating events when something happens to them. | ButtonMenu | menu item chosen | | Right click menu | menu item chosen | + ### Other Events #### Menubar menu item chosen for MenuBar menus and ButtonMenu menus @@ -761,7 +763,7 @@ Or, more commonly, you can unpack the return results separately. This is the pr ```python event, values = sg.Window('My title', window_rows).Read() -event, value_list = window.Read() +event, value_list = window.read() value1 = value_list[0] value2 = value_list[1] ... @@ -800,7 +802,7 @@ layout = [ ] window = sg.Window('Simple data entry window', layout) -event, values = window.Read() +event, values = window.read() window.Close() sg.Popup(event, values, values['_NAME_'], values['_ADDRESS_'], values['_PHONE_']) @@ -881,7 +883,7 @@ layout = [ [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]] window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False) -event, values = window.Read() +event, values = window.read() sg.Popup('Title', 'The results of the window.', @@ -970,7 +972,7 @@ You've already seen a number of examples above that use blocking windows. You'l A blocking Read (one that waits until an event happens) look like this: ```python -event, values = window.Read() +event, values = window.read() ``` A non-blocking / Async Read call looks like this: @@ -985,6 +987,9 @@ You can learn more about these async / non-blocking windows toward the end of th The first step is to create the window object using the desired window customizations. +Note - There is no direct support for "**modal windows**" in PySimpleGUI. All windows are accessable at all times unless you manually change the windows' settings. + + **IMPORTANT** - Many of the `Window` methods require you to either call `Window.Read` or `Window.Finalize` (or set `finalize=True` in your `Window` call) before you call the method. This is because these 2 calls are what actually creates the window using the underlying GUI Framework. Prior to one of those calls, the methods are likely to crash as they will not yet have their underlying widgets created. @@ -992,6 +997,12 @@ The first step is to create the window object using the desired window customiza PySimpleGUI computes the exact center of your window and centers the window on the screen. If you want to locate your window elsewhere, such as the system default of (0,0), if you have 2 ways of doing this. The first is when the window is created. Use the `location` parameter to set where the window. The second way of doing this is to use the `SetOptions` call which will set the default window location for all windows in the future. +#### 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. + +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 You can get your window's size by access the `Size` property. The window has to be Read once or Finalized in order for the value to be correct. Note that it's a property, not a call. @@ -1057,6 +1068,17 @@ To keep a window on top of all other windows on the screen, set keep_on_top = Tr PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call. +## Closing Windows + +When you are completely done with a window, you should close it and then delete it so that the resources, in particular the tkinter resources, are properly cleaned up. + +If you wish to do this in 1 line of code, here's your line: + +```python +window.close(); del window +``` + +The delete helps with a problem multi-threaded application encounter where tkinter complains that it is being called from the wrong thread (not the program's main thread) ## Window Methods That Complete Formation of Window @@ -1080,7 +1102,7 @@ window.Layout(layout) window.Finalize() ``` -### Chaining The Calls +### Chaining The Calls (the old method) The next level of compression that was done was to chain the calls together into a single line of code. @@ -1173,7 +1195,7 @@ layout = [ ] window = sg.Window('To Do List Example', layout) -event, values = window.Read() +event, values = window.read() ``` The output from this script was this window: @@ -1197,7 +1219,7 @@ for i in range(1,6): layout += [[sg.Button('Save'), sg.Button('Exit')]] window = sg.Window('To Do List Example', layout) -event, values = window.Read() +event, values = window.read() ``` It produces the exact same window of course. That's progress.... went from writing out every row of the GUI to generating every row. If we want 48 items as suggested, change the range(1,6) to range(1,48). Each time through the list another row is added onto the layout. @@ -1357,7 +1379,7 @@ input_rows = [[sg.Input(size=(15,1), pad=(0,0)) for col in range(4)] for row in layout = header + input_rows window = sg.Window('Table Simulation', layout, font='Courier 12') -event, values = window.Read() +event, values = window.read() ``` @@ -1634,6 +1656,16 @@ Later when you want to make that Element visible you simply call the Element's ` This feature works best on Qt, but does work on the tkinter version as well. The visible parameter can also be used with the Column and Frame "container" Elements. +Note - Tkiner elements behave differently than Qt elements in how they arrange themselves when going from invisible to visible. + +Tkinet 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. + +If you want to not only make the element invisible, on tkinter you can call `Element. + +Qt elements tend to hold their place really well and the window resizes itself nicely. It is more precise and less klunky. + ## Shortcut Functions / Multiple Function Names @@ -1641,10 +1673,11 @@ Perhaps not the best idea, but one that's done none the less is the naming of me In other words, I am lazy and don't like to type. The result is multiple ways to do exactly the same thing. Typically, the Demo Programs and other examples use the full name, or at least a longer name. Thankfully PyCharm will show you the same documentation regardless which you use. -This enables you to code much quicker once you are used to using the SDK. The Text Element, for example, has 3 different names `Text`, `Txt` or`T`. InputText can also be written `Input` or `In` . The shortcuts aren't limited to Elements. The `Window` method `Window.FindElement` can be written as `Window.Element` because it's such a commonly used function. +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` . -It's an ongoing thing. If you don't stay up to date and one of the newer shortcuts is used, you'll need to simply rename that shortcut. +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. +It's an ongoing thing. If you don't stay up to date and one of the newer shortcuts is used, you'll need to simply rename that shortcut in the code. For examples Replace sg.T with sg.Text if your version doesn't have sg.T in it. @@ -1659,8 +1692,17 @@ layout = [ [sg.Text('This is what a Text Element looks like')], ] ``` + ![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. + +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". + + + + --- ## `Window.FindElement(key)` Shortcut `Window[key]` @@ -1679,16 +1721,23 @@ window[key].Update(new_value) ``` This change has been released to PyPI for PySimpleGUI -It **has not yet been released to PyPI** for the other ports of PySimpleGUI (Qt, Wx, Web). You'll find the change on GitHub however for Qt and Web (still working on Wx). MANY Thanks is owed to the person that suggested and showed me how to do this. It's an incredible find. -## `Element.Update()` Shortcut `Element()` +## `Element.Update()` -> `Element()` shortcut This has to be one of the strangest syntactical contructs I've ever written. -It is best used in combination with `FindElement` (see prior section on how to shortcut `FindElement`). When used with the `FindElement` shortcut, the code to update an element can be shortened to this unusual looking call: +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: + +```python +window[key].update(new_value) +``` + +The code can be further compressed by removing the `.update` characters, resulting in this very compact looking call: ```python window[key](new_value) @@ -1696,9 +1745,29 @@ window[key](new_value) Yes, that's a valid statement in Python. +What's happening is that the element itself is being called. You can also writing it like this: + +```python +elem = sg.Text('Some text', key='-TEXT-') +elem('new text value') +``` + +Side note - you can also call your `window` variable directly. If you "call" it it will actually call `Window.read`. + +```python +window = sg.Window(....) +event, values = window() + +# is the same as +window = sg.Window(....) +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. -Still debating whether to begin to immediately use this for all demos going forward and also if should go back and change the docs and demo programs, essentially removing the other technique for doing an update. +Because it's such a foreign construct that someone with 1 week of Python classes will not reconize, 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. @@ -2241,22 +2310,22 @@ import PySimpleGUI as sg # layout the window layout = [[sg.Text('A custom progress meter')], - [sg.ProgressBar(10000, orientation='h', size=(20, 20), key='progressbar')], + [sg.ProgressBar(1000, orientation='h', size=(20, 20), key='progressbar')], [sg.Cancel()]] # create the window` window = sg.Window('Custom Progress Meter', layout) -progress_bar = window.FindElement('progressbar') +progress_bar = window['progressbar'] # loop that would normally do something useful -for i in range(10000): +for i in range(1000): # check to see if the cancel button was clicked and exit loop if clicked - event, values = window.Read(timeout=0) + event, values = window.read(timeout=10) if event == 'Cancel' or event is None: break # update bar with loop value +1 so that bar eventually reaches the maximum - progress_bar.UpdateBar(i + 1) + progress_bar.UpdateBar(i + 1) # done with loop... need to destroy the window as it's still open -window.Close() +window.close() ``` ![progress custom](https://user-images.githubusercontent.com/13696193/45243969-c3508100-b2c3-11e8-82bc-927d0307e093.jpg) @@ -2291,7 +2360,6 @@ Here's a complete solution for a chat-window using an Output Element. To displa ```python import PySimpleGUI as sg -# Blocking window that doesn't close def ChatBot(): layout = [[(sg.Text('This is where standard out is being routed', size=[40, 1]))], [sg.Output(size=(80, 20))], @@ -2299,21 +2367,23 @@ def ChatBot(): sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])), sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]] - window = sg.Window('Chat Window', layout, default_element_size=(30, 2)) + window = sg.Window('Chat Window', layout, default_element_size=(30, 2)) # ---===--- Loop taking in user input and using it to query HowDoI web oracle --- # - while True: - event, value = window.Read() + while True: + event, value = window.read() if event == 'SEND': print(value) else: break - + window.close() ChatBot() ``` -## Column Element +## Column Element & Frame, Tab "Container" Elements + +Columns and Frames and Tabs are all "Container Elements" and behave similarly. This section focuses on Columns but can be applied elsewhere. Starting in version 2.9 you'll be able to do more complex layouts by using the Column Element. Think of a Column as a window within a window. And, yes, you can have a Column within a Column if you want. @@ -2355,16 +2425,18 @@ layout = [[sg.Slider(range=(1,100), default_value=10, orientation='v', size=(8,2 # Display the window and get values window = sg.Window('Compact 1-line window with column', layout) -event, values = window.Read() +event, values = window.read() window.Close() sg.Popup(event, values, line_width=200) ``` -### Column Justification +### Column, Frame, Tab, Window element_justification -Beginning in Release 4.3 you can justify the `Column` element's row by setting the `Column`'s `justification` parameter. +Beginning in Release 4.3 you can set the justification for any container element. This is done through the `element_justification` parameter. This will greatly help anyone that wants to center all of their content in a window. Previously it was difficult to do these kinds of layouts, if not impossible. + +justify the `Column` element's row by setting the `Column`'s `justification` parameter. You can also justify the entire contents within a `Column` by using the Column's `element_justification` parameter. @@ -2464,7 +2536,7 @@ The order of operations to obtain a tkinter Canvas Widget is: fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig) # show it all again and get buttons - event, values = window.Read() + event, values = window.read() ``` @@ -2475,7 +2547,7 @@ To get a tkinter Canvas Widget from PySimpleGUI, follow these steps: * Find the Canvas Element by looking up using key * Your Canvas Widget Object will be the found_element.TKCanvas * Draw on your canvas to your heart's content -* Call `window.Read()` - Nothing will appear on your canvas until you call Read +* Call `window.read()` - Nothing will appear on your canvas until you call Read See `Demo_Matplotlib.py` for a Recipe you can copy. @@ -2552,10 +2624,9 @@ graph+UP {'graph': (154, 254)} ## Table Element -Out of all of the Elements, it's the Table and the Tree that are the most "problematic" in the tkinter inter and Qt implementations. They have been difficult implementation. (yea.... get of over it) +Table and Tree Elements are of the most complex in PySimpleGUI. They have a lot of options and a lot of unusual characteristics. - -### `window.Read()` return values from Table Element +### `window.read()` return values from Table Element The values returned from a `Window.Read` call for the Table Element are a list of row numbers that are currently highlighted. @@ -2572,6 +2643,24 @@ There has been an elusive problem where clicking on or near the table's header c This problem has existed since the first release of the `Table` element. It was fixed in release 4.3. +### Known table colors in Python 3.7.3, 3.7.4, 3.8, ? + +The tkinter that's been released in the past several releases of Python has a bug. Table colors of all types are not working, at all. The background of the rows never change. If that's important to you, you'll need to **downgrade** your Python version. 3.6 works really well with PySimpleGUI and tkinter. + +### Empty Tables + +If you wish to start your table as being an empty one, you will need to specify an empty table. This list comprehension will create an empty table with 15 rows and 6 columns. + +```python +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. +`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. + ## Tree Element The Tree Element and Table Element are close cousins. Many of the parameters found in the Table Element apply to Tree Elements. In particular the heading information, column widths, etc. @@ -2629,6 +2718,8 @@ Just like windows and the other container elements, the `Tab` Element has a layo *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 visibily parameter but calling update will not change it. + Tabs are contained in TabGroups. They are **not** placed into other layouts. To get a Tab into your window, first place the `Tab` Element into a `TabGroup` Element and then place the `TabGroup` Element into the Window layout. Let's look at this Window as an example: @@ -2963,7 +3054,7 @@ layout = [[sg.Text('Persistent window')], window = sg.Window('Window that stays open', layout) while True: - event, values = window.Read() + event, values = window.read() if event is None or event == 'Exit': break print(event, values) @@ -3145,7 +3236,7 @@ layout = [ [sg.Text('My layout', key='_TEXT_')], window = sg.Window('My new window', layout) while True: # Event Loop - event, values = window.Read() + event, values = window.read() if event is None: break window.Element('_TEXT_').Update('My new text value') @@ -3166,7 +3257,7 @@ window = sg.Window('My new window', layout).Finalize() window.Element('_TEXT_').Update('My new text value') while True: # Event Loop - event, values = window.Read() + event, values = window.read() if event is None: break ``` @@ -3206,7 +3297,7 @@ sz = fontSize window = sg.Window("Font size selector", layout, grab_anywhere=False) # Event Loop while True: - event, values= window.Read() + event, values= window.read() if event is None: break sz_spin = int(values['spin']) @@ -3293,7 +3384,7 @@ window = sg.Window("Keyboard Test", layout, return_keyboard_events=True, use_de # ---===--- Loop taking in user input --- # while True: - event, value = window.Read() + event, value = window.read() if event == "OK" or event is None: print(event, "exiting") @@ -3331,22 +3422,28 @@ To add a menu to a Window place the `Menu` or `MenuBar` element into your layout It doesn't really matter where you place the Menu Element in your layout as it will always be located at the top of the window. +When the user selects an item, it's returns as the event (along with the menu item's key if one was specified in the menu definition) + ## ButtonMenus Button menus were introduced in version 3.21, having been previously released in PySimpleGUIQt. They work exactly the same and are source code compatible between PySimpleGUI and PySimpleGUIQt. These types of menus take a single menu entry where a Menu Bar takes a list of menu entries. +**Return values for ButtonMenus are different than Menu Bars.** + +You will get back the ButtonMenu's KEY as the event. To get the actual item selected, you will look it up in the values dictionary. This can be done with the expression `values[event]` + ## Right Click Menus Right Click Menus were introduced in version 3.21. Almost every element has a right_click_menu parameter and there is a window-level setting for rich click menu that will attach a right click menu to all elements in the window. -The menu definition is the same a s the button menu definition, a single menu entry. +The menu definition is the same as the button menu definition, a single menu entry. ```python right_click_menu = ['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']] ``` The first string in a right click menu and a button menu is ***ignored***. It is not used. Normally you would put the string that is shown on the menu bar in that location. -**Return values for right click menus are different than menu bars and button menus.** Instead of the value being returned through the values dictionary, it is instead sent back as an Event. You will not +**Return values for right click menus are the same as MenuBars.** The value chosen is returned as the event. ## Menu Shortcut keys You have used ALT-key in other Windows programs to navigate menus. For example Alt-F+X exits the program. The Alt-F pulls down the File menu. The X selects the entry marked Exit. @@ -3387,6 +3484,22 @@ To add the `key` `_MY_KEY_` to the Special menu entry, the code would be: If you want to change the characters that indicate a key follows from '::' to something else, change the variable `MENU_KEY_SEPARATOR` +## The Menu Definitions + +Having read through the Menu section, you may have noticed that the right click menu and the button menu have a format that is a little odd as there is a part of it that is not utilized (the first very string). Perhaps the words "Not Used" should be in the examples.... But, there's a reason to retain words there that make sense. + +The reason for this is an architectural one, but it also has a convienence for the user. You can put the individual menu items (button and right click) into a list and you'll have a menu bar definition. + +This would work to make a menu bar from a series of these individual menu defintions: + +```python +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. + + + # Running Multiple Windows This is where PySimpleGUI continues to be simple, but the problem space just went into the realm of "Complex". @@ -3536,7 +3649,7 @@ If your program is running with blocking `Read` calls, then you will want to add Your event loop will be modified from this blocking: ```python while True: - event, values = window.Read() + event, values = window.read() ``` To this non-blocking: @@ -3863,6 +3976,58 @@ Either way you'll access it using the same `Window` variable `sg.Window.TKroot` Watch this space in the future for the more standardized variable name for this object. It may be something like `Window.Widget` as the Elements use or something like `Window.GUIWindow`. +## Binding tkiner "events" + +If you wish to receive events directly from tkinter, but do it in a PySimpleGUI way, then there's a particular way at the moment to make this happen. + +tkinter performs a callback into user code when an event happens, but that's not how PySimpleGUI works. Instead of callbacks, a PySimpleGUI user's program simply returns an event via the `window.read()` call. In order for your "event" to generate an event that will be returned to you via your read call, follow these instructions: + +1. Create a Button for each event you wish to receive +2. Set visible=False when creating the buttons +3. Make the Button text be the event you want to see returned to you or set the button's Key to that value +4. After creating / finalizing the window, make the tkinter bind call, passing `element.ButtonReboundCallback` as the function to call. + +This sample code binds not an element events but events from the window itself. In this case, Focus events. + +```python +import PySimpleGUI as sg + +layout = [ [sg.Text('My Window')], + [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], + [sg.Button('Do Something'), sg.Button('Exit'), + sg.Button('-FOCUS-IN-', visible=False), sg.Button('-FOCUS-OUT-', visible=False)] ] + +window = sg.Window('Window Title', layout, finalize=True) + +window.TKroot.bind("", window['-FOCUS-IN-'].ButtonReboundCallback) +window.TKroot.bind("", window['-FOCUS-OUT-'].ButtonReboundCallback) +``` + +This code binds the right mouse button to a button so that you can right click a button and get a different event than if you left clicked it. + +```python +import PySimpleGUI as sg + +layout = [ [sg.Text('My Window')], + [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], + [sg.Button('Do Something'), sg.Button('Right Click Me')], + [sg.Button('-RIGHT-', visible=False)] + ] + +window = sg.Window('Window Title', layout, finalize=True) + +window['Right Click Me'].Widget.bind("", window['-RIGHT-'].ButtonReboundCallback) + +has_focus = True +while True: # Event Loop + event, values = window.read() + print(event, values) + if event in (None, 'Exit'): + break +window.close() +``` + + --- @@ -3876,7 +4041,11 @@ Hoping this is a change for the better and that users will be able to find the i NOTE that this documentatiuopn section is created using the ***GitHUB released PySimpleGUI.py file***. Some of the calls may not be available to you or your port (Qt, Wx, Web). And some of the parameters may be different. We're working on adding docstrings to all the ports which will enable this kind of document to be available for each port. -Without further delay... here are all of the Elements +## Caution - Some functions / methods may be internal only yet exposed in this documenation + +This section of the documentation is generated directly from the source code. As a result, sometimes internal only functions or methods that you are not supposed to be calling are accidently shown in this documentation. Hopefully these accidents don't happen often. + +Without further delay... here are all of the Elements and the Window class @@ -3884,9 +4053,24 @@ Without further delay... here are all of the Elements ### Button Element - +#### ButtonCallBack + + + +#### ButtonPressCallBack + + + +#### ButtonReboundCallback + + + +#### ButtonReleaseCallBack + + + #### Click @@ -3907,11 +4091,31 @@ Without further delay... here are all of the Elements +#### click + + + +#### expand + + + +#### update + + + ### ButtonMenu Element +#### ButtonReboundCallback + + + +#### Click + + + #### SetFocus @@ -3924,11 +4128,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Canvas Element +#### ButtonReboundCallback + + + #### SetFocus @@ -3941,11 +4157,19 @@ Without further delay... here are all of the Elements +#### expand + + + ### Checkbox Element +#### ButtonReboundCallback + + + #### Get @@ -3962,6 +4186,18 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + ### Column Element @@ -3971,6 +4207,10 @@ Without further delay... here are all of the Elements +#### ButtonReboundCallback + + + #### Layout @@ -3987,11 +4227,27 @@ Without further delay... here are all of the Elements +#### expand + + + +#### layout + + + +#### update + + + ### Combo Element +#### ButtonReboundCallback + + + #### Get @@ -4008,6 +4264,55 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + + +### ErrorElement Element + + + + +#### ButtonReboundCallback + + + +#### Get + + + +#### SetFocus + + + +#### SetTooltip + + + +#### Update + + + +#### expand + + + +#### get + + + +#### update + + ### Frame Element @@ -4018,6 +4323,10 @@ Without further delay... here are all of the Elements +#### ButtonReboundCallback + + + #### Layout @@ -4034,6 +4343,18 @@ Without further delay... here are all of the Elements +#### expand + + + +#### layout + + + +#### update + + + ### Graph Element @@ -4047,6 +4368,10 @@ Without further delay... here are all of the Elements +#### ButtonReboundCallback + + + #### ButtonReleaseCallBack @@ -4127,11 +4452,31 @@ Without further delay... here are all of the Elements +#### erase + + + +#### expand + + + +#### move + + + +#### update + + + ### Image Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4148,11 +4493,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### InputText Element +#### ButtonReboundCallback + + + #### Get @@ -4169,11 +4526,31 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + ### Listbox Element +#### ButtonReboundCallback + + + +#### GetIndexes + + + #### GetListValues @@ -4194,11 +4571,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Menu Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4211,11 +4600,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Multiline Element +#### ButtonReboundCallback + + + #### Get @@ -4232,11 +4633,27 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + ### OptionMenu Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4249,11 +4666,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Output Element +#### ButtonReboundCallback + + + #### Get @@ -4266,19 +4695,28 @@ Without further delay... here are all of the Elements -#### TKOut - - #### Update +#### expand + + + +#### update + + + ### Pane Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4291,11 +4729,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### ProgressBar Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4312,11 +4762,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Radio Element +#### ButtonReboundCallback + + + #### Get @@ -4337,11 +4799,27 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + ### Slider Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4354,11 +4832,23 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Spin Element +#### ButtonReboundCallback + + + #### Get @@ -4375,11 +4865,27 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + ### StatusBar Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4392,6 +4898,14 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + ### Tab Element @@ -4401,6 +4915,10 @@ Without further delay... here are all of the Elements +#### ButtonReboundCallback + + + #### Layout @@ -4421,6 +4939,22 @@ Without further delay... here are all of the Elements +#### expand + + + +#### layout + + + +#### select + + + +#### update + + + ### TabGroup Element @@ -4430,6 +4964,10 @@ Without further delay... here are all of the Elements +#### ButtonReboundCallback + + + #### FindKeyFromTabName @@ -4450,11 +4988,31 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### layout + + + ### Table Element +#### ButtonReboundCallback + + + +#### Get + + + #### SetFocus @@ -4467,11 +5025,27 @@ Without further delay... here are all of the Elements +#### expand + + + +#### get + + + +#### update + + + ### Text Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4484,11 +5058,24 @@ Without further delay... here are all of the Elements +#### expand + + + +#### update + + + + ### Tree Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4501,7 +5088,15 @@ Without further delay... here are all of the Elements -### TreeData Class For Tree Element +#### expand + + + +#### update + + + +### TreeData Element @@ -4510,15 +5105,16 @@ Without further delay... here are all of the Elements -#### Node - - ### VerticalSeparator Element +#### ButtonReboundCallback + + + #### SetFocus @@ -4527,6 +5123,10 @@ Without further delay... here are all of the Elements +#### expand + + + ### Window @@ -4552,14 +5152,11 @@ Without further delay... here are all of the Elements + #### CurrentLocation -#### DecrementOpenCount - - - #### Disable @@ -4608,6 +5205,7 @@ Without further delay... here are all of the Elements + #### GetScreenDimensions @@ -4624,22 +5222,11 @@ Without further delay... here are all of the Elements -#### IncrementOpenCount - - #### Layout -#### LayoutAndRead - - - -#### LayoutAndShow - - - #### LoadFromDisk @@ -4660,6 +5247,7 @@ Without further delay... here are all of the Elements + #### Read @@ -4690,6 +5278,8 @@ Without further delay... here are all of the Elements #### Size +Note the `Window.Size` can be used for both reading and writing + #### UnHide @@ -4700,6 +5290,81 @@ Without further delay... here are all of the Elements +#### close + + + +#### disable + + + +#### disappear + + + +#### elem + + + +#### element + + + +#### enable + + + +#### fill + + + +#### finalize + + + +#### find + + + +#### hide + + + +#### layout + + + +#### maximize + + + +#### minimize + + + +#### move + + + +#### normal + + + +#### read + + + +#### reappear + + + +#### refresh + + + +#### size + + @@ -4747,8 +5412,44 @@ Without further delay... here are all of the Elements + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/readme_creator/4_Release_notes.md b/readme_creator/4_Release_notes.md index cb5b5469..59df551e 100644 --- a/readme_creator/4_Release_notes.md +++ b/readme_creator/4_Release_notes.md @@ -714,11 +714,11 @@ However, your code will look weird and ancient. ;-) (i.e. readable) MORE Docstring and main doc updates! * Finally 2.7 gets an upgrade and with it doc strings. It however doesn't get a full-version bump like main PySimpleGUI as this may be its last release. -* New window[key] == window.FindElement(key) +* New `window[key] == window.FindElement(key)` * New Update calling method. Can directly call an Element and it will call its Update method - * window[key](value=new_value) == window.FindElement(key).Update(value=new_value) + * `window[key](value=new_value) == window.FindElement(key).Update(value=new_value)` * Made Tearoff part of element so anything can be a menu in theory -* Removed a bunch of __del__ calls. Hoping it doesn't bite me in memory leaks +* Removed a bunch of `__del__` calls. Hoping it doesn't bite me in memory leaks * Combo.Get method added * Combo.GetSelectedItemsIndexes removed * New Graph methods SendFigureToBack, BringFigureToFront @@ -802,7 +802,37 @@ Let's hope it doesn't all blow up in our faces! * Frame - Trying to set the size but doesn't seem to be setting it correctly * Tabs will now expand & fill now (I hope this is OK!!!) +## 4.5 PySimpleGUI Release 04-Nov-2019 +* Metadata! + * All elements have a NEW metadata parameter that you can set to anything and access with Element.metadata + * Windows can have metadata too +* Window.finalize() - changed internally to do a fully window.read with timeout=1 so that it will complete all initializations correctly +* Removed typing import +* ButtonReboundCallback - Used with tkinter's Widget.bind method. Use this as a "target" for your bind and you'll get the event back via window.read() +* NEW Element methods that will work on a variety of elements: + * set_size - sets width, height. Can set one or both + * get_size - returns width, heigh of Element (underlying Widget), usually in PIXELS + * hide_row - hides the entire row that an element occupies + * unhide_row - makes visible the entire row that an element occupies + * expand - causes element to expand to fill available space in X or Y or both directions +* InputText Element - Update got new parameters: text_color=None, background_color=None, move_cursor_to='end' +* RadioButton - fix in Update. Was causing problems with loading a window from disk +* Text Element - new border width parameter that is used when there's a relief set for the text element +* Output Element - special expand method like the one for all other elements +* Frame element - Can change the text for the frame using Update method +* Slider element - can change range. Previously had to change value to change the range +* Scrollable frame / column - change to how mousewheel scrolls. Was causing all things to scroll when scrolling a single column + * NOTE - may have a bad side effect for scrolling tables with a mouse wheel +* Fix for icon setting when creating window. Wasn't defaulting to correct icon +* Window.get_screen_size() returns the screen width and height. Does not have to be a window that's created already as this is a class method +* Window.GetScreenDimensions - will return size even if the window has been destroyed by using get_screen_size +* Now deleting window read timers every time done with them +* Combo no longer defaults to first entry +* New Material1 and Material2 look and feel color schemes +* change_look_and_feel has new "force" parameter. Set to True to force colors when using a Mac +* Fix in popup_get_files when 0 length of filename +* Fix in Window.SetIcon - properly sets icon using file with Linux now. Was always defaulting ### Upcoming Make suggestions people! Future release features @@ -831,7 +861,7 @@ While not the best programming practice, the implementation resulted in a single In Python, functions behave just like object. When you're placing a Text Element into your form, you may be sometimes calling a function and other times declaring an object. If you use the word Text, then you're getting an object. If you're using `Txt`, then you're calling a function that returns a `Text` object. **Lists** -It seemed quite natural to use Python's powerful list constructs when possible. The form is specified as a series of lists. Each "row" of the GUI is represented as a list of Elements. When the form read returns the results to the user, all of the results are presented as a single list. This makes reading a form's values super-simple to do in a single line of Python code. +It seemed quite natural to use Python's powerful list constructs when possible. The form is specified as a series of lists. Each "row" of the GUI is represented as a list of Elements. **Dictionaries** Want to view your form's results as a dictionary instead of a list... no problem, just use the `key` keyword on your elements. For complex forms with a lot of values that need to be changed frequently, this is by far the best way of consuming the results. diff --git a/readme_creator/PySimpleGUIlib.py b/readme_creator/PySimpleGUIlib.py index 65c513bb..a4bf3779 100644 --- a/readme_creator/PySimpleGUIlib.py +++ b/readme_creator/PySimpleGUIlib.py @@ -1,5 +1,6 @@ #!/usr/bin/python3 -version = __version__ = "4.4.1 Released" + +version = __version__ = "4.5.0.0.1 The ALMOST Released but still un-released version 04-Nov-2019" # 888888ba .d88888b oo dP .88888. dP dP dP @@ -120,7 +121,7 @@ import pickle import calendar import textwrap import inspect -from typing import List, Any, Union, Tuple, Dict # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments +# from typing import List, Any, Union, Tuple, Dict # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments from random import randint import warnings @@ -217,7 +218,7 @@ if sys.platform == 'darwin': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = COLOR_SYSTEM_DEFAULT # Colors should never be this long else: DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default - OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") DEFAULT_BACKGROUND_COLOR = None @@ -501,7 +502,7 @@ class Element(): The base class for all Elements. Holds the basic description of an Element like size and colors """ - def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True): + def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None): """ Element base class. Only used internally. User will not create an Element object by itself @@ -515,6 +516,7 @@ class Element(): :param pad: (int, int) or ((int,int),(int,int)) Amount of padding to put around element in pixels (left/right, top/bottom) :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element (Default = True) + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Size = size self.Type = type @@ -542,6 +544,7 @@ class Element(): self.Widget = None # Set when creating window. Has the main tkinter widget for element self.Tearoff = False self.ParentRowFrame = None # type tk.Frame + self.metadata = metadata # type: Any def _RightClickMenuCallback(self, event): """ @@ -729,6 +732,21 @@ class Element(): if self.ParentForm.CurrentlyRunningMainloop: self.ParentForm.TKroot.quit() + def ButtonReboundCallback(self, event): + """ + Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal + callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button + callback function that is normally called. + + :param event: (unknown) Not used in this function. + """ + # print(f'Button callback event = {obj_to_string_single_obj(event)}') + try: + self.ButtonCallBack() + except: + print('** ButtonReboundCallback - warning your element does not have a ButtonCallBack method **') + + def SetTooltip(self, tooltip_text): """ Called by application to change the tooltip text for an Element. Normally invoked using the Element Object such as: window.Element('key').SetToolTip('New tip'). @@ -753,6 +771,73 @@ class Element(): print('Was unable to set focus. The Widget passed in was perhaps not present in this element? Check your elements .Widget property') + def set_size(self, size=(None, None)): + """ + Changes the size of an element to a specific size. + It's possible to specify None for one of sizes so that only 1 of the element's dimensions are changed. + + :param size: Tuple[int, int] The size in characters, rows typically. In some cases they are pixels + """ + try: + if size[0] != None: + self.Widget.config(width=size[0]) + except: + print('Warning, error setting width on element with key=', self.Key) + try: + if size[1] != None: + self.Widget.config(height=size[1]) + except: + print('Warning, error setting height on element with key=', self.Key) + + + def get_size(self): + """ + Return the size of an element in Pixels. Care must be taken as some elements use characters to specify their size but will return pixels when calling this get_size method. + :return: Tuple[int, int] - Width, Height of the element + """ + try: + w = self.Widget.winfo_width() + h = self.Widget.winfo_height() + except: + print('Warning, error getting size of element', self.Key) + w = h = None + return w,h + + + def hide_row(self): + try: + self.ParentRowFrame.pack_forget() + except: + print('Warning, error hiding element row for key =', self.Key) + + + def unhide_row(self): + try: + self.ParentRowFrame.pack() + except: + print('Warning, error hiding element row for key =', self.Key) + + def expand(self, expand_x=False, expand_y=False): + """ + Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + + :param expand_x: (Bool) If True Element will expand in the Horizontal directions + :param expand_y: (Bool) If True Element will expand in the Vertical directions + """ + + if expand_x and expand_y: + fill = tk.BOTH + elif expand_x: + fill = tk.X + elif expand_y: + fill = tk.Y + else: + return + + self.Widget.pack(expand=True, fill=fill) + self.ParentRowFrame.pack(expand=True, fill=fill) + + def __call__(self, *args, **kwargs): """ Makes it possible to "call" an already existing element. When you do make the "call", it actually calls @@ -779,7 +864,7 @@ class InputText(Element): def __init__(self, default_text='', size=(None, None), disabled=False, password_char='', justification=None, background_color=None, text_color=None, font=None, tooltip=None, change_submits=False, enable_events=False, do_not_clear=True, key=None, focus=False, pad=None, - right_click_menu=None, visible=True): + right_click_menu=None, visible=True, metadata=None): """ :param default_text: (str) Text initially shown in the input box as a default value(Default value = '') @@ -799,6 +884,7 @@ class InputText(Element): :param pad: (int, int) or ((int, int), (int, int)) Tuple(s). Amount of padding to put around element. Normally (horizontal pixels, vertical pixels) but can be split apart further into ((horizontal left, horizontal right), (vertical above, vertical below)) :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element (Default = True) + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.DefaultText = default_text self.PasswordCharacter = password_char @@ -812,9 +898,9 @@ class InputText(Element): self.RightClickMenu = right_click_menu self.TKEntry = self.Widget = None # type: tk.Entry super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad, - font=font, tooltip=tooltip, visible=visible) + font=font, tooltip=tooltip, visible=visible, metadata=metadata) - def Update(self, value=None, disabled=None, select=None, visible=None): + def Update(self, value=None, disabled=None, select=None, visible=None,text_color=None, background_color=None, move_cursor_to='end'): """ Changes some of the settings for the Input Element. Must call `Window.Read` or `Window.Finalize` prior @@ -822,6 +908,9 @@ class InputText(Element): :param disabled: (bool) disable or enable state of the element (sets Entry Widget to readonly or normal) :param select: (bool) if True, then the text will be selected :param visible: (bool) change visibility of element + :param text_color: (str) change color of text being typed + :param background_color: (str) change color of the background + :param move_cursor_to: Union[int, str] Moves the cursor to a particular offset. Defaults to 'end' """ if self.Widget is None: warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning) @@ -830,13 +919,20 @@ class InputText(Element): self.TKEntry['state'] = 'readonly' elif disabled is False: self.TKEntry['state'] = 'normal' + if background_color is not None: + self.TKEntry.configure(background=background_color) + if text_color is not None: + self.TKEntry.configure(fg=text_color) if value is not None: try: self.TKStringVar.set(value) except: pass self.DefaultText = value - self.TKEntry.icursor(tk.END) + if move_cursor_to == 'end': + self.TKEntry.icursor(tk.END) + elif move_cursor_to is not None: + self.TKEntry.icursor(move_cursor_to) if select: self.TKEntry.select_range(0, 'end') if visible is False: @@ -878,7 +974,7 @@ class Combo(Element): """ def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, - tooltip=None, readonly=False, font=None, visible=True): + tooltip=None, readonly=False, font=None, visible=True, metadata=None): """ :param values: List[Any] values to choose. While displayed as text, the items returned are what the caller supplied, not text :param default_value: (Any) Choice to be displayed as initial value. Must match one of values variable contents @@ -895,6 +991,7 @@ class Combo(Element): :param readonly: (bool) make element readonly (user can't change). True means user cannot change :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Values = values self.DefaultValue = default_value @@ -906,7 +1003,7 @@ class Combo(Element): fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR super().__init__(ELEM_TYPE_INPUT_COMBO, size=size, auto_size_text=auto_size_text, background_color=bg, - text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible) + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata) def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None, visible=None): """ @@ -999,7 +1096,7 @@ class OptionMenu(Element): it looks like a Combo Box that you scroll to select a choice. """ def __init__(self, values, default_value=None, size=(None, None), disabled=False, auto_size_text=None, - background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True): + background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None): """ :param values: List[Any] Values to be displayed :param default_value: (Any) the value to choose by default @@ -1012,6 +1109,7 @@ class OptionMenu(Element): :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param tooltip: (str) text that will appear when mouse hovers over this element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Values = values self.DefaultValue = default_value @@ -1021,7 +1119,7 @@ class OptionMenu(Element): fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR super().__init__(ELEM_TYPE_INPUT_OPTION_MENU, size=size, auto_size_text=auto_size_text, background_color=bg, - text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible) + text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) def Update(self, value=None, values=None, disabled=None, visible=None): """ @@ -1082,7 +1180,7 @@ class Listbox(Element): def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, no_scrollbar=False, background_color=None, text_color=None, key=None, pad=None, tooltip=None, right_click_menu=None, - visible=True): + visible=True, metadata=None): """ :param values: List[Any] list of values to display. Can be any type including mixed types as long as they have __str__ method :param default_values: List[Any] which values should be initially selected @@ -1105,6 +1203,7 @@ class Listbox(Element): :param tooltip: (str) text, that will appear when mouse hovers over the element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Values = values self.DefaultValues = default_values @@ -1129,7 +1228,7 @@ class Listbox(Element): self.TKListbox = self.Widget = None # type: tk.Listbox self.NoScrollbar = no_scrollbar super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=size, auto_size_text=auto_size_text, font=font, - background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible) + background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) def Update(self, values=None, disabled=None, set_to_index=None, scroll_to_index=None, visible=None): @@ -1239,7 +1338,7 @@ class Radio(Element): """ def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None, background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None, - change_submits=False, enable_events=False, visible=True): + change_submits=False, enable_events=False, visible=True, metadata=None): """ :param text: (str) Text to display next to button @@ -1257,6 +1356,7 @@ class Radio(Element): :param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead :param enable_events: (bool) Turns on the element specific events. Radio Button events happen when an item is selected :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.InitialState = default @@ -1270,7 +1370,7 @@ class Radio(Element): self.EncodedRadioValue = None super().__init__(ELEM_TYPE_INPUT_RADIO, size=size, auto_size_text=auto_size_text, font=font, background_color=background_color, text_color=self.TextColor, key=key, pad=pad, - tooltip=tooltip, visible=visible) + tooltip=tooltip, visible=visible, metadata=metadata) def Update(self, value=None, disabled=None, visible=None): """ @@ -1286,7 +1386,8 @@ class Radio(Element): return if value is not None: try: - self.TKIntVar.set(self.EncodedRadioValue) + if value: + self.TKIntVar.set(self.EncodedRadioValue) except: pass self.InitialState = value @@ -1334,7 +1435,7 @@ class Checkbox(Element): """ def __init__(self, text, default=False, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, - tooltip=None, visible=True): + tooltip=None, visible=True, metadata=None): """ :param text: (str) Text to display next to checkbox :param default: (bool). Set to True if you want this checkbox initially checked @@ -1350,6 +1451,7 @@ class Checkbox(Element): :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Text = text @@ -1362,7 +1464,7 @@ class Checkbox(Element): super().__init__(ELEM_TYPE_INPUT_CHECKBOX, size=size, auto_size_text=auto_size_text, font=font, background_color=background_color, text_color=self.TextColor, key=key, pad=pad, - tooltip=tooltip, visible=visible) + tooltip=tooltip, visible=visible, metadata=metadata) def Get(self): # type: (Checkbox) -> bool @@ -1424,7 +1526,7 @@ class Spin(Element): def __init__(self, values, initial_value=None, disabled=False, change_submits=False, enable_events=False, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, - pad=None, tooltip=None, visible=True): + pad=None, tooltip=None, visible=True, metadata=None): """ :param values: List[Any] List of valid values @@ -1441,6 +1543,7 @@ class Spin(Element): :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Values = values @@ -1452,7 +1555,7 @@ class Spin(Element): fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR super().__init__(ELEM_TYPE_INPUT_SPIN, size, auto_size_text, font=font, background_color=bg, text_color=fg, - key=key, pad=pad, tooltip=tooltip, visible=visible) + key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) return def Update(self, value=None, values=None, disabled=None, visible=None): @@ -1533,7 +1636,7 @@ class Multiline(Element): def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, border_width=None, size=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, do_not_clear=True, key=None, focus=False, font=None, pad=None, tooltip=None, - right_click_menu=None, visible=True): + right_click_menu=None, visible=True, metadata=None): """ :param default_text: (str) Initial text to show @@ -1555,6 +1658,7 @@ class Multiline(Element): :param tooltip: (str) text, that will appear when mouse hovers over the element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.DefaultText = default_text @@ -1570,7 +1674,7 @@ class Multiline(Element): self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH self.TKText = self.Widget = None # type: tkst.ScrolledText super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=size, auto_size_text=auto_size_text, background_color=bg, - text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible) + text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata) return def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None, @@ -1649,9 +1753,8 @@ class Text(Element): """ Text - Display some text in the window. Usually this means a single line of text. However, the text can also be multiple lines. If multi-lined there are no scroll bars. """ - def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=False, enable_events=False, - relief=None, font=None, text_color=None, background_color=None, justification=None, pad=None, key=None, - right_click_menu=None, tooltip=None, visible=True): + def __init__(self, text='', size=(None, None), auto_size_text=None, click_submits=False, enable_events=False, + relief=None, font=None, text_color=None, background_color=None, border_width=None, justification=None, pad=None, key=None, right_click_menu=None, tooltip=None, visible=True, metadata=None): """ :param text: (str) The text to display. Can include /n to achieve multiple lines :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high @@ -1662,12 +1765,14 @@ class Text(Element): :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc :param text_color: (str) color of the text :param background_color: (str) color of background + :param border_width: (int) number of pixels for the border (if using a relief) :param justification: (str) how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center` :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.DisplayText = str(text) @@ -1681,9 +1786,10 @@ class Text(Element): bg = background_color self.RightClickMenu = right_click_menu self.TKRightClickMenu = None + self.BorderWidth = border_width super().__init__(ELEM_TYPE_TEXT, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, - text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible) + text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): @@ -1736,7 +1842,7 @@ class StatusBar(Element): """ def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, enable_events=False, relief=RELIEF_SUNKEN, font=None, text_color=None, background_color=None, justification=None, pad=None, - key=None, tooltip=None, visible=True): + key=None, tooltip=None, visible=True, metadata=None): """ :param text: (str) Text that is to be displayed in the widget @@ -1753,6 +1859,7 @@ class StatusBar(Element): :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.DisplayText = text @@ -1767,7 +1874,7 @@ class StatusBar(Element): self.TKText = self.Widget = None # type: tk.Label super().__init__(ELEM_TYPE_STATUSBAR, size=size, auto_size_text=auto_size_text, background_color=bg, font=font or DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, - visible=visible) + visible=visible, metadata=metadata) return @@ -1970,7 +2077,7 @@ class Output(Element): Output Element - a multi-lined text area where stdout and stderr are re-routed to. """ def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None, - key=None, right_click_menu=None, visible=True): + key=None, right_click_menu=None, visible=True, metadata=None): """ :param size: Tuple[int, int] (w,h) w=characters-wide, h=rows-high :param background_color: (str) color of background @@ -1981,6 +2088,7 @@ class Output(Element): :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self._TKOut = self.Widget = None # type: TKOutput @@ -1989,7 +2097,7 @@ class Output(Element): self.RightClickMenu = right_click_menu super().__init__(ELEM_TYPE_OUTPUT, size=size, background_color=bg, text_color=fg, pad=pad, font=font, - tooltip=tooltip, key=key, visible=visible) + tooltip=tooltip, key=key, visible=visible, metadata=metadata) @property def TKOut(self): @@ -2025,6 +2133,29 @@ class Output(Element): return self._TKOut.output.get(1.0, tk.END) + def expand(self, expand_x=False, expand_y=False): + """ + Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + + :param expand_x: (Bool) If True Element will expand in the Horizontal directions + :param expand_y: (Bool) If True Element will expand in the Vertical directions + """ + + if expand_x and expand_y: + fill = tk.BOTH + elif expand_x: + fill = tk.X + elif expand_y: + fill = tk.Y + else: + return + + self._TKOut.output.pack(expand=True, fill=fill) + self._TKOut.frame.pack(expand=True, fill=fill) + self.ParentRowFrame.pack(expand=True, fill=fill) + + + set_focus = Element.SetFocus set_tooltip = Element.SetTooltip tk_out = TKOut @@ -2042,7 +2173,7 @@ class Button(Element): file_types=(("ALL Files", "*.*"),), initial_folder=None, disabled=False, change_submits=False, enable_events=False, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, - font=None, bind_return_key=False, focus=False, pad=None, key=None, visible=True): + font=None, bind_return_key=False, focus=False, pad=None, key=None, visible=True, metadata=None): """ :param button_text: (str) Text to be displayed on the button :param button_type: (int) You should NOT be setting this directly. ONLY the shortcut functions set this @@ -2067,6 +2198,7 @@ class Button(Element): :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.AutoSizeButton = auto_size_button @@ -2094,7 +2226,7 @@ class Button(Element): self.InitialFolder = initial_folder self.Disabled = disabled self.ChangeSubmits = change_submits or enable_events - super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, visible=visible) + super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return # Realtime button release callback @@ -2368,7 +2500,7 @@ class ButtonMenu(Element): def __init__(self, button_text, menu_def, tooltip=None, disabled=False, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, font=None, pad=None, key=None, - tearoff=False, visible=True): + tearoff=False, visible=True, metadata=None): """ :param button_text: (str) Text to be displayed on the button :param menu_def: List[List[str]] A list of lists of Menu items to show when this element is clicked. See docs for format as they are the same for all menu types @@ -2387,6 +2519,7 @@ class ButtonMenu(Element): :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element :param tearoff: (bool) Determines if menus should allow them to be torn off :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.MenuDefinition = menu_def @@ -2409,7 +2542,7 @@ class ButtonMenu(Element): # self.temp_size = size if size != (NONE, NONE) else super().__init__(ELEM_TYPE_BUTTONMENU, size=size, font=font, pad=pad, key=key, tooltip=tooltip, - text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible) + text_color=self.TextColor, background_color=self.BackgroundColor, visible=visible, metadata=metadata) return def _MenuItemChosenCallback(self, item_chosen): # ButtonMenu Menu Item Chosen Callback @@ -2473,7 +2606,7 @@ class ProgressBar(Element): Progress Bar Element - Displays a colored bar that is shaded as progress of some operation is made """ def __init__(self, max_value, orientation=None, size=(None, None), auto_size_text=None, bar_color=(None, None), - style=None, border_width=None, relief=None, key=None, pad=None, visible=True): + style=None, border_width=None, relief=None, key=None, pad=None, visible=True, metadata=None): """ :param max_value: (int) max value of progressbar :param orientation: (str) 'horizontal' or 'vertical' @@ -2486,6 +2619,7 @@ class ProgressBar(Element): :param key: (Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.MaxValue = max_value @@ -2499,7 +2633,7 @@ class ProgressBar(Element): self.Relief = relief if relief else DEFAULT_PROGRESS_BAR_RELIEF self.BarExpired = False super().__init__(ELEM_TYPE_PROGRESS_BAR, size=size, auto_size_text=auto_size_text, key=key, pad=pad, - visible=visible) + visible=visible, metadata=metadata) # returns False if update failed def UpdateBar(self, current_count, max=None): @@ -2555,7 +2689,7 @@ class Image(Element): """ def __init__(self, filename=None, data=None, background_color=None, size=(None, None), pad=None, key=None, - tooltip=None, right_click_menu=None, visible=True, enable_events=False): + tooltip=None, right_click_menu=None, visible=True, enable_events=False, metadata=None): """ :param filename: (str) image filename if there is a button image. GIFs and PNGs only. :param data: Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data @@ -2567,6 +2701,7 @@ class Image(Element): :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element :param enable_events: (bool) Turns on the element specific events. For an Image element, the event is "image clicked" + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Filename = filename @@ -2584,7 +2719,7 @@ class Image(Element): self.Source = filename if filename is not None else data super().__init__(ELEM_TYPE_IMAGE, size=size, background_color=background_color, pad=pad, key=key, - tooltip=tooltip, visible=visible) + tooltip=tooltip, visible=visible, metadata=metadata) return def Update(self, filename=None, data=None, size=(None, None), visible=None): @@ -2682,7 +2817,7 @@ class Canvas(Element): """ """ def __init__(self, canvas=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None, - right_click_menu=None, visible=True): + right_click_menu=None, visible=True, metadata=None): """ :param canvas: (tk.Canvas) Your own tk.Canvas if you already created it. Leave blank to create a Canvas @@ -2693,6 +2828,7 @@ class Canvas(Element): :param tooltip: (str) text, that will appear when mouse hovers over the element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR @@ -2700,7 +2836,7 @@ class Canvas(Element): self.RightClickMenu = right_click_menu super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=size, pad=pad, key=key, - tooltip=tooltip, visible=visible) + tooltip=tooltip, visible=visible, metadata=metadata) return @property @@ -2734,7 +2870,7 @@ class Graph(Element): def __init__(self, canvas_size, graph_bottom_left, graph_top_right, background_color=None, pad=None, change_submits=False, drag_submits=False, enable_events=False, key=None, tooltip=None, - right_click_menu=None, visible=True, float_values=False): + right_click_menu=None, visible=True, float_values=False, metadata=None): """ :param canvas_size: Tuple[int, int] (width, height) size of the canvas area in pixels :param graph_bottom_left: Tuple[int, int] (x,y) The bottoms left corner of your coordinate system @@ -2749,6 +2885,7 @@ class Graph(Element): :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element (Default = True) :param float_values: (bool) If True x,y coordinates are returned as floats, not ints + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.CanvasSize = canvas_size @@ -2765,7 +2902,7 @@ class Graph(Element): self.FloatValues = float_values super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key, - tooltip=tooltip, visible=visible) + tooltip=tooltip, visible=visible, metadata=metadata) return def _convert_xy_to_canvas_xy(self, x_in, y_in): @@ -3239,7 +3376,7 @@ class Frame(Element): def __init__(self, title, layout, title_color=None, background_color=None, title_location=None, relief=DEFAULT_FRAME_RELIEF, size=(None, None), font=None, pad=None, border_width=None, key=None, - tooltip=None, right_click_menu=None, visible=True, element_justification='left'): + tooltip=None, right_click_menu=None, visible=True, element_justification='left', metadata=None): """ :param title: (str) text that is displayed as the Frame's "label" or title :param layout: List[List[Elements]] The layout to put inside the Frame @@ -3257,6 +3394,7 @@ class Frame(Element): :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element :param element_justification: (str) All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.UseDictionary = False @@ -3279,7 +3417,7 @@ class Frame(Element): self.Layout(layout) super().__init__(ELEM_TYPE_FRAME, background_color=background_color, text_color=title_color, size=size, - font=font, pad=pad, key=key, tooltip=tooltip, visible=visible) + font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return def AddRow(self, *args): @@ -3326,10 +3464,11 @@ class Frame(Element): element = row[col_num] return element - def Update(self, visible=None): + def Update(self, value=None, visible=None): """ Changes some of the settings for the Frame Element. Must call `Window.Read` or `Window.Finalize` prior + :param value: (Any) New text value to show on frame :param visible: (bool) control visibility of element """ if self.Widget is None: @@ -3339,6 +3478,8 @@ class Frame(Element): self.TKFrame.pack_forget() elif visible is True: self.TKFrame.pack() + if value is not None: + self.TKFrame.config(text=str(value)) add_row = AddRow @@ -3382,7 +3523,7 @@ class Tab(Element): """ def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, disabled=False, - border_width=None, key=None, tooltip=None, right_click_menu=None, visible=True, element_justification='left'): + border_width=None, key=None, tooltip=None, right_click_menu=None, visible=True, element_justification='left', metadata=None): """ :param title: (str) text to show on the tab :param layout: List[List[Element]] The element layout that will be shown in the tab @@ -3397,6 +3538,7 @@ class Tab(Element): :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element :param element_justification: (str) All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.UseDictionary = False @@ -3420,7 +3562,7 @@ class Tab(Element): self.Layout(layout) super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, - key=key, tooltip=tooltip, visible=visible) + key=key, tooltip=tooltip, visible=visible, metadata=metadata) return def AddRow(self, *args): @@ -3517,7 +3659,7 @@ class TabGroup(Element): def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None, font=None, change_submits=False, enable_events=False, pad=None, border_width=None, theme=None, - key=None, tooltip=None, visible=True): + key=None, tooltip=None, visible=True, metadata=None): """ :param layout: List[List[Tab]] Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row :param tab_location: (str) location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright @@ -3533,6 +3675,7 @@ class TabGroup(Element): :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.UseDictionary = False @@ -3556,7 +3699,7 @@ class TabGroup(Element): self.Layout(layout) super().__init__(ELEM_TYPE_TAB_GROUP, background_color=background_color, text_color=title_color, font=font, - pad=pad, key=key, tooltip=tooltip, visible=visible) + pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return def AddRow(self, *args): @@ -3656,7 +3799,7 @@ class Slider(Element): def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, disable_number_display=False, border_width=None, relief=None, change_submits=False, enable_events=False, disabled=False, size=(None, None), font=None, background_color=None, - text_color=None, key=None, pad=None, tooltip=None, visible=True): + text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None): """ :param range: Union[Tuple[int, int], Tuple[float, float]] slider's range (min value, max value) @@ -3684,6 +3827,7 @@ class Slider(Element): :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param tooltip: (str) text, that will appear when mouse hovers over the element :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.TKScale = self.Widget = None # type: tk.Scale @@ -3702,7 +3846,7 @@ class Slider(Element): temp_size = (20, 20) if self.Orientation.startswith('h') else (8, 20) super().__init__(ELEM_TYPE_INPUT_SLIDER, size=temp_size, font=font, background_color=background_color, - text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible) + text_color=text_color, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) return def Update(self, value=None, range=(None, None), disabled=None, visible=None): @@ -3721,8 +3865,6 @@ class Slider(Element): if value is not None: try: self.TKIntVar.set(value) - if range != (None, None): - self.TKScale.config(from_=range[0], to_=range[1]) except: pass self.DefaultValue = value @@ -3734,6 +3876,10 @@ class Slider(Element): self.TKScale.pack_forget() elif visible is True: self.TKScale.pack() + if range != (None, None): + self.TKScale.config(from_=range[0], to_=range[1]) + + def _SliderChangedHandler(self, event): """ @@ -3836,8 +3982,8 @@ class TkScrollableFrame(tk.Frame): self.bind('', self.set_scrollregion) - self.TKFrame.bind_all("", self.yscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! - self.TKFrame.bind_all("", self.xscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! + self.canvas.bind("", self.yscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! + self.canvas.bind("", self.xscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! @@ -3913,7 +4059,7 @@ class Column(Element): """ def __init__(self, layout, background_color=None, size=(None, None), pad=None, scrollable=False, - vertical_scroll_only=False, right_click_menu=None, key=None, visible=True, justification='left', element_justification='left'): + vertical_scroll_only=False, right_click_menu=None, key=None, visible=True, justification='left', element_justification='left', metadata=None): """ :param layout: List[List[Element]] Layout that will be shown in the Column container :param background_color: (str) color of background of entire Column @@ -3927,6 +4073,7 @@ class Column(Element): :param visible: (bool) set visibility state of the element :param justification: (str) set justification for the Column itself. Note entire row containing the Column will be affected :param element_justification: (str) All elements inside the Column will have this justification 'left', 'right', 'center' are valid values + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.UseDictionary = False @@ -3948,7 +4095,7 @@ class Column(Element): self.Justification = justification self.Layout(layout) - super().__init__(ELEM_TYPE_COLUMN, background_color=bg, size=size, pad=pad, key=key, visible=visible) + super().__init__(ELEM_TYPE_COLUMN, background_color=bg, size=size, pad=pad, key=key, visible=visible, metadata=metadata) return def AddRow(self, *args): @@ -4035,7 +4182,7 @@ class Pane(Element): """ def __init__(self, pane_list, background_color=None, size=(None, None), pad=None, orientation='vertical', - show_handle=True, relief=RELIEF_RAISED, handle_size=None, border_width=None, key=None, visible=True): + show_handle=True, relief=RELIEF_RAISED, handle_size=None, border_width=None, key=None, visible=True, metadata=None): """ :param pane_list: List[Column] Must be a list of Column Elements. Each Column supplied becomes one pane that's shown :param background_color: (str) color of background @@ -4054,6 +4201,7 @@ class Pane(Element): :param border_width: (int) width of border around element in pixels :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.UseDictionary = False @@ -4075,7 +4223,7 @@ class Pane(Element): self.Rows = [pane_list] - super().__init__(ELEM_TYPE_PANE, background_color=bg, size=size, pad=pad, key=key, visible=visible) + super().__init__(ELEM_TYPE_PANE, background_color=bg, size=size, pad=pad, key=key, visible=visible, metadata=metadata) return def Update(self, visible=None): @@ -4390,7 +4538,7 @@ class Menu(Element): """ def __init__(self, menu_definition, background_color=None, size=(None, None), tearoff=False, pad=None, key=None, - visible=True): + visible=True, metadata=None): """ :param menu_definition: List[List[Tuple[str, List[str]]] :param background_color: (str) color of the background @@ -4399,6 +4547,7 @@ class Menu(Element): :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) :param key: (any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR @@ -4408,7 +4557,7 @@ class Menu(Element): self.MenuItemChosen = None super().__init__(ELEM_TYPE_MENUBAR, background_color=background_color, size=size, pad=pad, key=key, - visible=visible) + visible=visible, metadata=metadata) return def _MenuItemChosenCallback(self, item_chosen): # Menu Menu Item Chosen Callback @@ -4479,7 +4628,7 @@ class Table(Element): row_height=None, font=None, justification='right', text_color=None, background_color=None, alternating_row_color=None, row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, size=(None, None), change_submits=False, enable_events=False, bind_return_key=False, pad=None, - key=None, tooltip=None, right_click_menu=None, visible=True): + key=None, tooltip=None, right_click_menu=None, visible=True, metadata=None): """ :param values: List[List[Union[str, int, float]]] :param headings: List[str] The headings to show on the top line @@ -4512,6 +4661,7 @@ class Table(Element): :param tooltip: (str) text, that will appear when mouse hovers over the element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.Values = values @@ -4542,7 +4692,7 @@ class Table(Element): self.RowColors = row_colors self.tree_ids = [] # ids returned when inserting items into table - will use to delete colors super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, - size=size, pad=pad, key=key, tooltip=tooltip, visible=visible) + size=size, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return def Update(self, values=None, num_rows=None, visible=None, select_rows=None, alternating_row_color=None, row_colors=None): @@ -4679,7 +4829,7 @@ class Tree(Element): def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False, change_submits=False, enable_events=False, font=None, justification='right', text_color=None, background_color=None, num_rows=None, row_height=None, pad=None, key=None, tooltip=None, - right_click_menu=None, visible=True): + right_click_menu=None, visible=True, metadata=None): """ :param data: (TreeData) The data represented using a PySimpleGUI provided TreeData class @@ -4708,6 +4858,7 @@ class Tree(Element): :param tooltip: (str) text, that will appear when mouse hovers over the element :param right_click_menu: List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format. :param visible: (bool) set visibility state of the element + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.TreeData = data @@ -4735,7 +4886,7 @@ class Tree(Element): self.KeyToID = {'':''} super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, - key=key, tooltip=tooltip, visible=visible) + key=key, tooltip=tooltip, visible=visible, metadata=metadata) return def treeview_selected(self, event): @@ -4949,13 +5100,13 @@ class ErrorElement(Element): """ A "dummy Element" that is returned when there are error conditions, like trying to find an element that's invalid """ - def __init__(self, key=None): + def __init__(self, key=None, metadata=None): """ :param key: Used with window.FindElement and with return values to uniquely identify this element """ self.Key = key - super().__init__(ELEM_TYPE_ERROR, key=key) + super().__init__(ELEM_TYPE_ERROR, key=key, metadata=metadata) def Update(self, silent_on_error=True, *args, **kwargs): @@ -5003,7 +5154,6 @@ class Window: """ Represents a single Window """ - NumOpenWindows = 0 user_defined_icon = None hidden_master_root = None @@ -5020,7 +5170,7 @@ class Window: alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=False, disable_close=False, disable_minimize=False, right_click_menu=None, transparent_color=None, debugger_enabled=True, - finalize=False, element_justification='left'): + finalize=False, element_justification='left', metadata=None): """ :param title: (str) The title that will be displayed in the Titlebar and on the Taskbar :param layout: List[List[Elements]] The layout for the window. Can also be specified in the Layout method @@ -5056,11 +5206,12 @@ class Window: :param debugger_enabled: (bool) If True then the internal debugger will be enabled :param finalize: (bool) If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code :param element_justification: (str) All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values + :param metadata: (Any) User metadata that can be set to ANYTHING """ self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT self.AutoSizeButtons = auto_size_buttons if auto_size_buttons is not None else DEFAULT_AUTOSIZE_BUTTONS - self.Title = title + self.Title = str(title) self.Rows = [] # a list of ELEMENTS for this row self.DefaultElementSize = default_element_size self.DefaultButtonElementSize = default_button_element_size if default_button_element_size != ( @@ -5072,7 +5223,12 @@ class Window: self.Font = font if font else DEFAULT_FONT self.RadioDict = {} self.BorderDepth = border_depth - self.WindowIcon = Window.user_defined_icon if Window.user_defined_icon is not None else icon if icon is not None else DEFAULT_WINDOW_ICON + if icon: + self.WindowIcon = icon + elif Window.user_defined_icon is not None: + self.WindowIcon = Window.user_defined_icon + else: + self.WindowIcon = DEFAULT_WINDOW_ICON self.AutoClose = auto_close self.NonBlocking = False self.TKroot = None @@ -5120,8 +5276,7 @@ class Window: self.WasClosed = False self.ElementJustification = element_justification self.FocusSet = False - if type(title) != str: - warnings.warn('Your title is not a string. Are you passing in the right parameters?', UserWarning) + self.metadata = metadata if layout is not None and type(layout) not in (list, tuple): warnings.warn('Your layout is not a list or tuple... this is not good!') @@ -5130,6 +5285,7 @@ class Window: if finalize: self.Finalize() + @classmethod def GetAContainerNumber(cls): """ @@ -5156,6 +5312,14 @@ class Window: self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0 # print('----- DECREMENTING Num Open Windows = {} ---'.format(Window.NumOpenWindows)) + @classmethod + def get_screen_size(self): + root = tk.Tk() + screen_width = root.winfo_screenwidth() # get window info to move to middle of screen + screen_height = root.winfo_screenheight() + root.destroy() + return screen_width, screen_height + # ------------------------- Add ONE Row to Form ------------------------- # def AddRow(self, *args): """ @@ -5248,7 +5412,6 @@ class Window: """ Deprecated - do not use any longer. Layout your window and then call Read. Or can add a Finalize call before the Read :param rows: - """ raise DeprecationWarning('LayoutAndShow is no longer supported... ') @@ -5298,42 +5461,44 @@ class Window: def SetIcon(self, icon=None, pngbase64=None): """ Sets the icon that is shown on the title bar and on the task bar. Can pass in: - * a filename which must be a .ICO icon file. + * a filename which must be a .ICO icon file for windows * a bytes object * a BASE64 encoded file held in a variable :param icon: (str) Filename or bytes object :param pngbase64: (str) Base64 encoded GIF or PNG file """ - if type(icon) is bytes: - wicon = tkinter.PhotoImage(data=icon) + if type(icon) is bytes or pngbase64 is not None: + wicon = tkinter.PhotoImage(data=icon if icon is not None else pngbase64) try: self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) except: - pass - elif pngbase64 != None: - wicon = tkinter.PhotoImage(data=pngbase64) - try: - self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) - except: - pass - else: - wicon = icon - - self.WindowIcon = wicon - try: - # print(f'icon bitmap = {wicon}') - self.TKroot.iconbitmap(wicon) - except: - # if can't set trying any other ways, just default to the built-in icon - try: wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) try: self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) except: pass + self.WindowIcon = wicon + return + + try: + self.TKroot.iconbitmap(icon) + wicon = icon + except: + try: + wicon = tkinter.PhotoImage(file=icon) + self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) except: - pass + try: + wicon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) + try: + self.TKroot.tk.call('wm', 'iconphoto', self.TKroot._w, wicon) + except: + pass + except: + pass + self.WindowIcon = wicon + def _GetElementAtLocation(self, location): """ @@ -5475,6 +5640,7 @@ class Window: # print(f'Window {self.Title} Last button clicked = {self.LastButtonClicked}') try: self.TKroot.after_cancel(self.TKAfterID) + del self.TKAfterID except: pass # print('** tkafter cancel failed **') @@ -5503,8 +5669,7 @@ class Window: if not self.XFound and self.Timeout != 0 and self.Timeout is not None and self.ReturnValues[ 0] is None: # Special Qt case because returning for no reason so fake timeout self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout - elif not self.XFound and self.ReturnValues[ - 0] is None: # TODO HIGHLY EXPERIMENTAL... added due to tray icon interaction + elif not self.XFound and self.ReturnValues[0] is None: # TODO HIGHLY EXPERIMENTAL... added due to tray icon interaction # print("*** Faking timeout ***") self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout return self.ReturnValues @@ -5557,6 +5722,9 @@ class Window: if self.TKrootDestroyed: return self + self.Read(timeout=1) + return self + # OLD CODE FOLLOWS if not self.Shown: self._Show(non_blocking=True) try: @@ -5564,6 +5732,7 @@ class Window: except: self.TKrootDestroyed = True Window.DecrementOpenCount() + print('** Finalize failed **') # _my_windows.Decrement() # return None, None return self @@ -5748,7 +5917,7 @@ class Window: :return: Union[Tuple[None, None], Tuple[width, height]] Tuple containing width and height of screen in pixels """ if self.TKrootDestroyed: - return None, None + return Window.get_screen_size() screen_width = self.TKroot.winfo_screenwidth() # get window info to move to middle of screen screen_height = self.TKroot.winfo_screenheight() return screen_width, screen_height @@ -5903,6 +6072,9 @@ class Window: Window.NumOpenWindows = 0 # if no hidden window, then this won't execute except: pass + self.TKrootDestroyed = True + del self.TKroot + del self.Rows # IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called @@ -6254,7 +6426,7 @@ def Sizer(h_pixels=0, v_pixels=0): # ------------------------- FOLDER BROWSE Element lazy function ------------------------- # def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, disabled=False, change_submits=False, enable_events=False, - font=None, pad=None, key=None): + font=None, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Browse') :param target: key or (row,col) target for the button (Default value = (ThisRow, -1)) @@ -6275,14 +6447,14 @@ def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FOLDER, target=target, initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, disabled=disabled, button_color=button_color, change_submits=change_submits, - enable_events=enable_events, font=font, pad=pad, key=key) + enable_events=enable_events, font=font, pad=pad, key=key, metadata=metadata) # ------------------------- FILE BROWSE Element lazy function ------------------------- # def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, enable_events=False, font=None, disabled=False, - pad=None, key=None): + pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Browse') @@ -6304,14 +6476,14 @@ def FileBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Fil return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILE, target=target, file_types=file_types, initial_folder=initial_folder, tooltip=tooltip, size=size, auto_size_button=auto_size_button, change_submits=change_submits, enable_events=enable_events, disabled=disabled, - button_color=button_color, font=font, pad=pad, key=key) + button_color=button_color, font=font, pad=pad, key=key, metadata=metadata) # ------------------------- FILES BROWSE Element (Multiple file selection) lazy function ------------------------- # def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), disabled=False, initial_folder=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, enable_events=False, - font=None, pad=None, key=None): + font=None, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Browse') @@ -6333,14 +6505,14 @@ def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Fi return Button(button_text=button_text, button_type=BUTTON_TYPE_BROWSE_FILES, target=target, file_types=file_types, initial_folder=initial_folder, change_submits=change_submits, enable_events=enable_events, tooltip=tooltip, size=size, auto_size_button=auto_size_button, - disabled=disabled, button_color=button_color, font=font, pad=pad, key=key) + disabled=disabled, button_color=button_color, font=font, pad=pad, key=key, metadata=metadata) # ------------------------- FILE BROWSE Element lazy function ------------------------- # def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, enable_events=False, font=None, - pad=None, key=None): + pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Save As...') @@ -6362,14 +6534,14 @@ def FileSaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, - enable_events=enable_events, font=font, pad=pad, key=key) + enable_events=enable_events, font=font, pad=pad, key=key, metadata=metadata) # ------------------------- SAVE AS Element lazy function ------------------------- # def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Files", "*.*"),), initial_folder=None, disabled=False, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, change_submits=False, enable_events=False, font=None, - pad=None, key=None): + pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Save As...') @@ -6391,12 +6563,12 @@ def SaveAs(button_text='Save As...', target=(ThisRow, -1), file_types=(("ALL Fil return Button(button_text=button_text, button_type=BUTTON_TYPE_SAVEAS_FILE, target=target, file_types=file_types, initial_folder=initial_folder, tooltip=tooltip, size=size, disabled=disabled, auto_size_button=auto_size_button, button_color=button_color, change_submits=change_submits, - enable_events=enable_events, font=font, pad=pad, key=key) + enable_events=enable_events, font=font, pad=pad, key=key, metadata=metadata) # ------------------------- SAVE BUTTON Element lazy function ------------------------- # def Save(button_text='Save', size=(None, None), auto_size_button=None, button_color=None, bind_return_key=True, - disabled=False, tooltip=None, font=None, focus=False, pad=None, key=None): + disabled=False, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Save') @@ -6414,12 +6586,12 @@ def Save(button_text='Save', size=(None, None), auto_size_button=None, button_co """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- SUBMIT BUTTON Element lazy function ------------------------- # def Submit(button_text='Submit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, - bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Submit') @@ -6437,13 +6609,13 @@ def Submit(button_text='Submit', size=(None, None), auto_size_button=None, butto """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- OPEN BUTTON Element lazy function ------------------------- # # ------------------------- OPEN BUTTON Element lazy function ------------------------- # def Open(button_text='Open', size=(None, None), auto_size_button=None, button_color=None, disabled=False, - bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Open') @@ -6461,12 +6633,12 @@ def Open(button_text='Open', size=(None, None), auto_size_button=None, button_co """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- OK BUTTON Element lazy function ------------------------- # def OK(button_text='OK', size=(None, None), auto_size_button=None, button_color=None, disabled=False, - bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'OK') @@ -6484,12 +6656,12 @@ def OK(button_text='OK', size=(None, None), auto_size_button=None, button_color= """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- YES BUTTON Element lazy function ------------------------- # def Ok(button_text='Ok', size=(None, None), auto_size_button=None, button_color=None, disabled=False, - bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None): + bind_return_key=True, tooltip=None, font=None, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Ok') @@ -6507,12 +6679,12 @@ def Ok(button_text='Ok', size=(None, None), auto_size_button=None, button_color= """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- CANCEL BUTTON Element lazy function ------------------------- # def Cancel(button_text='Cancel', size=(None, None), auto_size_button=None, button_color=None, disabled=False, - tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, key=None): + tooltip=None, font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Cancel') @@ -6530,12 +6702,12 @@ def Cancel(button_text='Cancel', size=(None, None), auto_size_button=None, butto """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- QUIT BUTTON Element lazy function ------------------------- # def Quit(button_text='Quit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, - font=None, bind_return_key=False, focus=False, pad=None, key=None): + font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Quit') @@ -6553,12 +6725,12 @@ def Quit(button_text='Quit', size=(None, None), auto_size_button=None, button_co """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- Exit BUTTON Element lazy function ------------------------- # def Exit(button_text='Exit', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, - font=None, bind_return_key=False, focus=False, pad=None, key=None): + font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Exit') @@ -6576,12 +6748,12 @@ def Exit(button_text='Exit', size=(None, None), auto_size_button=None, button_co """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- YES BUTTON Element lazy function ------------------------- # def Yes(button_text='Yes', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, - font=None, bind_return_key=True, focus=False, pad=None, key=None): + font=None, bind_return_key=True, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Yes') @@ -6599,12 +6771,12 @@ def Yes(button_text='Yes', size=(None, None), auto_size_button=None, button_colo """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- NO BUTTON Element lazy function ------------------------- # def No(button_text='No', size=(None, None), auto_size_button=None, button_color=None, disabled=False, tooltip=None, - font=None, bind_return_key=False, focus=False, pad=None, key=None): + font=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'No') @@ -6622,12 +6794,12 @@ def No(button_text='No', size=(None, None), auto_size_button=None, button_color= """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- NO BUTTON Element lazy function ------------------------- # def Help(button_text='Help', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, - tooltip=None, bind_return_key=False, focus=False, pad=None, key=None): + tooltip=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = 'Help') @@ -6645,12 +6817,12 @@ def Help(button_text='Help', size=(None, None), auto_size_button=None, button_co """ return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- NO BUTTON Element lazy function ------------------------- # def Debug(button_text='', size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, - tooltip=None, bind_return_key=False, focus=False, pad=None, key=None): + tooltip=None, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button (Default value = '') @@ -6669,13 +6841,13 @@ def Debug(button_text='', size=(None, None), auto_size_button=None, button_color return Button(button_text=button_text, button_type=BUTTON_TYPE_SHOW_DEBUGGER, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=COLOR_SYSTEM_DEFAULT, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, image_data=PSG_DEBUGGER_LOGO, - image_subsample=4, border_width=0) + image_subsample=4, border_width=0, metadata=metadata) # ------------------------- GENERIC BUTTON Element lazy function ------------------------- # def SimpleButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, - font=None, bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + font=None, bind_return_key=False, disabled=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button @@ -6700,13 +6872,13 @@ def SimpleButton(button_text, image_filename=None, image_data=None, image_size=( image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- CLOSE BUTTON Element lazy function ------------------------- # def CloseButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, - bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + bind_return_key=False, disabled=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button @@ -6731,7 +6903,7 @@ def CloseButton(button_text, image_filename=None, image_data=None, image_size=(N image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) CButton = CloseButton @@ -6740,7 +6912,7 @@ CButton = CloseButton # ------------------------- GENERIC BUTTON Element lazy function ------------------------- # def ReadButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, - bind_return_key=False, disabled=False, focus=False, pad=None, key=None): + bind_return_key=False, disabled=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button @@ -6765,7 +6937,7 @@ def ReadButton(button_text, image_filename=None, image_data=None, image_size=(No image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, disabled=disabled, auto_size_button=auto_size_button, button_color=button_color, font=font, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) ReadFormButton = ReadButton @@ -6775,7 +6947,7 @@ RButton = ReadFormButton # ------------------------- Realtime BUTTON Element lazy function ------------------------- # def RealtimeButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, - font=None, disabled=False, bind_return_key=False, focus=False, pad=None, key=None): + font=None, disabled=False, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button @@ -6800,13 +6972,13 @@ def RealtimeButton(button_text, image_filename=None, image_data=None, image_size image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, disabled=disabled, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) # ------------------------- Dummy BUTTON Element lazy function ------------------------- # def DummyButton(button_text, image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, border_width=None, tooltip=None, size=(None, None), auto_size_button=None, button_color=None, font=None, - disabled=False, bind_return_key=False, focus=False, pad=None, key=None): + disabled=False, bind_return_key=False, focus=False, pad=None, key=None, metadata=None): """ :param button_text: text in the button @@ -6831,7 +7003,7 @@ def DummyButton(button_text, image_filename=None, image_data=None, image_size=(N image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, bind_return_key=bind_return_key, focus=focus, - pad=pad, key=key) + pad=pad, key=key, metadata=metadata) # ------------------------- Calendar Chooser Button lazy function ------------------------- # @@ -6839,7 +7011,7 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, - key=None, locale=None, format=None): + key=None, locale=None, format=None, metadata=None): """ :param button_text: text in the button @@ -6870,7 +7042,7 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True image_filename=image_filename, image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) button.CalendarCloseWhenChosen = close_when_date_chosen button.DefaultDate_M_D_Y = default_date_m_d_y button.CalendarLocale = locale @@ -6882,7 +7054,7 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True def ColorChooserButton(button_text, target=(None, None), image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, - key=None): + key=None, metadata=None): """ :param button_text: text in the button @@ -6908,7 +7080,7 @@ def ColorChooserButton(button_text, target=(None, None), image_filename=None, im image_filename=image_filename, image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, metadata=metadata) ##################################### ----- RESULTS ------ ################################################## @@ -7452,7 +7624,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # *********** Make TK Row ***********# tk_row_frame = tk.Frame(containing_frame) row_should_expand = False - row_justify = '' + row_justify = form.ElementJustification for col_num, element in enumerate(flex_row): element.ParentRowFrame = tk_row_frame element.ParentForm = toplevel_form # save the button's parent form object @@ -7536,6 +7708,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): else: anchor=tk.NW side = tk.LEFT + # anchor=tk.NW + # side = tk.LEFT row_justify = element.Justification element.Widget = element.TKColFrame element.TKColFrame.pack(side=side, anchor=anchor, padx=elementpad[0], pady=elementpad[1], expand=False, fill=tk.NONE) @@ -7603,6 +7777,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): width = max_line_len height = num_lines # ---===--- LABEL widget create and place --- # + element = element # type: Text + bd = element.BorderWidth if element.BorderWidth is not None else border_depth stringvar = tk.StringVar() element.TKStringVar = stringvar stringvar.set(str(display_text)) @@ -7618,7 +7794,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE tktext_label = element.Widget = tk.Label(tk_row_frame, textvariable=stringvar, width=width, - height=height, justify=justify, bd=border_depth, font=font) + height=height, justify=justify, bd=bd, font=font) # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS wraplen = tktext_label.winfo_reqwidth() # width of widget in Pixels if not auto_size_text and height == 1: # if just 1 line high, ensure no wrap happens @@ -7669,22 +7845,26 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): bc = toplevel_form.ButtonColor else: bc = DEFAULT_BUTTON_COLOR - border_depth = element.BorderWidth + bd = element.BorderWidth if btype != BUTTON_TYPE_REALTIME: tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height, command=element.ButtonCallBack, justify=tk.LEFT, - bd=border_depth, font=font) + bd=bd, font=font) else: tkbutton = element.Widget = tk.Button(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, - bd=border_depth, font=font) + bd=bd, font=font) tkbutton.bind('', element.ButtonReleaseCallBack) tkbutton.bind('', element.ButtonPressCallBack) if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT: + # if sys.platform.startswith('darwin'): + # print('*** USING MAC BUTTON COLORS ****', bc) + # tkbutton.config(foreground=bc[0], highlightbackground=bc[1],background=bc[1], activebackground=bc[1], highlightcolor=bc[1], activeforeground=bc[1], highlightthickness=-10, bd=0, relief='solid') + # else: tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1]) elif bc[1] == COLOR_SYSTEM_DEFAULT: tkbutton.config(foreground=bc[0]) - if border_depth == 0: + if bd == 0 and not sys.platform.startswith('darwin'): tkbutton.config(relief=tk.FLAT) tkbutton.config(highlightthickness=0) element.TKButton = tkbutton # not used yet but save the TK button in case @@ -7748,15 +7928,15 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): bc = toplevel_form.ButtonColor else: bc = DEFAULT_BUTTON_COLOR - border_depth = element.BorderWidth + bd = element.BorderWidth tkbutton = element.Widget = tk.Menubutton(tk_row_frame, text=btext, width=width, height=height, - justify=tk.LEFT, bd=border_depth, font=font) + justify=tk.LEFT, bd=bd, font=font) element.TKButtonMenu = tkbutton if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT: tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1]) elif bc[1] == COLOR_SYSTEM_DEFAULT: tkbutton.config(foreground=bc[0]) - if border_depth == 0: + if bd == 0: tkbutton.config(relief=tk.FLAT) tkbutton.config(highlightthickness=0) element.TKButton = tkbutton # not used yet but save the TK button in case @@ -7863,13 +8043,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): unique_field = str(element.Key) + '.TCombobox.field' - # unique_field = str(time.time()).replace('.', '') + str(element.Key) + '.TCombobox.field' - - # unique_field = str(time.time()).replace('.','') + '.TCombobox.field' - # unique_field = str(datetime.datetime.today().timestamp()).replace('.','') + '.TCombobox.field' - # unique_field = str(randint(1,50000000)) + '.TCombobox.field' - - # print(unique_field) # Clones over the TCombobox.field element from the "alt" theme. # This is what will allow us to change the background color without altering the whole programs theme @@ -7916,8 +8089,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if v == element.DefaultValue: element.TKCombo.current(i) break - elif element.Values: - element.TKCombo.current(0) + # elif element.Values: + # element.TKCombo.current(0) if element.ChangeSubmits: element.TKCombo.bind('<>', element._ComboboxSelectHandler) if element.Readonly: @@ -8003,9 +8176,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element = element # type: Multiline default_text = element.DefaultText width, height = element_size - border_depth = element.BorderWidth + bd = element.BorderWidth element.TKText = element.Widget = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, - wrap='word', bd=border_depth, font=font, + wrap='word', bd=bd, font=font, relief=RELIEF_SUNKEN) element.TKText.insert(1.0, default_text) # set the default text if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: @@ -9240,7 +9413,7 @@ class DebugWin(): def Close(self): """ """ self.window.Close() - self.window.__del__() + del self.window self.window = None @@ -9289,20 +9462,13 @@ def EasyPrintClose(): # ===================================================# def SetGlobalIcon(icon): """ + Sets the icon which will be used any time a window is created if an icon is not provided when the + window is created. - :param icon: - + :param icon: Union[bytes, str] Either a Base64 byte string or a filename """ - # global _my_windows - try: - with open(icon, 'r') as icon_file: - pass - except: - raise FileNotFoundError - # _my_windows.user_defined_icon = icon Window.user_defined_icon = icon - return True # ============================== SetOptions =========# @@ -9507,6 +9673,32 @@ LOOK_AND_FEEL_TABLE = {'SystemDefault': 'BORDER': 1, 'SLIDER_DEPTH': 1, 'PROGRESS_DEPTH': 0}, + 'Material1': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', #I can't see it change, so I don't know it is good color. + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + + 'Material2': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', #I can't see it change, so I don't know it is good color. + 'BUTTON': ('#FFFFFF', '#0079D3'), #based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, + 'Reddit': {'BACKGROUND': '#ffffff', 'TEXT': '#1a1a1b', 'INPUT': '#dae0e6', @@ -9781,15 +9973,44 @@ def ListOfLookAndFeelValues(): return list(LOOK_AND_FEEL_TABLE.keys()) -def ChangeLookAndFeel(index): +def ChangeLookAndFeel(index, force=False): + """ + Change the "color scheme" of all future PySimpleGUI Windows. + The scheme are string names that specify a group of colors. Background colors, text colors, button colors. + There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel + The look and feel table itself has these indexe into the dictionary LOOK_AND_FEEL_TABLE + SystemDefault + Material1 + Material2 + Reddit + Topanga + GreenTan + Dark + LightGreen + Dark2 + Black + Tan + TanBlue + DarkTanBlue + DarkAmber + DarkBlue + Reds + Green + BluePurple + Purple + BlueMono + GreenMono + BrownBlue + BrightColors + NeutralBlue + Kayak + SandyBeach + TealMono + :param index: (str) the name of the index into the Look and Feel table + :param force: (bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors """ - :param index: - - """ - # global LOOK_AND_FEEL_TABLE - - if sys.platform == 'darwin': + if sys.platform == 'darwin' and not force: print('*** Changing look and feel is not supported on Mac platform ***') return @@ -10320,7 +10541,6 @@ def PopupCancel(*args, title=None, button_color=None, background_color=None, tex :param grab_anywhere: If True can grab anywhere to move the window (Default = False) :param location: Location on screen to display :param location: - """ return Popup(*args, title=title, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color, text_color=text_color, @@ -10365,21 +10585,22 @@ def PopupOKCancel(*args, title=None, button_color=None, background_color=None, t """ Display popup with OK and Cancel buttons - :param *args: + :param args: :param title: - :param button_color: button color (foreground, background) - :param background_color: color of background - :param text_color: color of the text - :param auto_close: (Default = False) + :param button_color: + :param background_color: + :param text_color: + :param auto_close: :param auto_close_duration: - :param non_blocking: (Default = False) - :param icon: Icon to display - :param line_width: Width of lines in characters - :param font: specifies the font family, size, etc - :param no_titlebar: (Default = False) - :param grab_anywhere: If True can grab anywhere to move the window (Default = False) - :param location: Location on screen to display - :return: Union["OK", "Cancel", None] + :param non_blocking: + :param icon: + :param line_width: + :param font: + :param no_titlebar: + :param grab_anywhere: + :param keep_on_top: + :param location: + :return: """ return Popup(*args, title=title, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color, text_color=text_color, @@ -10566,7 +10787,8 @@ def PopupGetFile(message, title=None, default_path='', default_extension='', sav Window.hidden_master_root.destroy() Window.hidden_master_root = None if not multiple_files and type(filename) in (tuple, list): - filename = filename[0] + if len(filename): # only if not 0 length, otherwise will get an error + filename = filename[0] return filename if save_as: @@ -11259,7 +11481,6 @@ def _refresh_debugger(): - # d8b # Y8P # @@ -11308,7 +11529,7 @@ def main(): frame2 = [ [Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], select_mode=SELECT_MODE_EXTENDED, size=(20, 5), no_scrollbar=True)], - [Combo(['Combo item 1',2,3,4 ], size=(20, 3),readonly=True, text_color='red', background_color='red', key='_COMBO1_')], + [Combo(['Combo item 1',2,3,4 ], size=(20, 3), default_value=2, readonly=True, text_color='red', background_color='red', key='_COMBO1_')], # [Combo(['Combo item 1', 2,3,4], size=(20, 3), readonly=False, text_color='red', background_color='red', key='_COMBO2_')], [Spin([1, 2, 3, 'a','b','c'], size=(4, 3))], ] @@ -11357,12 +11578,11 @@ def main(): [Column([[Frame('Structured Data Group', frame5, title_color='red', element_justification='l')]]), ], # [Frame('Graphing Group', frame6)], [TabGroup([[tab1, tab2]],key='_TAB_GROUP_' )], - [ProgressBar(max_value=800, size=(60, 25), key='+PROGRESS+'), Button('Button'), B('Normal'), + [ProgressBar(max_value=800, size=(60, 25), key='+PROGRESS+'), Button('Button'), B('Normal', metadata='my metadata'), Button('Exit', tooltip='Exit button')], ] layout = [[Menu(menu_def, key='_MENU_')]] + layout1 - window = Window('Window Title', layout, font=('Helvetica', 13), # background_color='black', @@ -11371,7 +11591,8 @@ def main(): resizable=True, keep_on_top=True, element_justification='left', - # icon=r'X:\VMWare Virtual Machines\SHARED FOLDER\kingb.ico' + metadata='My window metadata', + # icon=PSG_DEBUGGER_LOGO ) # graph_elem.DrawCircle((200, 200), 50, 'blue') i = 0 @@ -11386,7 +11607,6 @@ def main(): else: graph_elem.Move(-1, 0) graph_elem.DrawLine((i, 0), (i, randint(0, 300)), width=1, color='#{:06x}'.format(randint(0, 0xffffff))) - window['+PROGRESS+'].UpdateBar(i % 800) window.Element('_IMAGE_').UpdateAnimation(DEFAULT_BASE64_LOADING_GIF, time_between_frames=50) i += 1 @@ -11402,6 +11622,8 @@ def main(): show_debugger_popout_window() elif event == 'Launch Debugger': show_debugger_window() + elif event == 'About...': + popup('About this program...') window.Close() @@ -11449,7 +11671,9 @@ rgb = RGB set_global_icon = SetGlobalIcon set_options = SetOptions +test = main +# __all__ = ['** YOUR from PySimpleGUI import * HAS BEEN BLOCKED. YOU ARE NOT ALLOWED THIS KIND OF IMPORT WITH THIS LIBRARY **'] # do not allow import * # -------------------------------- ENTRY POINT IF RUN STANDALONE -------------------------------- # if __name__ == '__main__': diff --git a/readme_creator/readme.md b/readme_creator/readme.md index 4a37fe9b..6ea89ffd 100644 --- a/readme_creator/readme.md +++ b/readme_creator/readme.md @@ -1,37 +1,69 @@ ![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) [![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) tkinter - [![Downloads ](https://pepy.tech/badge/pysimplegui27)](https://pepy.tech/project/pysimplegui27) tkinter 2.7 - [![Downloads](https://pepy.tech/badge/pysimpleguiqt)](https://pepy.tech/project/pysimpleguiqt) Qt - [![Downloads](https://pepy.tech/badge/pysimpleguiwx)](https://pepy.tech/project/pysimpleguiWx) WxPython - [![Downloads](https://pepy.tech/badge/pysimpleguiweb)](https://pepy.tech/project/pysimpleguiWeb) Web (Remi) ![Documentation Status](https://readthedocs.org/projects/pysimplegui/badge/?version=latest) - ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) - ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.4.0-red.svg?longCache=true&style=for-the-badge) - -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.0-blue.svg?longCache=true&style=for-the-badge) - -![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.26.0-orange.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.5.0-red.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.1-blue.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.28.0-orange.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUIWx_version-0.11.0-orange.svg?longCache=true&style=for-the-badge) - ![Python Version](https://img.shields.io/badge/PySimpleGUIWeb_Version-0.28.1-orange.svg?longCache=true&style=for-the-badge) # PySimpleGUI User's Manual -## This manual is crammed full of answers so start your search for answers here. Read/Search this PRIOR to opening an Issue on GitHub. ## Python GUI For Humans - Transforms tkinter, Qt, Remi, WxPython into portable people-friendly Pythonic interfaces -#### July-2019 Note - This readme is being generated from the PySimpleGUI.py file located on GitHub. As a result, some of the calls or parameters may not match the PySimpleGUI that you pip installed. +### This manual is crammed full of answers so start your search for answers here. Read/Search this prior to opening an Issue on GitHub. Press Control F and type. +--- + +# Jump-Start + +## Install + +``` +pip install pysimplegui +or +pip3 install pysimplegui +``` + +### This Code + +```python +import PySimpleGUI as sg +# All the stuff inside your window. +layout = [ [sg.Text('Some text on Row 1')], + [sg.Text('Enter something on Row 2'), sg.InputText()], + [sg.Button('Ok'), sg.Button('Cancel')] ] + +# Create the Window +window = sg.Window('Window Title', layout) +# Event Loop to process "events" and get the "values" of the inputs +while True: + event, values = window.read() + if event in (None, 'Cancel'): # if user closes window or clicks cancel + break + print('You entered ', values[0]) + +window.close() +``` + +### Makes This Window + +and returns the value input as well as the button clicked. + +![image](https://user-images.githubusercontent.com/13696193/61077153-cdfc0b00-a3eb-11e9-9e93-d6ec2ffb442a.png) + +### Any Questions? It's that simple. + +--- #### Looking for a GUI package? Are you.... @@ -72,6 +104,8 @@ * 170+ Demo Programs teach you how to integrate with many popular packages like OpenCV, Matplotlib, PyGame, etc. * 200 pages of documentation, a Cookbook, built-in help using docstrings, in short it's heavily documented +#### July-2019 Note - This readme is being generated from the PySimpleGUI.py file located on GitHub. As a result, some of the calls or parameters may not match the PySimpleGUI that you pip installed. + ## GUI Development does not have to be difficult nor painful. It can be FUN #### What users are saying about PySimpleGUI @@ -107,7 +141,7 @@ [Brief Tutorial](http://Tutorial.PySimpleGUI.org) -[Latest Demos and Master Branch on GitHub](http//www.PySimpleGUI.com) +[Latest Demos and Master Branch on GitHub](https://github.com/PySimpleGUI/PySimpleGUI/tree/master/DemoPrograms) [Repl.it Home for PySimpleGUI](https://repl.it/@PySimpleGUI) @@ -135,7 +169,7 @@ Bluntness is required here as the subtle approach has not worked in the past: Re-read that statement. This **will** be a serious problem for you if you're the type of person that finds it "quicker and easier to post on StackOverflow rather than reading documentation". -If you have not yet matured to the point you are able to undertand this skill or choose to not follow it, then please save ***everyone*** the pain of doing **for you** what you, as a developer, software engineer, or wanna be coder, must do on your own. It's a vital skill for you to learn. +If you have not yet matured to the point you are able to understand this skill or choose to not follow it, then please save ***everyone*** the pain of doing **for you** what you, as a developer, software engineer, or wanna be coder, must do on your own. It's a vital skill for you to learn. Want to be a "real engineer"? Then follow "real engineering practices" such as "reading". You are learning a NEW GUI package. You've not seen anything like it. Don't be so arrogant as to believe you will never need to read documentation. @@ -191,9 +225,15 @@ PySimpleGUI runs on Windows, Linux and Mac, just like tkinter, Qt, WxPython and As of 9/25/2018 **both Python 3 and Python 2.7 are supported** when using **tkinter version** of PySimpleGUI! The Python 3 version is named `PySimpleGUI`. The Python 2.7 version is `PySimpleGUI27`. They are installed separately and the imports are different. See instructions in Installation section for more info. **None** of the other ports can use Python 2. +###### Python 2.7 Code will be deleted from this GitHub on Dec 31, 2019 + Note that the 2.7 port will *cease to exist on this GitHub* on Jan 1, 2020. If you would like to know how much time you have to move over to the Python 3 version of PySimpleGUI, then go here: https://pythonclock.org/. The only thing that will be available is an unsupported PyPI release of PySimpleGUI27. -By "will cease to exist on this GitHub" I mean, it will be deleted entirely. No source code, no supporting programs. Nothing. If you're stuck using 2.7 in December, it would behoove you to fork the 2.7 code on Dec 31, 2019. Legacy Python doesn't have a permanent home here. +By "will cease to exist on this GitHub" I mean, it will be deleted entirely. No source code, no supporting programs. Nothing. If you're stuck using 2.7 in December, it would behoove you to fork the 2.7 code on Dec 31, 2019. Legacy Python doesn't have a permanent home here. It sounds cruel, but experts in security particularly says 2.7 is a huge risk. Furthering it use only hurts the computing world. + +#### Warning - tkinter + Python 3.7.3 and later, including 3.8 has problems + +The version of tkinter that is being supplied with the 3.7.3 and later versions of Python is known to have a problem with table colors. Basically, they don't work. As a result, if you want to use the plain PySimpleGUI running on tkinter, you should be using 3.7.2 or less. 3.6 is the version PySimpleGUI has chosen as the recommended version for most users. ## Output Devices @@ -431,21 +471,39 @@ So, [open an Issue](https://github.com/PySimpleGUI/PySimpleGUI/issues/new/choose ### PySimpleGUI Trolls -Yea, they're out there. Would have NEVER in a billion years guessed that there would be objection to this package, coming from a small, but vocal, number of people. I naively believed everyone would be supportive, see the value, hold hands around the fire, sing songs, and in the very least be truthful. But, this ain't Kansas and the Internet is well... WTF is it with people? +Yea, they're out there. Would have NEVER in a billion years guessed that there would be objection to this package, coming from a small, but vocal, number of people. I naively believed everyone would be supportive, see the value, hold hands around the fire, sing songs, and in the very least be truthful. But, this ain't Kansas and the Internet is well... -If someone is actively discouraging you from using this package, then know you are on the right track and you should give it a try. Stuff like this sometimes happens because the person works for a particular company or they have a GUI package of their own.... that's not popuplar, or they just like to tear things down. +If someone is actively discouraging you from using this package, then know you are on the right track and you should give it a try. Stuff like this sometimes happens because the person works for a particular company or they have a GUI package of their own.... that's not popuplar, or they like to tear things down or I dunno... people can be really weird and emotional. -I promise you're not going to be wrecked for life (as has been claimed). It will not cause you to be a bad programmer with bad habits. It will not ruin your career. It's not going to teach you bad habits. One person I know got a bonus based on a PySimpleGUI program he wrote. +I promise you're not going to be wrecked for life. It will not cause you to be a bad programmer with bad habits. It will not ruin your career. It's not going to teach you bad habits. One person I know got a bonus based on a PySimpleGUI program he wrote. -So fear not. ***How about success being the goal?*** Spend time polishing your GUI and working on your primary code instead of struggling your way through the mountains of documentation in the Qt library, trying to set the color of something. +***How about success being the goal?*** Spend time polishing your GUI and working on your primary code instead of struggling your way through the mountains of documentation in the Qt library, trying to set the color of something. How about getting your program done, working, and in use? -Start with PySimpleGUI, then in the future if you want to code directly in Qt to get more control, it's not like you won't be able to pick up Qt due to your PySimpleGUI knowledge. If anything, you'll have more knowledge going it than most people that are just starting because you'll have already built working GUIs, perhaps many of them and understand how to layout an efficient interface as well as having a good education in GUI Widgets and how they work. +Start with PySimpleGUI, then in the future if you want to code directly in Qt, it's not like you won't be able to learn something else due to your PySimpleGUI knowledge. Unable to write a `while` loop because you already learned using a `for` loop? That seems to be the logic. + +If anything, you'll have more knowledge than most people that are just starting because you'll have already built working GUIs, perhaps many of them and understand how to layout an efficient interface as well as having a good education in GUI Widgets and how they work. + +Here are the forces likely at work.... said Troll has been programming for a while now and really knows these GUI frameworks. Probably invested a lot of hours learning them and thus has some marketable skills (yes, follow the money). + +Enter snotty-nosed high-shool or first year programmer using PySimpleGUI that manages to make GUI windows with great ease... that look, well, pretty much the **same** as the windows Sir Troll ***was*** used to getting paid big bucks to make. What used to be a skill only a select few can do, now 1,000's, 10,000's, or 100,000s more programmers can do, quicker and easier. Bummer Mr. Troll. Bummer. + +"***It's supposed to be difficult to write a GUI***" was an actual reason listed why not to use PySimpleGUI by one person offering to help junior programmers learn Qt. Really? It's supposed to be difficult. Huh. Well, not in this Python universe. Maybe in C++ world it works that way?? + +Just know you're safe in trying and possibly even succeeding in the process. ### Target Audience -PySimpleGUI is trying to serve the 80% of GUI *problems*. The other 20% go straight to tkinter, Qt, WxPython, Remi, or whatever fills that need. That 80% is a huge problem space. Again, the "Simple" of PySimpleGUI describes how easy it is to use, not the nature of the problem space it solves. Note that people are not part of that description. It's not trying to solve GUI problems for 80% of the people trying it. PySimpleGUI tries to solve 80% of GUI ***problems***, regardless of the programmer's experience level. +PySimpleGUI is trying to serve the 80% of GUI *problems*. The other 20% go straight to tkinter, Qt, WxPython, Remi, or whatever fills that need. That 80% is **a huge problem space**. -PySimpleGUI is designed with both the beginner and the experienceed developer in mind. Why? Because both tend to like compact code. Most like people, we just want to get sh\*t done, right? +***The "Simple" of PySimpleGUI describes how easy it is to use, not the nature of the problem space it solves.*** Note that people are not part of that description. It's not trying to solve GUI problems for 80% of the people trying it. PySimpleGUI tries to solve 80% of GUI ***problems***, regardless of the programmer's experience level. + +Is file I/O in Python limited to only certain people? Is starting a thread, building a multi-threaded Python program incredibly difficult such that it takes a year to learn? No. It's quite easy. Like most things Python, you import the object from package and you use it. It is 2 lines of Python code to create and start a thread. + +Why can't it be 2 lines of code to show a GUI window? What's SO special about the Python GUI libraries that they require you to follow a specific Object Oriented model of development? Other parts and packages of Python don't tend to do that. + +The reason is because they didn't originate in Python. They are strangers in a strange land and they had to be "adapted". They started as C++ programs / SDKs, and remain that way too. There's a vaneer of Python slapped onto the top of them, but that sure didn't make them fit the language as well as they could have. + +PySimpleGUI is designed with both the beginner and the experienceed developer in mind. Why? Because both tend to like compact code. Most like people, we just want to get sh\*t done, right? And, why not do it in a way that's like how most of Python works? The beginners can begin working with GUIs ***in their first week of Python education***. The professionals can jump right into the deep end of the pool to use the entire array of Elements and their capabilities to build stuff like a database application. @@ -1747,7 +1805,7 @@ This is the FUN part of the programming of this GUI. In order to really get the This first section on custom windows is for your typical, blocking, non-persistent window. By this I mean, when you "show" the window, the function will not return until the user has clicked a button or closed the window with an X. Two other types of windows exist. -1. Persistent window - the `Window.Read()` method returns and the window continues to be visible. This is good for applications like a chat window or a timer or anything that stays active on the screen for a while. +1. Persistent window - the `Window.read()` method returns and the window continues to be visible. This is good for applications like a chat window or a timer or anything that stays active on the screen for a while. 2. Asynchronous window - the trickiest of the lot. Great care must be exercised. Examples are an MP3 player or status dashboard. Async windows are updated (refreshed) on a periodic basis. You can spot them easily as they will have a `timeout` parameter on the call to read. `event, values = window.Read(timeout=100)` It's both not enjoyable nor helpful to immediately jump into tweaking each and every little thing available to you. Make some simple windows. Use the Cookbook and the Demo Programs as a way to learn and as a "starting point". @@ -1839,7 +1897,9 @@ layout = [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ] -event, values = sg.Window('Get filename example', layout).Read() +window sg.Window('Get filename example', layout) +event, values = window.read() +window.close() sg.Popup(event, values[0]) ``` @@ -1865,8 +1925,8 @@ layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], window = sg.Window('SHA-1 & 256 Hash', layout) -event, values = window.Read() -window.Close() +event, values = window.read() +window.close() source_filename = values[0] # the first input element is values[0] ``` @@ -1887,12 +1947,12 @@ layout = [[sg.Text('Persistent window')], window = sg.Window('Window that stays open', layout) while True: - event, values = window.Read() + event, values = window.read() if event is None or event == 'Exit': break print(event, values) -window.Close() +window.close() ``` ## Pattern 2 B - Persistent window (multiple reads using an event loop + updates data in window) @@ -1906,28 +1966,26 @@ A final note... the parameter `do_not_clear` in the input call determines the ac This example introduces the concept of "keys". Keys are super important in PySimpleGUI as they enable you to identify and work with Elements using names you want to use. Keys can be ANYTHING, except `None`. To access an input element's data that is read in the example below, you will use `values['_IN_']` instead of `values[0]` like before. ```python -import sys -if sys.version_info[0] >= 3: - import PySimpleGUI as sg -else: - import PySimpleGUI27 as sg +import PySimpleGUI as sg -layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_') ], - [sg.Input(key='_IN_')], - [sg.Button('Show'), sg.Button('Exit')]] +layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', key='_OUTPUT_')], + [sg.Input(key='_IN_')], + [sg.Button('Show'), sg.Button('Exit')]] window = sg.Window('Window Title', layout) -while True: # Event Loop - event, values = window.Read() - print(event, values) - if event is None or event == 'Exit': - break - if event == 'Show': - # change the "output" element to be the value of "input" element - window.Element('_OUTPUT_').Update(values['_IN_']) +while True: # Event Loop + event, values = window.read() # can also be written as event, values = window() + print(event, values) + if event is None or event == 'Exit': + break + if event == 'Show': + # change the "output" element to be the value of "input" element + window['_OUTPUT_'].update(values['_IN_']) + # above line can also be written without the update specified + window['_OUTPUT_'](values['_IN_']) -window.Close() +window.close() ``` ### Qt Designer @@ -1954,8 +2012,8 @@ layout = [[sg.Text('Rename files or folders')], window = sg.Window('Rename Files or Folders', layout) -event, values = window.Read() - +event, values = window.read() +window.close() folder_path, file_path = values[0], values[1] # get the data from the values dictionary print(folder_path, file_path) ``` @@ -1972,9 +2030,9 @@ Now let's look at how those 2 rows and the other two row from Python code: ```python layout = [[sg.Text('Rename files or folders')], - [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], - [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], - [sg.Submit(), sg.Cancel()]] + [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], + [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], + [sg.Submit(), sg.Cancel()]] ``` See how the source code mirrors the layout? You simply make lists for each row, then submit that table to PySimpleGUI to show and get values from. @@ -1986,7 +2044,7 @@ For return values the window is scanned from top to bottom, left to right. Each In our example window, there are 2 fields, so the return values from this window will be a dictionary with 2 values in it. Remember, if you do not specify a `key` when creating an element, one will be created for you. They are ints starting with 0. In this example, we have 2 input elements. They will be addressable as values[0] and values[1] ```python -event, values = window.Read() +event, values = window.read() folder_path, file_path = values[0], values[1] ``` @@ -1996,14 +2054,14 @@ Isn't this what a Python programmer looking for a GUI wants? Something easy to w ## Return values -There are 2 return values from a call to `Window.Read()`, an `event` that caused the `Read` to return and `values` a list or dictionary of values. If there are no elements with keys in the layout, then it will be a list. However, some elements, like some buttons, have a key automatically added to them. **It's best to use keys on all of your input type elements.** +There are 2 return values from a call to `Window.read()`, an `event` that caused the `Read` to return and `values` a list or dictionary of values. If there are no elements with keys in the layout, then it will be a list. However, some elements, like some buttons, have a key automatically added to them. **It's best to use keys on all of your input type elements.** ### Two Return Values All Window Read calls return 2 values. By convention a read statement is written: ```python -event, values = window.Read() +event, values = window.read() ``` You don't HAVE to write your reads in this way. You can name your variables however you want. But if you want to code them in a way that other programmers using PySimpleGUI are used to, then use this statement. @@ -2049,7 +2107,7 @@ Putting it all together we end up with an "event loop" that looks something like ```python while True: - event, values = window.Read() + event, values = window.read() if event is None: break window.Close() @@ -2058,7 +2116,7 @@ window.Close() You will very often see the examples and demo programs write this check as: ```python - event, values = window.Read() + event, values = window.read() if event in (None, 'Exit'): break ``` @@ -2089,7 +2147,7 @@ If your window has an event loop where it is read over and over, remember to giv ```python while True: - event, values = window.Read() + event, values = window.read() if event is None or event == 'Quit': break ``` @@ -2098,7 +2156,7 @@ Actually, the more "Pythonic version" is used in most Demo Programs and examples ```python while True: - event, values = window.Read() + event, values = window.read() if event in (None, 'Quit'): break ``` @@ -2111,7 +2169,6 @@ Some elements are capable of generating events when something happens to them. | --- | --- | | InputText | any change | | Combo | item chosen | -| Option menu | item chosen | | Listbox | selection changed | | Radio | selection changed | | Checkbox | selection changed | @@ -2120,6 +2177,8 @@ Some elements are capable of generating events when something happens to them. | Text | clicked | | Status Bar | clicked | | Graph | clicked | +| Graph | dragged | +| Graph | drag ended (mouse up) | | TabGroup | tab clicked | | Slider | slider moved | | Table | row selected | @@ -2160,7 +2219,7 @@ Or, more commonly, you can unpack the return results separately. This is the pr ```python event, values = sg.Window('My title', window_rows).Read() -event, value_list = window.Read() +event, value_list = window.read() value1 = value_list[0] value2 = value_list[1] ... @@ -2199,7 +2258,7 @@ layout = [ ] window = sg.Window('Simple data entry window', layout) -event, values = window.Read() +event, values = window.read() window.Close() sg.Popup(event, values, values['_NAME_'], values['_ADDRESS_'], values['_PHONE_']) @@ -2278,7 +2337,7 @@ layout = [ [sg.Submit(tooltip='Click to submit this form'), sg.Cancel()]] window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False) -event, values = window.Read() +event, values = window.read() sg.Popup('Title', 'The results of the window.', @@ -2362,7 +2421,7 @@ You've already seen a number of examples above that use blocking windows. You'l A blocking Read (one that waits until an event happens) look like this: ```python -event, values = window.Read() +event, values = window.read() ``` A non-blocking / Async Read call looks like this: @@ -2377,12 +2436,20 @@ You can learn more about these async / non-blocking windows toward the end of th The first step is to create the window object using the desired window customizations. +Note - There is no direct support for "**modal windows**" in PySimpleGUI. All windows are accessable at all times unless you manually change the windows' settings. + **IMPORTANT** - Many of the `Window` methods require you to either call `Window.Read` or `Window.Finalize` (or set `finalize=True` in your `Window` call) before you call the method. This is because these 2 calls are what actually creates the window using the underlying GUI Framework. Prior to one of those calls, the methods are likely to crash as they will not yet have their underlying widgets created. ### Window Location PySimpleGUI computes the exact center of your window and centers the window on the screen. If you want to locate your window elsewhere, such as the system default of (0,0), if you have 2 ways of doing this. The first is when the window is created. Use the `location` parameter to set where the window. The second way of doing this is to use the `SetOptions` call which will set the default window location for all windows in the future. +#### 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. + +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 You can get your window's size by access the `Size` property. The window has to be Read once or Finalized in order for the value to be correct. Note that it's a property, not a call. @@ -2443,6 +2510,18 @@ To keep a window on top of all other windows on the screen, set keep_on_top = Tr PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call. +## Closing Windows + +When you are completely done with a window, you should close it and then delete it so that the resources, in particular the tkinter resources, are properly cleaned up. + +If you wish to do this in 1 line of code, here's your line: + +```python +window.close(); del window +``` + +The delete helps with a problem multi-threaded application encounter where tkinter complains that it is being called from the wrong thread (not the program's main thread) + ## Window Methods That Complete Formation of Window After you have completed making your layout, stored in a variable called `layout` in these examples, you will create your window. @@ -2465,7 +2544,7 @@ window.Layout(layout) window.Finalize() ``` -### Chaining The Calls +### Chaining The Calls (the old method) The next level of compression that was done was to chain the calls together into a single line of code. @@ -2554,7 +2633,7 @@ layout = [ ] window = sg.Window('To Do List Example', layout) -event, values = window.Read() +event, values = window.read() ``` The output from this script was this window: @@ -2576,7 +2655,7 @@ for i in range(1,6): layout += [[sg.Button('Save'), sg.Button('Exit')]] window = sg.Window('To Do List Example', layout) -event, values = window.Read() +event, values = window.read() ``` It produces the exact same window of course. That's progress.... went from writing out every row of the GUI to generating every row. If we want 48 items as suggested, change the range(1,6) to range(1,48). Each time through the list another row is added onto the layout. @@ -2734,7 +2813,7 @@ input_rows = [[sg.Input(size=(15,1), pad=(0,0)) for col in range(4)] for row in layout = header + input_rows window = sg.Window('Table Simulation', layout, font='Courier 12') -event, values = window.Read() +event, values = window.read() ``` ## User Defined Elements / Compound Elements @@ -3006,15 +3085,27 @@ Later when you want to make that Element visible you simply call the Element's ` This feature works best on Qt, but does work on the tkinter version as well. The visible parameter can also be used with the Column and Frame "container" Elements. +Note - Tkiner elements behave differently than Qt elements in how they arrange themselves when going from invisible to visible. + +Tkinet 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. + +If you want to not only make the element invisible, on tkinter you can call `Element. + +Qt elements tend to hold their place really well and the window resizes itself nicely. It is more precise and less klunky. + ## 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". In other words, I am lazy and don't like to type. The result is multiple ways to do exactly the same thing. Typically, the Demo Programs and other examples use the full name, or at least a longer name. Thankfully PyCharm will show you the same documentation regardless which you use. -This enables you to code much quicker once you are used to using the SDK. The Text Element, for example, has 3 different names `Text`, `Txt` or`T`. InputText can also be written `Input` or `In` . The shortcuts aren't limited to Elements. The `Window` method `Window.FindElement` can be written as `Window.Element` because it's such a commonly used function. +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` . -It's an ongoing thing. If you don't stay up to date and one of the newer shortcuts is used, you'll need to simply rename that shortcut. +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. + +It's an ongoing thing. If you don't stay up to date and one of the newer shortcuts is used, you'll need to simply rename that shortcut in the code. For examples Replace sg.T with sg.Text if your version doesn't have sg.T in it. ## Text Element | `T == Txt == Text` @@ -3025,8 +3116,13 @@ layout = [ [sg.Text('This is what a Text Element looks like')], ] ``` + ![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. + +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". + --- ## `Window.FindElement(key)` Shortcut `Window[key]` @@ -3045,15 +3141,22 @@ window[key].Update(new_value) ``` This change has been released to PyPI for PySimpleGUI -It **has not yet been released to PyPI** for the other ports of PySimpleGUI (Qt, Wx, Web). You'll find the change on GitHub however for Qt and Web (still working on Wx). MANY Thanks is owed to the person that suggested and showed me how to do this. It's an incredible find. -## `Element.Update()` Shortcut `Element()` +## `Element.Update()` -> `Element()` shortcut This has to be one of the strangest syntactical contructs I've ever written. -It is best used in combination with `FindElement` (see prior section on how to shortcut `FindElement`). When used with the `FindElement` shortcut, the code to update an element can be shortened to this unusual looking call: +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: + +```python +window[key].update(new_value) +``` + +The code can be further compressed by removing the `.update` characters, resulting in this very compact looking call: ```python window[key](new_value) @@ -3061,9 +3164,27 @@ window[key](new_value) Yes, that's a valid statement in Python. +What's happening is that the element itself is being called. You can also writing it like this: + +```python +elem = sg.Text('Some text', key='-TEXT-') +elem('new text value') +``` + +Side note - you can also call your `window` variable directly. If you "call" it it will actually call `Window.read`. + +```python +window = sg.Window(....) +event, values = window() + +# is the same as +window = sg.Window(....) +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. -Still debating whether to begin to immediately use this for all demos going forward and also if should go back and change the docs and demo programs, essentially removing the other technique for doing an update. +Because it's such a foreign construct that someone with 1 week of Python classes will not reconize, 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. @@ -3560,22 +3681,22 @@ import PySimpleGUI as sg # layout the window layout = [[sg.Text('A custom progress meter')], - [sg.ProgressBar(10000, orientation='h', size=(20, 20), key='progressbar')], + [sg.ProgressBar(1000, orientation='h', size=(20, 20), key='progressbar')], [sg.Cancel()]] # create the window` window = sg.Window('Custom Progress Meter', layout) -progress_bar = window.FindElement('progressbar') +progress_bar = window['progressbar'] # loop that would normally do something useful -for i in range(10000): +for i in range(1000): # check to see if the cancel button was clicked and exit loop if clicked - event, values = window.Read(timeout=0) + event, values = window.read(timeout=10) if event == 'Cancel' or event is None: break # update bar with loop value +1 so that bar eventually reaches the maximum - progress_bar.UpdateBar(i + 1) + progress_bar.UpdateBar(i + 1) # done with loop... need to destroy the window as it's still open -window.Close() +window.close() ``` ![progress custom](https://user-images.githubusercontent.com/13696193/45243969-c3508100-b2c3-11e8-82bc-927d0307e093.jpg) @@ -3603,7 +3724,6 @@ Here's a complete solution for a chat-window using an Output Element. To displa ```python import PySimpleGUI as sg -# Blocking window that doesn't close def ChatBot(): layout = [[(sg.Text('This is where standard out is being routed', size=[40, 1]))], [sg.Output(size=(80, 20))], @@ -3611,20 +3731,22 @@ def ChatBot(): sg.Button('SEND', button_color=(sg.YELLOWS[0], sg.BLUES[0])), sg.Button('EXIT', button_color=(sg.YELLOWS[0], sg.GREENS[0]))]] - window = sg.Window('Chat Window', layout, default_element_size=(30, 2)) + window = sg.Window('Chat Window', layout, default_element_size=(30, 2)) # ---===--- Loop taking in user input and using it to query HowDoI web oracle --- # - while True: - event, value = window.Read() + while True: + event, value = window.read() if event == 'SEND': print(value) else: break - + window.close() ChatBot() ``` -## Column Element +## Column Element & Frame, Tab "Container" Elements + +Columns and Frames and Tabs are all "Container Elements" and behave similarly. This section focuses on Columns but can be applied elsewhere. Starting in version 2.9 you'll be able to do more complex layouts by using the Column Element. Think of a Column as a window within a window. And, yes, you can have a Column within a Column if you want. @@ -3665,16 +3787,18 @@ layout = [[sg.Slider(range=(1,100), default_value=10, orientation='v', size=(8,2 # Display the window and get values window = sg.Window('Compact 1-line window with column', layout) -event, values = window.Read() +event, values = window.read() window.Close() sg.Popup(event, values, line_width=200) ``` -### Column Justification +### Column, Frame, Tab, Window element_justification -Beginning in Release 4.3 you can justify the `Column` element's row by setting the `Column`'s `justification` parameter. +Beginning in Release 4.3 you can set the justification for any container element. This is done through the `element_justification` parameter. This will greatly help anyone that wants to center all of their content in a window. Previously it was difficult to do these kinds of layouts, if not impossible. + +justify the `Column` element's row by setting the `Column`'s `justification` parameter. You can also justify the entire contents within a `Column` by using the Column's `element_justification` parameter. @@ -3761,7 +3885,7 @@ The order of operations to obtain a tkinter Canvas Widget is: fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig) # show it all again and get buttons - event, values = window.Read() + event, values = window.read() ``` To get a tkinter Canvas Widget from PySimpleGUI, follow these steps: @@ -3771,7 +3895,7 @@ To get a tkinter Canvas Widget from PySimpleGUI, follow these steps: * Find the Canvas Element by looking up using key * Your Canvas Widget Object will be the found_element.TKCanvas * Draw on your canvas to your heart's content -* Call `window.Read()` - Nothing will appear on your canvas until you call Read +* Call `window.read()` - Nothing will appear on your canvas until you call Read See `Demo_Matplotlib.py` for a Recipe you can copy. @@ -3844,9 +3968,9 @@ graph+UP {'graph': (154, 254)} ## Table Element -Out of all of the Elements, it's the Table and the Tree that are the most "problematic" in the tkinter inter and Qt implementations. They have been difficult implementation. (yea.... get of over it) +Table and Tree Elements are of the most complex in PySimpleGUI. They have a lot of options and a lot of unusual characteristics. -### `window.Read()` return values from Table Element +### `window.read()` return values from Table Element The values returned from a `Window.Read` call for the Table Element are a list of row numbers that are currently highlighted. @@ -3862,6 +3986,24 @@ There has been an elusive problem where clicking on or near the table's header c This problem has existed since the first release of the `Table` element. It was fixed in release 4.3. +### Known table colors in Python 3.7.3, 3.7.4, 3.8, ? + +The tkinter that's been released in the past several releases of Python has a bug. Table colors of all types are not working, at all. The background of the rows never change. If that's important to you, you'll need to **downgrade** your Python version. 3.6 works really well with PySimpleGUI and tkinter. + +### Empty Tables + +If you wish to start your table as being an empty one, you will need to specify an empty table. This list comprehension will create an empty table with 15 rows and 6 columns. + +```python +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. +`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. + ## Tree Element The Tree Element and Table Element are close cousins. Many of the parameters found in the Table Element apply to Tree Elements. In particular the heading information, column widths, etc. @@ -3917,6 +4059,8 @@ Just like windows and the other container elements, the `Tab` Element has a layo *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 visibily parameter but calling update will not change it. + Tabs are contained in TabGroups. They are **not** placed into other layouts. To get a Tab into your window, first place the `Tab` Element into a `TabGroup` Element and then place the `TabGroup` Element into the Window layout. Let's look at this Window as an example: @@ -4220,7 +4364,7 @@ layout = [[sg.Text('Persistent window')], window = sg.Window('Window that stays open', layout) while True: - event, values = window.Read() + event, values = window.read() if event is None or event == 'Exit': break print(event, values) @@ -4390,7 +4534,7 @@ layout = [ [sg.Text('My layout', key='_TEXT_')], window = sg.Window('My new window', layout) while True: # Event Loop - event, values = window.Read() + event, values = window.read() if event is None: break window.Element('_TEXT_').Update('My new text value') @@ -4411,7 +4555,7 @@ window = sg.Window('My new window', layout).Finalize() window.Element('_TEXT_').Update('My new text value') while True: # Event Loop - event, values = window.Read() + event, values = window.read() if event is None: break ``` @@ -4448,7 +4592,7 @@ sz = fontSize window = sg.Window("Font size selector", layout, grab_anywhere=False) # Event Loop while True: - event, values= window.Read() + event, values= window.read() if event is None: break sz_spin = int(values['spin']) @@ -4531,7 +4675,7 @@ window = sg.Window("Keyboard Test", layout, return_keyboard_events=True, use_de # ---===--- Loop taking in user input --- # while True: - event, value = window.Read() + event, value = window.read() if event == "OK" or event is None: print(event, "exiting") @@ -4567,22 +4711,28 @@ To add a menu to a Window place the `Menu` or `MenuBar` element into your layout It doesn't really matter where you place the Menu Element in your layout as it will always be located at the top of the window. +When the user selects an item, it's returns as the event (along with the menu item's key if one was specified in the menu definition) + ## ButtonMenus Button menus were introduced in version 3.21, having been previously released in PySimpleGUIQt. They work exactly the same and are source code compatible between PySimpleGUI and PySimpleGUIQt. These types of menus take a single menu entry where a Menu Bar takes a list of menu entries. +**Return values for ButtonMenus are different than Menu Bars.** + +You will get back the ButtonMenu's KEY as the event. To get the actual item selected, you will look it up in the values dictionary. This can be done with the expression `values[event]` + ## Right Click Menus Right Click Menus were introduced in version 3.21. Almost every element has a right_click_menu parameter and there is a window-level setting for rich click menu that will attach a right click menu to all elements in the window. -The menu definition is the same a s the button menu definition, a single menu entry. +The menu definition is the same as the button menu definition, a single menu entry. ```python right_click_menu = ['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']] ``` The first string in a right click menu and a button menu is ***ignored***. It is not used. Normally you would put the string that is shown on the menu bar in that location. -**Return values for right click menus are different than menu bars and button menus.** Instead of the value being returned through the values dictionary, it is instead sent back as an Event. You will not +**Return values for right click menus are the same as MenuBars.** The value chosen is returned as the event. ## Menu Shortcut keys You have used ALT-key in other Windows programs to navigate menus. For example Alt-F+X exits the program. The Alt-F pulls down the File menu. The X selects the entry marked Exit. @@ -4621,6 +4771,20 @@ To add the `key` `_MY_KEY_` to the Special menu entry, the code would be: If you want to change the characters that indicate a key follows from '::' to something else, change the variable `MENU_KEY_SEPARATOR` +## The Menu Definitions + +Having read through the Menu section, you may have noticed that the right click menu and the button menu have a format that is a little odd as there is a part of it that is not utilized (the first very string). Perhaps the words "Not Used" should be in the examples.... But, there's a reason to retain words there that make sense. + +The reason for this is an architectural one, but it also has a convienence for the user. You can put the individual menu items (button and right click) into a list and you'll have a menu bar definition. + +This would work to make a menu bar from a series of these individual menu defintions: + +```python +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. + # Running Multiple Windows This is where PySimpleGUI continues to be simple, but the problem space just went into the realm of "Complex". @@ -4765,7 +4929,7 @@ If your program is running with blocking `Read` calls, then you will want to add Your event loop will be modified from this blocking: ```python while True: - event, values = window.Read() + event, values = window.read() ``` To this non-blocking: @@ -5079,6 +5243,57 @@ Either way you'll access it using the same `Window` variable `sg.Window.TKroot` Watch this space in the future for the more standardized variable name for this object. It may be something like `Window.Widget` as the Elements use or something like `Window.GUIWindow`. +## Binding tkiner "events" + +If you wish to receive events directly from tkinter, but do it in a PySimpleGUI way, then there's a particular way at the moment to make this happen. + +tkinter performs a callback into user code when an event happens, but that's not how PySimpleGUI works. Instead of callbacks, a PySimpleGUI user's program simply returns an event via the `window.read()` call. In order for your "event" to generate an event that will be returned to you via your read call, follow these instructions: + +1. Create a Button for each event you wish to receive +2. Set visible=False when creating the buttons +3. Make the Button text be the event you want to see returned to you or set the button's Key to that value +4. After creating / finalizing the window, make the tkinter bind call, passing `element.ButtonReboundCallback` as the function to call. + +This sample code binds not an element events but events from the window itself. In this case, Focus events. + +```python +import PySimpleGUI as sg + +layout = [ [sg.Text('My Window')], + [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], + [sg.Button('Do Something'), sg.Button('Exit'), + sg.Button('-FOCUS-IN-', visible=False), sg.Button('-FOCUS-OUT-', visible=False)] ] + +window = sg.Window('Window Title', layout, finalize=True) + +window.TKroot.bind("", window['-FOCUS-IN-'].ButtonReboundCallback) +window.TKroot.bind("", window['-FOCUS-OUT-'].ButtonReboundCallback) +``` + +This code binds the right mouse button to a button so that you can right click a button and get a different event than if you left clicked it. + +```python +import PySimpleGUI as sg + +layout = [ [sg.Text('My Window')], + [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], + [sg.Button('Do Something'), sg.Button('Right Click Me')], + [sg.Button('-RIGHT-', visible=False)] + ] + +window = sg.Window('Window Title', layout, finalize=True) + +window['Right Click Me'].Widget.bind("", window['-RIGHT-'].ButtonReboundCallback) + +has_focus = True +while True: # Event Loop + event, values = window.read() + print(event, values) + if event in (None, 'Exit'): + break +window.close() +``` + --- ------------------ @@ -5091,7 +5306,11 @@ Hoping this is a change for the better and that users will be able to find the i NOTE that this documentatiuopn section is created using the ***GitHUB released PySimpleGUI.py file***. Some of the calls may not be available to you or your port (Qt, Wx, Web). And some of the parameters may be different. We're working on adding docstrings to all the ports which will enable this kind of document to be available for each port. -Without further delay... here are all of the Elements +## Caution - Some functions / methods may be internal only yet exposed in this documenation + +This section of the documentation is generated directly from the source code. As a result, sometimes internal only functions or methods that you are not supposed to be calling are accidently shown in this documentation. Hopefully these accidents don't happen often. + +Without further delay... here are all of the Elements and the Window class ### Button Element @@ -5120,7 +5339,8 @@ Button(button_text="", focus=False, pad=None, key=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -5150,6 +5370,59 @@ Parameter Descriptions: |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |key|(Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonCallBack + +Not user callable! Called by tkinter when a button is clicked. This is where all the fun begins! + +```python +ButtonCallBack() +``` + +#### ButtonPressCallBack + +Not a user callable method. Callback called by tkinter when a "realtime" button is pressed + +``` +ButtonPressCallBack(parm) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|parm|Event info passed in by tkinter| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + +#### ButtonReleaseCallBack + +Not a user callable function. Called by tkinter when a "realtime" button is released + +``` +ButtonReleaseCallBack(parm) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|parm|the event info from tkinter| #### Click @@ -5226,6 +5499,58 @@ Parameter Descriptions: |image_subsample|(int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc| |image_size|Tuple[int, int] Size of the image in pixels (width, height)| +#### click + +Generates a click of the button as if the user clicked the button + Calls the tkinter invoke method for the button + +```python +click() +``` + +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Button Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(text=None, + button_color=(None, None), + disabled=None, + image_data=None, + image_filename=None, + visible=None, + image_subsample=None, + image_size=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|text|(str) sets button text| +|button_color|Tuple[str, str] (text color, background color) of button. Easy to remember which is which if you say "ON" between colors. "red" on "green"| +|disabled|(bool) disable or enable state of the element| +|image_data|Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data| +|image_filename|(str) image filename if there is a button image. GIFs and PNGs only.| +|visible|(bool) control visibility of element| +|image_subsample|(int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc| +|image_size|Tuple[int, int] Size of the image in pixels (width, height)| + ### ButtonMenu Element The Button Menu Element. Creates a button that when clicked will show a menu similar to right click menu @@ -5247,7 +5572,8 @@ ButtonMenu(button_text, pad=None, key=None, tearoff=False, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -5271,6 +5597,32 @@ Parameter Descriptions: |key|(Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element| |tearoff|(bool) Determines if menus should allow them to be torn off| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + +#### Click + +Generates a click of the button as if the user clicked the button + Calls the tkinter invoke method for the button + +```python +Click() +``` #### SetFocus @@ -5315,6 +5667,36 @@ Parameter Descriptions: |menu_definition|(List[List]) New menu definition (in menu definition format)| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the ButtonMenu Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(menu_definition, visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|menu_definition|(List[List]) New menu definition (in menu definition format)| +|visible|(bool) control visibility of element| + ### Canvas Element ``` @@ -5325,7 +5707,8 @@ Canvas(canvas=None, key=None, tooltip=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -5340,6 +5723,23 @@ Parameter Descriptions: |tooltip|(str) text, that will appear when mouse hovers over the element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -5373,6 +5773,21 @@ Parameter Descriptions: #### property: TKCanvas +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + ### Checkbox Element Checkbox Element - Displays a checkbox and text next to it @@ -5391,7 +5806,8 @@ Checkbox(text, key=None, pad=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -5412,6 +5828,23 @@ Parameter Descriptions: |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |tooltip|(str) text, that will appear when mouse hovers over the element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -5470,6 +5903,50 @@ Parameter Descriptions: |disabled|(bool) disable or enable element| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Return the current state of this checkbox + +`get()` + +|Name|Meaning| +|---|---| +| **return** | (bool) Current state of checkbox | + +#### update + +Changes some of the settings for the Checkbox Element. Must call `Window.Read` or `Window.Finalize` prior. +Note that changing visibility may cause element to change locations when made visible after invisible + +``` +update(value=None, + disabled=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(bool) if True checks the checkbox, False clears it| +|disabled|(bool) disable or enable element| +|visible|(bool) control visibility of element| + ### Column Element A container element that is used to create a layout within your window's layout @@ -5485,7 +5962,8 @@ Column(layout, key=None, visible=True, justification="left", - element_justification="left") + element_justification="left", + metadata=None) ``` Parameter Descriptions: @@ -5503,6 +5981,7 @@ Parameter Descriptions: |visible|(bool) set visibility state of the element| |justification|(str) set justification for the Column itself. Note entire row containing the Column will be affected| |element_justification|(str) All elements inside the Column will have this justification 'left', 'right', 'center' are valid values| +|metadata|(Any) User metadata that can be set to ANYTHING| #### AddRow @@ -5518,6 +5997,22 @@ Parameter Descriptions: |---|---| |*args|List[Element] The list of elements for this row| +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + #### Layout Can use like the Window.Layout method, but it's better to use the layout parameter when creating @@ -5576,6 +6071,51 @@ Parameter Descriptions: |---|---| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### layout + +Can use like the Window.Layout method, but it's better to use the layout parameter when creating + +``` +layout(rows) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|rows|List[List[Element]] The rows of Elements| +||| +| **return** | (Column) Used for chaining | + +#### update + +Changes some of the settings for the Column Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|visible|(bool) control visibility of element| + ### Combo Element ComboBox Element - A combination of a single-line input and a drop-down menu. User can type in their own value or choose from list. @@ -5595,7 +6135,8 @@ Combo(values, tooltip=None, readonly=False, font=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -5617,6 +6158,23 @@ Parameter Descriptions: |readonly|(bool) make element readonly (user can't change). True means user cannot change| |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -5683,6 +6241,191 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Returns the current (right now) value of the Combo. DO NOT USE THIS AS THE NORMAL WAY OF READING A COMBO! +You should be using values from your call to window.Read instead. Know what you're doing if you use it. + +`get()` + +|Name|Meaning| +|---|---| +| **return** | Union[Any, None] Returns the value of what is currently chosen | + +#### update + +Changes some of the settings for the Combo Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + values=None, + set_to_index=None, + disabled=None, + readonly=None, + font=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(Any) change which value is current selected hased on new list of previous list of choices| +|values|List[Any] change list of choices| +|set_to_index|(int) change selection to a particular choice starting with index = 0| +|disabled|(bool) disable or enable state of the element| +|readonly|(bool) if True make element readonly (user cannot change any choices)| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|visible|(bool) control visibility of element| + +### ErrorElement Element + + A "dummy Element" that is returned when there are error conditions, like trying to find an element that's invalid + +``` +ErrorElement(key=None, metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + +#### Get + +One of the method names found in other Elements. Used here to return an error string in case it's called + +`Get()` + +|Name|Meaning| +|---|---| +| **return** | (str) A warning text string. | + +#### SetFocus + +Sets the current focus to be on this element + +``` +SetFocus(force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|force|(bool) if True will call focus_force otherwise calls focus_set| + +#### SetTooltip + +Called by application to change the tooltip text for an Element. Normally invoked using the Element Object such as: window.Element('key').SetToolTip('New tip'). + +``` +SetTooltip(tooltip_text) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|tooltip_text|(str) the text to show in tooltip.| + +#### Update + +Update method for the Error Element, an element that should not be directly used by developer + +``` +Update(silent_on_error=True, + args, + kwargs) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|silent_on_error|(bool) if False, then a Popup window will be shown| +|*args|(Any) meant to "soak up" any normal parameters passed in| +|**kwargs|(Any) meant to "soak up" any keyword parameters that were passed in| +||| +| **return** | (ErrorElement) returns 'self' so call can be chained | + +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +One of the method names found in other Elements. Used here to return an error string in case it's called + +`get()` + +|Name|Meaning| +|---|---| +| **return** | (str) A warning text string. | + +#### update + +Update method for the Error Element, an element that should not be directly used by developer + +``` +update(silent_on_error=True, + args, + kwargs) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|silent_on_error|(bool) if False, then a Popup window will be shown| +|*args|(Any) meant to "soak up" any normal parameters passed in| +|**kwargs|(Any) meant to "soak up" any keyword parameters that were passed in| +||| +| **return** | (ErrorElement) returns 'self' so call can be chained | + ### Frame Element A Frame Element that contains other Elements. Encloses with a line around elements and a text label. @@ -5702,7 +6445,8 @@ Frame(title, tooltip=None, right_click_menu=None, visible=True, - element_justification="left") + element_justification="left", + metadata=None) ``` Parameter Descriptions: @@ -5724,6 +6468,7 @@ Parameter Descriptions: |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| |element_justification|(str) All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values| +|metadata|(Any) User metadata that can be set to ANYTHING| #### AddRow @@ -5739,6 +6484,22 @@ Parameter Descriptions: |---|---| |*args|List[Element] The list of elements for this row| +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + #### Layout Can use like the Window.Layout method, but it's better to use the layout parameter when creating @@ -5788,13 +6549,60 @@ Parameter Descriptions: Changes some of the settings for the Frame Element. Must call `Window.Read` or `Window.Finalize` prior ``` -Update(visible=None) +Update(value=None, visible=None) ``` Parameter Descriptions: |Name|Meaning| |---|---| +|value|(Any) New text value to show on frame| +|visible|(bool) control visibility of element| + +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### layout + +Can use like the Window.Layout method, but it's better to use the layout parameter when creating + +``` +layout(rows) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|rows|List[List[Element]] The rows of Elements| +||| +| **return** | (Frame) Used for chaining | + +#### update + +Changes some of the settings for the Frame Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(Any) New text value to show on frame| |visible|(bool) control visibility of element| ### Graph Element @@ -5822,7 +6630,8 @@ Graph(canvas_size, tooltip=None, right_click_menu=None, visible=True, - float_values=False) + float_values=False, + metadata=None) ``` Parameter Descriptions: @@ -5842,6 +6651,7 @@ Parameter Descriptions: |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element (Default = True)| |float_values|(bool) If True x,y coordinates are returned as floats, not ints| +|metadata|(Any) User metadata that can be set to ANYTHING| #### BringFigureToFront @@ -5871,6 +6681,22 @@ Parameter Descriptions: |---|---| |event|(event) event info from tkinter. Contains the x and y coordinates of a click| +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + #### ButtonReleaseCallBack Not a user callable method. Used to get Graph click events. Called by tkinter when button is released @@ -6220,6 +7046,59 @@ Parameter Descriptions: |background_color|color of background| |visible|(bool) control visibility of element| +#### erase + +Erase the Graph - Removes all figures previously "drawn" using the Graph methods (e.g. DrawText) + +```python +erase() +``` + +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### move + +Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system + +``` +move(x_direction, y_direction) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|x_direction|Union[int, float] how far to move in the "X" direction in your coordinates| +|y_direction|Union[int, float] how far to move in the "Y" direction in your coordinates| + +#### update + +Changes some of the settings for the Graph Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(background_color=None, visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|background_color|color of background| +|visible|(bool) control visibility of element| + ### Image Element Image Element - show an image in the window. Should be a GIF or a PNG only @@ -6234,7 +7113,8 @@ Image(filename=None, tooltip=None, right_click_menu=None, visible=True, - enable_events=False) + enable_events=False, + metadata=None) ``` Parameter Descriptions: @@ -6251,6 +7131,23 @@ Parameter Descriptions: |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| |enable_events|(bool) Turns on the element specific events. For an Image element, the event is "image clicked"| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -6316,6 +7213,41 @@ Parameter Descriptions: |source|Union[str,bytes] Filename or Base64 encoded string containing Animated GIF| |time_between_frames|(int) Number of milliseconds to wait between showing frames| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Image Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(filename=None, + data=None, + size=(None, None), + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|filename|(str) filename to the new image to display.| +|data|(str) Base64 encoded string| +|size|Tuple[int,int] size of a image (w,h) w=characters-wide, h=rows-high| +|visible|(bool) control visibility of element| + ### InputText Element Display a single text input field. Based on the tkinter Widget `Entry` @@ -6337,7 +7269,8 @@ InputText(default_text="", focus=False, pad=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6361,6 +7294,23 @@ Parameter Descriptions: |pad|(int, int) or ((int, int), (int, int)) Tuple(s). Amount of padding to put around element. Normally (horizontal pixels, vertical pixels) but can be split apart further into ((horizontal left, horizontal right), (vertical above, vertical below))| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element (Default = True)| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -6408,7 +7358,10 @@ Changes some of the settings for the Input Element. Must call `Window.Read` or ` Update(value=None, disabled=None, select=None, - visible=None) + visible=None, + text_color=None, + background_color=None, + move_cursor_to="end") ``` Parameter Descriptions: @@ -6419,6 +7372,60 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element (sets Entry Widget to readonly or normal)| |select|(bool) if True, then the text will be selected| |visible|(bool) change visibility of element| +|text_color|(str) change color of text being typed| +|background_color|(str) change color of the background| +|move_cursor_to|Union[int, str] Moves the cursor to a particular offset. Defaults to 'end'| + +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Read and return the current value of the input element. Must call `Window.Read` or `Window.Finalize` prior + +`get()` + +|Name|Meaning| +|---|---| +| **return** | (str) current value of Input field or '' if error encountered | + +#### update + +Changes some of the settings for the Input Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + disabled=None, + select=None, + visible=None, + text_color=None, + background_color=None, + move_cursor_to="end") +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(str) new text to display as default text in Input field| +|disabled|(bool) disable or enable state of the element (sets Entry Widget to readonly or normal)| +|select|(bool) if True, then the text will be selected| +|visible|(bool) change visibility of element| +|text_color|(str) change color of text being typed| +|background_color|(str) change color of the background| +|move_cursor_to|Union[int, str] Moves the cursor to a particular offset. Defaults to 'end'| ### Listbox Element @@ -6443,7 +7450,8 @@ Listbox(values, pad=None, tooltip=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6467,6 +7475,33 @@ Parameter Descriptions: |tooltip|(str) text, that will appear when mouse hovers over the element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + +#### GetIndexes + +Returns the items currently selected as a list of indexes + +`GetIndexes()` + +|Name|Meaning| +|---|---| +| **return** | List[int] A list of offsets into values that is currently selected | #### GetListValues @@ -6542,6 +7577,43 @@ Parameter Descriptions: |scroll_to_index|(int) scroll the listbox so that this index is the first shown| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Listbox Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(values=None, + disabled=None, + set_to_index=None, + scroll_to_index=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|values|List[Any] new list of choices to be shown to user| +|disabled|(bool) disable or enable state of the element| +|set_to_index|Union[int, list, tuple] highlights the item(s) indicated. If parm is an int one entry will be set. If is a list, then each entry in list is highlighted| +|scroll_to_index|(int) scroll the listbox so that this index is the first shown| +|visible|(bool) control visibility of element| + ### Menu Element Menu Element is the Element that provides a Menu Bar that goes across the top of the window, just below titlebar. @@ -6566,7 +7638,8 @@ Menu(menu_definition, tearoff=False, pad=None, key=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6580,6 +7653,23 @@ Parameter Descriptions: |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |key|(any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -6624,6 +7714,36 @@ Parameter Descriptions: |menu_definition|List[List[Tuple[str, List[str]]]| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Update a menubar - can change the menu definition and visibility. The entire menu has to be specified + +``` +update(menu_definition=None, visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|menu_definition|List[List[Tuple[str, List[str]]]| +|visible|(bool) control visibility of element| + ### Multiline Element Multiline Element - Display and/or read multiple lines of text. This is both an input and output element. @@ -6649,7 +7769,8 @@ Multiline(default_text="", pad=None, tooltip=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6675,6 +7796,23 @@ Parameter Descriptions: |tooltip|(str) text, that will appear when mouse hovers over the element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -6742,6 +7880,59 @@ Parameter Descriptions: |visible|(bool) set visibility state of the element| |autoscroll|(bool) if True then contents of element are scrolled down when new text is added to the end| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Return current contents of the Multiline Element + +`get()` + +|Name|Meaning| +|---|---| +| **return** | (str) current contents of the Multiline Element (used as an input type of Multiline | + +#### update + +Changes some of the settings for the Multiline Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + disabled=None, + append=False, + font=None, + text_color=None, + background_color=None, + visible=None, + autoscroll=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(str) new text to display| +|disabled|(bool) disable or enable state of the element| +|append|(bool) if True then new value will be added onto the end of the current value. if False then contents will be replaced.| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|text_color|(str) color of the text| +|background_color|(str) color of background| +|visible|(bool) set visibility state of the element| +|autoscroll|(bool) if True then contents of element are scrolled down when new text is added to the end| + ### OptionMenu Element Option Menu is an Element available ONLY on the tkinter port of PySimpleGUI. It's is a widget that is unique @@ -6760,7 +7951,8 @@ OptionMenu(values, key=None, pad=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6778,6 +7970,23 @@ Parameter Descriptions: |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |tooltip|(str) text that will appear when mouse hovers over this element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -6827,6 +8036,41 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the OptionMenu Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + values=None, + disabled=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(Any) the value to choose by default| +|values|List[Any] Values to be displayed| +|disabled|(bool) disable or enable state of the element| +|visible|(bool) control visibility of element| + ### Output Element Output Element - a multi-lined text area where stdout and stderr are re-routed to. @@ -6840,7 +8084,8 @@ Output(size=(None, None), tooltip=None, key=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6856,6 +8101,23 @@ Parameter Descriptions: |key|(Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -6895,10 +8157,6 @@ Parameter Descriptions: |---|---| |tooltip_text|(str) the text to show in tooltip.| -#### TKOut - -#### property: TKOut - #### Update Changes some of the settings for the Output Element. Must call `Window.Read` or `Window.Finalize` prior @@ -6914,6 +8172,36 @@ Parameter Descriptions: |value|(str) string that will replace current contents of the output area| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Output Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(str) string that will replace current contents of the output area| +|visible|(bool) control visibility of element| + ### Pane Element A sliding Pane that is unique to tkinter. Uses Columns to create individual panes @@ -6929,7 +8217,8 @@ Pane(pane_list, handle_size=None, border_width=None, key=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -6947,6 +8236,23 @@ Parameter Descriptions: |border_width|(int) width of border around element in pixels| |key|(any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -6990,6 +8296,35 @@ Parameter Descriptions: |---|---| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Pane Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|visible|(bool) control visibility of element| + ### ProgressBar Element Progress Bar Element - Displays a colored bar that is shaded as progress of some operation is made @@ -7005,7 +8340,8 @@ ProgressBar(max_value, relief=None, key=None, pad=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7023,6 +8359,23 @@ Parameter Descriptions: |key|(Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element| |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -7081,6 +8434,35 @@ Parameter Descriptions: |current_count|(int) sets the current value| |max|(int) changes the max value| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the ProgressBar Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|visible|(bool) control visibility of element| + ### Radio Element Radio Button Element - Used in a group of other Radio Elements to provide user with ability to select only @@ -7101,7 +8483,8 @@ Radio(text, tooltip=None, change_submits=False, enable_events=False, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7123,6 +8506,23 @@ Parameter Descriptions: |change_submits|(bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead| |enable_events|(bool) Turns on the element specific events. Radio Button events happen when an item is selected| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -7188,6 +8588,49 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +A snapshot of the value of Radio Button -> (bool) + +`get()` + +|Name|Meaning| +|---|---| +| **return** | (bool) True if this radio button is selected | + +#### update + +Changes some of the settings for the Radio Button Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + disabled=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(bool) if True change to selected and set others in group to unselected| +|disabled|(bool) disable or enable state of the element| +|visible|(bool) control visibility of element| + ### Slider Element A slider, horizontal or vertical @@ -7211,7 +8654,8 @@ Slider(range=(None, None), key=None, pad=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7237,6 +8681,23 @@ Parameter Descriptions: |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |tooltip|(str) text, that will appear when mouse hovers over the element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -7286,6 +8747,41 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Slider Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + range=(None, None), + disabled=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|Union[int, float] sets current slider value| +|range|Union[Tuple[int, int], Tuple[float, float] Sets a new range for slider| +|disabled|(bool) disable or enable state of the element| +|visible|(bool) control visibility of element| + ### Spin Element A spinner with up/down buttons and a single line of text. Choose 1 values from list @@ -7304,7 +8800,8 @@ Spin(values, key=None, pad=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7325,6 +8822,23 @@ Parameter Descriptions: |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |tooltip|(str) text, that will appear when mouse hovers over the element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### Get @@ -7386,6 +8900,53 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Return the current chosen value showing in spinbox. +This value will be the same as what was provided as list of choices. If list items are ints, then the +item returned will be an int (not a string) + +`get()` + +|Name|Meaning| +|---|---| +| **return** | (Any) The currently visible entry | + +#### update + +Changes some of the settings for the Spin Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + values=None, + disabled=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(Any) set the current value from list of choices| +|values|List[Any] set available choices| +|disabled|(bool) disable or enable state of the element| +|visible|(bool) control visibility of element| + ### StatusBar Element A StatusBar Element creates the sunken text-filled strip at the bottom. Many Windows programs have this line @@ -7404,7 +8965,8 @@ StatusBar(text, pad=None, key=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7425,6 +8987,23 @@ Parameter Descriptions: |key|(Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element| |tooltip|(str) text, that will appear when mouse hovers over the element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -7476,6 +9055,43 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) set visibility state of the element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + background_color=None, + text_color=None, + font=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(str) new text to show| +|background_color|(str) color of background| +|text_color|(str) color of the text| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|visible|(bool) set visibility state of the element| + ### Tab Element Tab Element is another "Container" element that holds a layout and displays a tab with text. Used with TabGroup only @@ -7494,7 +9110,8 @@ Tab(title, tooltip=None, right_click_menu=None, visible=True, - element_justification="left") + element_justification="left", + metadata=None) ``` Parameter Descriptions: @@ -7514,6 +9131,7 @@ Parameter Descriptions: |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| |element_justification|(str) All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values| +|metadata|(Any) User metadata that can be set to ANYTHING| #### AddRow @@ -7529,6 +9147,22 @@ Parameter Descriptions: |---|---| |*args|List[Element] The list of elements for this row| +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + #### Layout Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements @@ -7596,6 +9230,60 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### layout + +Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements + +``` +layout(rows) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|rows|List[List[Element]] The list of rows| +||| +| **return** | (Tab) used for chaining | + +#### select + +Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first! + +```python +select() +``` + +#### update + +Changes some of the settings for the Tab Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(disabled=None, visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|disabled|(bool) disable or enable state of the element| +|visible|(bool) control visibility of element| + ### TabGroup Element TabGroup Element groups together your tabs into the group of tabs you see displayed in your window @@ -7614,7 +9302,8 @@ TabGroup(layout, theme=None, key=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7635,6 +9324,7 @@ Parameter Descriptions: |key|(any) Value that uniquely identifies this element from all other elements. Used when Finding an element or in return values. Must be unique to the window| |tooltip|(str) text, that will appear when mouse hovers over the element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| #### AddRow @@ -7650,6 +9340,22 @@ Parameter Descriptions: |---|---| |*args|List[Element] The list of elements for this row| +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + #### FindKeyFromTabName Searches through the layout to find the key that matches the text on the tab. Implies names should be unique @@ -7723,6 +9429,50 @@ Parameter Descriptions: |---|---| |tooltip_text|(str) the text to show in tooltip.| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on +the tab if no key is defined. Returns None if an error occurs. +Note that this is exactly the same data that would be returned from a call to Window.Read. Are you sure you +are using this method correctly? + +`get()` + +|Name|Meaning| +|---|---| +| **return** | Union[Any, None] The key of the currently selected tab or the tab's text if it has no key | + +#### layout + +Can use like the Window.Layout method, but it's better to use the layout parameter when creating + +``` +layout(rows) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|rows|List[List[Element]] The rows of Elements| +||| +| **return** | (Frame) Used for chaining | + ### Table Element ``` @@ -7753,7 +9503,8 @@ Table(values, key=None, tooltip=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7788,6 +9539,35 @@ Parameter Descriptions: |tooltip|(str) text, that will appear when mouse hovers over the element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + +#### Get + +Dummy function for tkinter port. In the Qt port you can read back the values in the table in case they were +edited. Don't know yet how to enable editing of a Tree in tkinter so just returning the values provided by +user when Table was created or Updated. + +`Get()` + +|Name|Meaning| +|---|---| +| **return** | List[List[Any]] the current table values (for now what was originally provided up updated) | #### SetFocus @@ -7841,12 +9621,63 @@ Parameter Descriptions: |alternating_row_color|(str) the color to make every other row| |row_colors|List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### get + +Dummy function for tkinter port. In the Qt port you can read back the values in the table in case they were +edited. Don't know yet how to enable editing of a Tree in tkinter so just returning the values provided by +user when Table was created or Updated. + +`get()` + +|Name|Meaning| +|---|---| +| **return** | List[List[Any]] the current table values (for now what was originally provided up updated) | + +#### update + +Changes some of the settings for the Table Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(values=None, + num_rows=None, + visible=None, + select_rows=None, + alternating_row_color=None, + row_colors=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|values|List[List[Union[str, int, float]]] A new 2-dimensional table to show| +|num_rows|(int) How many rows to display at a time| +|visible|(bool) if True then will be visible| +|select_rows|List[int] List of rows to select as if user did| +|alternating_row_color|(str) the color to make every other row| +|row_colors|List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)| + ### Text Element Text - Display some text in the window. Usually this means a single line of text. However, the text can also be multiple lines. If multi-lined there are no scroll bars. ``` -Text(text, +Text(text="", size=(None, None), auto_size_text=None, click_submits=False, @@ -7855,12 +9686,14 @@ Text(text, font=None, text_color=None, background_color=None, + border_width=None, justification=None, pad=None, key=None, right_click_menu=None, tooltip=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7876,12 +9709,30 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |text_color|(str) color of the text| |background_color|(str) color of background| +|border_width|(int) number of pixels for the border (if using a relief)| |justification|(str) how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center`| |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| |key|(Any) Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |tooltip|(str) text, that will appear when mouse hovers over the element| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -7933,6 +9784,43 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) set visibility state of the element| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Text Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(value=None, + background_color=None, + text_color=None, + font=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|value|(str) new text to show| +|background_color|(str) color of background| +|text_color|(str) color of the text| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|visible|(bool) set visibility state of the element| + ### Tree Element Tree Element - Presents data in a tree-like manner, much like a file/folder browser. Uses the TreeData class @@ -7961,7 +9849,8 @@ Tree(data=None, key=None, tooltip=None, right_click_menu=None, - visible=True) + visible=True, + metadata=None) ``` Parameter Descriptions: @@ -7991,6 +9880,23 @@ Parameter Descriptions: |tooltip|(str) text, that will appear when mouse hovers over the element| |right_click_menu|List[List[Union[List[str],str]]] A list of lists of Menu items to show when this element is right clicked. See user docs for exact format.| |visible|(bool) set visibility state of the element| +|metadata|(Any) User metadata that can be set to ANYTHING| + +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| #### SetFocus @@ -8044,7 +9950,46 @@ Parameter Descriptions: |icon|Union[bytes, str] can be either a base64 icon or a filename for the icon| |visible|(bool) control visibility of element| -### TreeData Class For Tree Element +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + +#### update + +Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior + +``` +update(values=None, + key=None, + value=None, + text=None, + icon=None, + visible=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|values|(TreeData) Representation of the tree| +|key|(Any) identifies a particular item in tree to update| +|value|(Any) sets the node identified by key to a particular value| +|text|(str) sets the node identified by ket to this string| +|icon|Union[bytes, str] can be either a base64 icon or a filename for the icon| +|visible|(bool) control visibility of element| + +### TreeData Element Class that user fills in to represent their tree data. It's a very simple tree representation with a root "Node" with possibly one or more children "Nodes". Each Node contains a key, text to display, list of values to display @@ -8079,18 +10024,6 @@ Parameter Descriptions: |values|List[Any] The list of values that are displayed at this node| |icon|Union[str, bytes]| -#### Node - -Contains information about the individual node in the tree - -``` -Node(parent, - key, - text, - values, - icon=None) -``` - ### VerticalSeparator Element Vertical Separator Element draws a vertical line at the given location. It will span 1 "row". Usually paired with @@ -8106,6 +10039,22 @@ Parameter Descriptions: |---|---| |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| +#### ButtonReboundCallback + +Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal +callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button +callback function that is normally called. + +``` +ButtonReboundCallback(event) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|(unknown) Not used in this function.| + #### SetFocus Sets the current focus to be on this element @@ -8134,6 +10083,21 @@ Parameter Descriptions: |---|---| |tooltip_text|(str) the text to show in tooltip.| +#### expand + +Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions + +``` +expand(expand_x=False, expand_y=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|expand_x|(Bool) If True Element will expand in the Horizontal directions| +|expand_y|(Bool) If True Element will expand in the Vertical directions| + ### Window Represents a single Window @@ -8172,7 +10136,8 @@ Window(title, transparent_color=None, debugger_enabled=True, finalize=False, - element_justification="left") + element_justification="left", + metadata=None) ``` Parameter Descriptions: @@ -8213,6 +10178,7 @@ Parameter Descriptions: |debugger_enabled|(bool) If True then the internal debugger will be enabled| |finalize|(bool) If True then the Finalize method will be called. Use this rather than chaining .Finalize for cleaner code| |element_justification|(str) All elements in the Window itself will have this justification 'left', 'right', 'center' are valid values| +|metadata|(Any) User metadata that can be set to ANYTHING| #### AddRow @@ -8284,14 +10250,6 @@ Get the current location of the window's top left corner |---|---| | **return** | Tuple[(int), (int)] The x and y location in tuple form (x,y) | -#### DecrementOpenCount - -Not user callable! Decrements the number of open windows - -``` -DecrementOpenCount() -``` - #### Disable Disables window from taking any input from the user @@ -8544,15 +10502,6 @@ Hides the window from the screen and the task bar Hide() ``` -#### IncrementOpenCount - -Not user callable! Increments the number of open windows -Note - there is a bug where this count easily gets out of sync. Issue has been opened already. No ill effects - -``` -IncrementOpenCount() -``` - #### Layout Second of two preferred ways of telling a Window what its layout is. The other way is to pass the layout as @@ -8572,35 +10521,6 @@ Parameter Descriptions: ||| | **return** | (Window} self so that you can chain method calls | -#### LayoutAndRead - -Deprecated!! Now your layout your window's rows (layout) and then separately call Read. - -``` -LayoutAndRead(rows, non_blocking=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|(List[List[Element]]) The layout of the window| -|non_blocking|(bool) if True the Read call will not block| - -#### LayoutAndShow - -Deprecated - do not use any longer. Layout your window and then call Read. Or can add a Finalize call before the Read - -``` -LayoutAndShow(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|| - #### LoadFromDisk Restore values from a previous call to SaveToDisk which saves the returned values dictionary in Pickle format @@ -8727,7 +10647,7 @@ Parameter Descriptions: #### SetIcon Sets the icon that is shown on the title bar and on the task bar. Can pass in: -* a filename which must be a .ICO icon file. +* a filename which must be a .ICO icon file for windows * a bytes object * a BASE64 encoded file held in a variable @@ -8758,6 +10678,8 @@ Parameter Descriptions: #### Size +Note the `Window.Size` can be used for both reading and writing + #### property: Size Return the current size of the window in pixels @@ -8785,6 +10707,288 @@ call and then have that same source run on plain PySimpleGUI. |---|---| | **return** | | +#### close + +Closes window. Users can safely call even if window has been destroyed. Should always call when done with + a window so that resources are properly freed up within your thread. + +```python +close() +``` + +#### disable + +Disables window from taking any input from the user + +```python +disable() +``` + +#### disappear + +Causes a window to "disappear" from the screen, but remain on the taskbar. It does this by turning the alpha + channel to 0. NOTE that on some platforms alpha is not supported. The window will remain showing on these + platforms. The Raspberry Pi for example does not have an alpha setting + +```python +disappear() +``` + +#### elem + +Find element object associated with the provided key. +THIS METHOD IS NO LONGER NEEDED to be called by the user + +You can perform the same operation by writing this statement: +element = window[key] + +You can drop the entire "FindElement" function name and use [ ] instead. + +Typically used in combination with a call to element's Update method (or any other element method!): +window[key].Update(new_value) + +Versus the "old way" +window.FindElement(key).Update(new_value) + +This call can be abbreviated to any of these: +FindElement == Element == Find +Rememeber that this call will return None if no match is found which may cause your code to crash if not +checked for. + +``` +elem(key, silent_on_error=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|(Any) Used with window.FindElement and with return values to uniquely identify this element| +|silent_on_error|(bool) If True do not display popup nor print warning of key errors| +||| +| **return** | Union[Element, Error Element, None] Return value can be:
* the Element that matches the supplied key if found
* an Error Element if silent_on_error is False
* None if silent_on_error True | + +#### element + +Find element object associated with the provided key. +THIS METHOD IS NO LONGER NEEDED to be called by the user + +You can perform the same operation by writing this statement: +element = window[key] + +You can drop the entire "FindElement" function name and use [ ] instead. + +Typically used in combination with a call to element's Update method (or any other element method!): +window[key].Update(new_value) + +Versus the "old way" +window.FindElement(key).Update(new_value) + +This call can be abbreviated to any of these: +FindElement == Element == Find +Rememeber that this call will return None if no match is found which may cause your code to crash if not +checked for. + +``` +element(key, silent_on_error=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|(Any) Used with window.FindElement and with return values to uniquely identify this element| +|silent_on_error|(bool) If True do not display popup nor print warning of key errors| +||| +| **return** | Union[Element, Error Element, None] Return value can be:
* the Element that matches the supplied key if found
* an Error Element if silent_on_error is False
* None if silent_on_error True | + +#### enable + +Re-enables window to take user input after having it be Disabled previously + +```python +enable() +``` + +#### fill + +Fill in elements that are input fields with data based on a 'values dictionary' + +``` +fill(values_dict) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|values_dict|(Dict[Any:Any]) {Element key : value} pairs| +||| +| **return** | (Window) returns self so can be chained with other methods | + +#### finalize + +Use this method to cause your layout to built into a real tkinter window. In reality this method is like +Read(timeout=0). It doesn't block and uses your layout to create tkinter widgets to represent the elements. +Lots of action! + +`finalize()` + +|Name|Meaning| +|---|---| +| **return** | (Window) Returns 'self' so that method "Chaining" can happen (read up about it as it's very cool!) | + +#### find + +Find element object associated with the provided key. +THIS METHOD IS NO LONGER NEEDED to be called by the user + +You can perform the same operation by writing this statement: +element = window[key] + +You can drop the entire "FindElement" function name and use [ ] instead. + +Typically used in combination with a call to element's Update method (or any other element method!): +window[key].Update(new_value) + +Versus the "old way" +window.FindElement(key).Update(new_value) + +This call can be abbreviated to any of these: +FindElement == Element == Find +Rememeber that this call will return None if no match is found which may cause your code to crash if not +checked for. + +``` +find(key, silent_on_error=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|(Any) Used with window.FindElement and with return values to uniquely identify this element| +|silent_on_error|(bool) If True do not display popup nor print warning of key errors| +||| +| **return** | Union[Element, Error Element, None] Return value can be:
* the Element that matches the supplied key if found
* an Error Element if silent_on_error is False
* None if silent_on_error True | + +#### hide + +Hides the window from the screen and the task bar + +```python +hide() +``` + +#### layout + +Second of two preferred ways of telling a Window what its layout is. The other way is to pass the layout as +a parameter to Window object. The parameter method is the currently preferred method. This call to Layout +has been removed from examples contained in documents and in the Demo Programs. Trying to remove this call +from history and replace with sending as a parameter to Window. + +``` +layout(rows) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|rows|List[List[Elements]] Your entire layout| +||| +| **return** | (Window} self so that you can chain method calls | + +#### maximize + +Maximize the window. This is done differently on a windows system versus a linux or mac one. For non-Windows + the root attribute '-fullscreen' is set to True. For Windows the "root" state is changed to "zoomed" + The reason for the difference is the title bar is removed in some cases when using fullscreen option + +```python +maximize() +``` + +#### minimize + +Minimize this window to the task bar + +```python +minimize() +``` + +#### move + +Move the upper left corner of this window to the x,y coordinates provided + +``` +move(x, y) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|x|(int) x coordinate in pixels| +|y|(int) y coordinate in pixels| + +#### normal + +Restore a window to a non-maximized state. Does different things depending on platform. See Maximize for more. + +```python +normal() +``` + +#### read + +THE biggest deal method in the Window class! This is how you get all of your data from your Window. +Pass in a timeout (in milliseconds) to wait for a maximum of timeout milliseconds. Will return timeout_key +if no other GUI events happen first. + +``` +read(timeout=None, timeout_key="__TIMEOUT__") +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|timeout|(int) Milliseconds to wait until the Read will return IF no other GUI events happen first| +|timeout_key|(Any) The value that will be returned from the call if the timer expired| +||| +| **return** | Tuple[(Any), Union[Dict[Any:Any]], List[Any], None] (event, values)
(event or timeout_key or None, Dictionary of values or List of values from all elements in the Window) | + +#### reappear + +Causes a window previously made to "Disappear" (using that method). Does this by restoring the alpha channel + +```python +reappear() +``` + +#### refresh + +Refreshes the window by calling tkroot.update(). Can sometimes get away with a refresh instead of a Read. +Use this call when you want something to appear in your Window immediately (as soon as this function is called). +Without this call your changes to a Window will not be visible to the user until the next Read call + +`refresh()` + +|Name|Meaning| +|---|---| +| **return** | (Window) `self` so that method calls can be easily "chained" | + +#### size + +#### property: size + +Return the current size of the window in pixels + +|Name|Meaning| +|---|---| +| **return** | Tuple[(int), (int)] the (width, height) of the window | + ``` CButton(button_text, image_filename=None, @@ -8801,7 +11005,8 @@ CButton(button_text, disabled=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -8848,7 +11053,8 @@ CalendarButton(button_text, pad=None, key=None, locale=None, - format=None) + format=None, + metadata=None) ``` Parameter Descriptions: @@ -8891,7 +11097,8 @@ Cancel(button_text="Cancel", bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -8910,15 +11117,48 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexe into the dictionary LOOK_AND_FEEL_TABLE +SystemDefault +Material1 +Material2 +Reddit +Topanga +GreenTan +Dark +LightGreen +Dark2 +Black +Tan +TanBlue +DarkTanBlue +DarkAmber +DarkBlue +Reds +Green +BluePurple +Purple +BlueMono +GreenMono +BrownBlue +BrightColors +NeutralBlue +Kayak +SandyBeach +TealMono + ``` -ChangeLookAndFeel(index) +ChangeLookAndFeel(index, force=False) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|index|| +|index|(str) the name of the index into the Look and Feel table| +|force|(bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors| ``` CloseButton(button_text, @@ -8936,7 +11176,8 @@ CloseButton(button_text, disabled=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -8979,7 +11220,8 @@ ColorChooserButton(button_text, bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9017,7 +11259,8 @@ Debug(button_text="", bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9054,7 +11297,8 @@ DummyButton(button_text, bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9124,7 +11368,8 @@ Exit(button_text="Exit", bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9157,7 +11402,8 @@ FileBrowse(button_text="Browse", font=None, disabled=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9195,7 +11441,8 @@ FileSaveAs(button_text="Save As...", enable_events=False, font=None, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9233,7 +11480,8 @@ FilesBrowse(button_text="Browse", enable_events=False, font=None, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9283,7 +11531,8 @@ FolderBrowse(button_text="Browse", enable_events=False, font=None, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9317,7 +11566,8 @@ Help(button_text="Help", bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9353,7 +11603,8 @@ No(button_text="No", bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9383,7 +11634,8 @@ OK(button_text="OK", font=None, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9436,7 +11688,8 @@ Ok(button_text="Ok", font=None, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9508,7 +11761,8 @@ Open(button_text="Open", font=None, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9766,7 +12020,8 @@ Quit(button_text="Quit", bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9803,7 +12058,8 @@ RButton(button_text, disabled=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9843,7 +12099,8 @@ ReadButton(button_text, disabled=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9883,7 +12140,8 @@ RealtimeButton(button_text, bind_return_key=False, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9918,7 +12176,8 @@ Save(button_text="Save", font=None, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -9953,7 +12212,8 @@ SaveAs(button_text="Save As...", enable_events=False, font=None, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -10008,6 +12268,9 @@ Parameter Descriptions: ||| | **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | +Sets the icon which will be used any time a window is created if an icon is not provided when the +window is created. + ``` SetGlobalIcon(icon) ``` @@ -10016,7 +12279,7 @@ Parameter Descriptions: |Name|Meaning| |---|---| -|icon|| +|icon|Union[bytes, str] Either a Base64 byte string or a filename| ``` SetOptions(icon=None, @@ -10103,7 +12366,8 @@ Submit(button_text="Submit", font=None, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -10147,7 +12411,8 @@ Yes(button_text="Yes", bind_return_key=True, focus=False, pad=None, - key=None) + key=None, + metadata=None) ``` Parameter Descriptions: @@ -10168,6 +12433,82 @@ Parameter Descriptions: ||| | **return** | (Button) | +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexe into the dictionary LOOK_AND_FEEL_TABLE +SystemDefault +Material1 +Material2 +Reddit +Topanga +GreenTan +Dark +LightGreen +Dark2 +Black +Tan +TanBlue +DarkTanBlue +DarkAmber +DarkBlue +Reds +Green +BluePurple +Purple +BlueMono +GreenMono +BrownBlue +BrightColors +NeutralBlue +Kayak +SandyBeach +TealMono + +``` +change_look_and_feel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table| +|force|(bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors| + +``` +easy_print(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +easy_print_close() +``` + ``` eprint(args, size=(None, None), @@ -10197,12 +12538,1088 @@ Parameter Descriptions: |grab_anywhere|If True can grab anywhere to move the window (Default = False)| |do_not_reroute_stdout|(Default = True)| +Fills a window with values provided in a values dictionary { element_key : new_value } + +``` +fill_form_with_values(window, values_dict) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|window|(Window) The window object to fill| +|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| + +``` +list_of_look_and_feel_values() +``` + The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. ``` main() ``` +``` +obj_to_string(obj, extra=" ") +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|obj|| +|extra|(Default value = ' ')| + +``` +obj_to_string_single_obj(obj) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|obj|| + +``` +one_line_progress_meter(title, + current_value, + max_value, + key, + args, + orientation="v", + bar_color=(None, None), + button_color=None, + size=(20, 20), + border_width=None, + grab_anywhere=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|title|text to display| +|current_value|current progressbar value| +|max_value|max value of progressbar| +|key|Used with window.FindElement and with return values to uniquely identify this element| +|*args|stuff to output.| +|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| +|bar_color|| +|button_color|button color (foreground, background)| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| +|border_width|width of border around element| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| + +``` +one_line_progress_meter_cancel(key) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the +"print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. + +``` +popup(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + button_type=0, + auto_close=False, + auto_close_duration=None, + custom_text=(None, None), + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|(Any) Variable number of your arguments. Load up the call with stuff to see!| +|title|(str) Optional title for the window. If none provided, the first arg will be used instead.| +|button_color|Tuple[str, str] Color of the buttons shown (text color, button color)| +|background_color|(str) Window's background color| +|text_color|(str) text color| +|button_type|(enum) NOT USER SET! Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). There are many Popup functions and they call Popup, changing this parameter to get the desired effect.| +|auto_close|(bool) If True the window will automatically close| +|auto_close_duration|(int) time in seconds to keep window open before closing it automatically| +|custom_text|Union[Tuple[str, str], str] A string or pair of strings that contain the text to display on the buttons| +|non_blocking|(bool) If True then will immediately return from the function without waiting for the user's input.| +|icon|Union[str, bytes] icon to display on the window. Same format as a Window call| +|line_width|(int) Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH| +|font|Union[str, tuple(font name, size, modifiers) specifies the font family, size, etc| +|no_titlebar|(bool) If True will not show the frame around the window and the titlebar across the top| +|grab_anywhere|(bool) If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too| +|location|Tuple[int, int] Location on screen to display the top left corner of window. Defaults to window centered on screen| +||| +| **return** | Union[str, None] Returns text of the button that was pressed. None will be returned if user closed window with X | + +Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency + and the rate the frames of video is shown remains constant. Maybe your frames update every 30 ms but your + event loop is running every 10 ms. You don't have to worry about delaying, just call it every time through the + loop. + +``` +popup_animated(image_source, + message=None, + background_color=None, + text_color=None, + font=None, + no_titlebar=True, + grab_anywhere=True, + keep_on_top=True, + location=(None, None), + alpha_channel=None, + time_between_frames=0, + transparent_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|image_source|Union[str, bytes] Either a filename or a base64 string.| +|message|(str) An optional message to be shown with the animation| +|background_color|(str) color of background| +|text_color|(str) color of the text| +|font|Union[str, tuple) specifies the font family, size, etc| +|no_titlebar|(bool) If True then the titlebar and window frame will not be shown| +|grab_anywhere|(bool) If True then you can move the window just clicking anywhere on window, hold and drag| +|keep_on_top|(bool) If True then Window will remain on top of all other windows currently shownn| +|location|(int, int) (x,y) location on the screen to place the top left corner of your window. Default is to center on screen| +|alpha_channel|(float) Window transparency 0 = invisible 1 = completely visible. Values between are see through| +|time_between_frames|(int) Amount of time in milliseconds between each frame| +|transparent_color|(str) This color will be completely see-through in your window. Can even click through| + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +popup_annoying(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Popup that closes itself after some time period + +``` +popup_auto_close(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display Popup with "cancelled" button text + +``` +popup_cancel(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Popup with colored button and 'Error' as button text + +``` +popup_error(args, + title=None, + button_color=(None, None), + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|(Default = (None))| + +Display popup window with text entry field and browse button so that a file can be chosen by user. + +``` +popup_get_file(message, + title=None, + default_path="", + default_extension="", + save_as=False, + multiple_files=False, + file_types=(('ALL Files', '*.*'),), + no_window=False, + size=(None, None), + button_color=None, + background_color=None, + text_color=None, + icon=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None), + initial_folder=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|message|(str) message displayed to user| +|title|(str) Window title| +|default_path|(str) path to display to user as starting point (filled into the input field)| +|default_extension|(str) If no extension entered by user, add this to filename (only used in saveas dialogs)| +|save_as|(bool) if True, the "save as" dialog is shown which will verify before overwriting| +|multiple_files|(bool) if True, then allows multiple files to be selected that are returned with ';' between each filename| +|file_types|Tuple[Tuple[str,str]] List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.*"),)| +|no_window|(bool) if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown| +|size|Tuple[int, int] (width, height) of the InputText Element| +|button_color|Tuple[str, str] Color of the button (text, background)| +|background_color|(str) background color of the entire window| +|text_color|(str) color of the message text| +|icon|Union[bytes, str] filename or base64 string to be used for the window's icon| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|no_titlebar|(bool) If True no titlebar will be shown| +|grab_anywhere|(bool) If True can click and drag anywhere in the window to move the window| +|keep_on_top|(bool) If True the window will remain above all current windows| +|location|Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window| +|initial_folder|(str) location in filesystem to begin browsing| +||| +| **return** | Union[str, None] string representing the file(s) chosen, None if cancelled or window closed with X | + +Display popup with text entry field and browse button so that a folder can be chosen. + +``` +popup_get_folder(message, + title=None, + default_path="", + no_window=False, + size=(None, None), + button_color=None, + background_color=None, + text_color=None, + icon=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None), + initial_folder=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|message|(str) message displayed to user| +|title|(str) Window title| +|default_path|(str) path to display to user as starting point (filled into the input field)| +|no_window|(bool) if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown| +|size|Tuple[int, int] (width, height) of the InputText Element| +|button_color|Tuple[str, str] Color of the button (text, background)| +|background_color|(str) background color of the entire window| +|text_color|(str) color of the message text| +|icon|Union[bytes, str] filename or base64 string to be used for the window's icon| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|no_titlebar|(bool) If True no titlebar will be shown| +|grab_anywhere|(bool) If True can click and drag anywhere in the window to move the window| +|keep_on_top|(bool) If True the window will remain above all current windows| +|location|Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window| +|initial_folder|(str) location in filesystem to begin browsing| +||| +| **return** | Union[str, None] string representing the path chosen, None if cancelled or window closed with X | + +Display Popup with text entry field. Returns the text entered or None if closed / cancelled + +``` +popup_get_text(message, + title=None, + default_text="", + password_char="", + size=(None, None), + button_color=None, + background_color=None, + text_color=None, + icon=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|message|(str) message displayed to user| +|title|(str) Window title| +|default_text|(str) default value to put into input area| +|password_char|(str) character to be shown instead of actually typed characters| +|size|Tuple[int, int] (width, height) of the InputText Element| +|button_color|Tuple[str, str] Color of the button (text, background)| +|background_color|(str) background color of the entire window| +|text_color|(str) color of the message text| +|icon|Union[bytes, str] filename or base64 string to be used for the window's icon| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|no_titlebar|(bool) If True no titlebar will be shown| +|grab_anywhere|(bool) If True can click and drag anywhere in the window to move the window| +|keep_on_top|(bool) If True the window will remain above all current windows| +|location|Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window| +||| +| **return** | Union[str, None] Text entered or None if window was closed or cancel button clicked | + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +popup_no_border(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Show a Popup but without any buttons + +``` +popup_no_buttons(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +popup_no_frame(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +popup_no_titlebar(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Show Popup window and immediately return (does not block) + +``` +popup_no_wait(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show Popup window and immediately return (does not block) + +``` +popup_non_blocking(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display Popup with OK button only + +``` +popup_ok(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show Popup box that doesn't block and closes itself + +``` +popup_quick(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=2, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|(Default value = 2)| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show Popup window with no titlebar, doesn't block, and auto closes itself. + +``` +popup_quick_message(args, + title=None, + button_type=5, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=2, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=True, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_NO_BUTTONS)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|(Default value = 2)| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = True)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you +want, just like a print statement. + +``` +popup_scrolled(args, + title=None, + button_color=None, + yes_no=False, + auto_close=False, + auto_close_duration=None, + size=(None, None), + location=(None, None), + non_blocking=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|(Any) Variable number of items to display| +|title|(str) Title to display in the window.| +|button_color|Tuple[str, str] button color (foreground, background)| +|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| +|auto_close|(bool) if True window will close itself| +|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| +|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| +||| +| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | + +Popup that closes itself after some time period + +``` +popup_timed(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display Popup with Yes and No buttons + +``` +popup_yes_no(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|Location on screen to display| +||| +| **return** | Union["Yes", "No", None] | + +``` +quit(button_text="Quit", + size=(None, None), + auto_size_button=None, + button_color=None, + disabled=False, + tooltip=None, + font=None, + bind_return_key=False, + focus=False, + pad=None, + key=None, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Quit')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +Sets the icon which will be used any time a window is created if an icon is not provided when the +window is created. + +``` +set_global_icon(icon) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|icon|Union[bytes, str] Either a Base64 byte string or a filename| + +``` +set_options(icon=None, + button_color=None, + element_size=(None, None), + button_element_size=(None, None), + margins=(None, None), + element_padding=(None, None), + auto_size_text=None, + auto_size_buttons=None, + font=None, + border_width=None, + slider_border_width=None, + slider_relief=None, + slider_orientation=None, + autoclose_time=None, + message_box_line_width=None, + progress_meter_border_depth=None, + progress_meter_style=None, + progress_meter_relief=None, + progress_meter_color=None, + progress_meter_size=None, + text_justification=None, + background_color=None, + element_background_color=None, + text_element_background_color=None, + input_elements_background_color=None, + input_text_color=None, + scrollbar_color=None, + text_color=None, + element_text_color=None, + debug_win_size=(None, None), + window_location=(None, None), + error_button_color=(None, None), + tooltip_time=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|icon|filename of icon used for taskbar and title bar| +|button_color|button color (foreground, background)| +|element_size|Tuple[int, int] element size (width, height) in characters| +|button_element_size|Tuple[int, int]| +|margins|tkinter margins around outsize (Default = (None))| +|element_padding|(Default = (None))| +|auto_size_text|True if size should fit the text length| +|auto_size_buttons|| +|font|specifies the font family, size, etc| +|border_width|width of border around element| +|slider_border_width|| +|slider_relief|| +|slider_orientation|| +|autoclose_time|| +|message_box_line_width|| +|progress_meter_border_depth|| +|progress_meter_style|| +|progress_meter_relief|| +|progress_meter_color|| +|progress_meter_size|Tuple[int, int]| +|text_justification|| +|background_color|color of background| +|element_background_color|| +|text_element_background_color|| +|input_elements_background_color|| +|input_text_color|| +|scrollbar_color|| +|text_color|color of the text| +|element_text_color|| +|debug_win_size|Tuple[int, int] (Default = (None))| +|window_location|(Default = (None))| +|error_button_color|(Default = (None))| +|tooltip_time|time in milliseconds to wait before showing a tooltip. Default is 400ms| + +``` +sgprint(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +sgprint_close() +``` + Shows the smaller "popout" window. Default location is the upper right corner of your screen ``` @@ -10260,6 +13677,12 @@ Parameter Descriptions: ||| | **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | +The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. + +``` +test() +``` + --- # "Demo Programs" Applications @@ -11186,11 +14609,11 @@ However, your code will look weird and ancient. ;-) (i.e. readable) MORE Docstring and main doc updates! * Finally 2.7 gets an upgrade and with it doc strings. It however doesn't get a full-version bump like main PySimpleGUI as this may be its last release. -* New window[key] == window.FindElement(key) +* New `window[key] == window.FindElement(key)` * New Update calling method. Can directly call an Element and it will call its Update method - * window[key](value=new_value) == window.FindElement(key).Update(value=new_value) + * `window[key](value=new_value) == window.FindElement(key).Update(value=new_value)` * Made Tearoff part of element so anything can be a menu in theory -* Removed a bunch of __del__ calls. Hoping it doesn't bite me in memory leaks +* Removed a bunch of `__del__` calls. Hoping it doesn't bite me in memory leaks * Combo.Get method added * Combo.GetSelectedItemsIndexes removed * New Graph methods SendFigureToBack, BringFigureToFront @@ -11273,6 +14696,38 @@ Let's hope it doesn't all blow up in our faces! * Frame - Trying to set the size but doesn't seem to be setting it correctly * Tabs will now expand & fill now (I hope this is OK!!!) +## 4.5 PySimpleGUI Release 04-Nov-2019 + +* Metadata! + * All elements have a NEW metadata parameter that you can set to anything and access with Element.metadata + * Windows can have metadata too +* Window.finalize() - changed internally to do a fully window.read with timeout=1 so that it will complete all initializations correctly +* Removed typing import +* ButtonReboundCallback - Used with tkinter's Widget.bind method. Use this as a "target" for your bind and you'll get the event back via window.read() +* NEW Element methods that will work on a variety of elements: + * set_size - sets width, height. Can set one or both + * get_size - returns width, heigh of Element (underlying Widget), usually in PIXELS + * hide_row - hides the entire row that an element occupies + * unhide_row - makes visible the entire row that an element occupies + * expand - causes element to expand to fill available space in X or Y or both directions +* InputText Element - Update got new parameters: text_color=None, background_color=None, move_cursor_to='end' +* RadioButton - fix in Update. Was causing problems with loading a window from disk +* Text Element - new border width parameter that is used when there's a relief set for the text element +* Output Element - special expand method like the one for all other elements +* Frame element - Can change the text for the frame using Update method +* Slider element - can change range. Previously had to change value to change the range +* Scrollable frame / column - change to how mousewheel scrolls. Was causing all things to scroll when scrolling a single column + * NOTE - may have a bad side effect for scrolling tables with a mouse wheel +* Fix for icon setting when creating window. Wasn't defaulting to correct icon +* Window.get_screen_size() returns the screen width and height. Does not have to be a window that's created already as this is a class method +* Window.GetScreenDimensions - will return size even if the window has been destroyed by using get_screen_size +* Now deleting window read timers every time done with them +* Combo no longer defaults to first entry +* New Material1 and Material2 look and feel color schemes +* change_look_and_feel has new "force" parameter. Set to True to force colors when using a Mac +* Fix in popup_get_files when 0 length of filename +* Fix in Window.SetIcon - properly sets icon using file with Linux now. Was always defaulting + ### Upcoming Make suggestions people! Future release features @@ -11299,7 +14754,7 @@ While not the best programming practice, the implementation resulted in a single In Python, functions behave just like object. When you're placing a Text Element into your form, you may be sometimes calling a function and other times declaring an object. If you use the word Text, then you're getting an object. If you're using `Txt`, then you're calling a function that returns a `Text` object. **Lists** -It seemed quite natural to use Python's powerful list constructs when possible. The form is specified as a series of lists. Each "row" of the GUI is represented as a list of Elements. When the form read returns the results to the user, all of the results are presented as a single list. This makes reading a form's values super-simple to do in a single line of Python code. +It seemed quite natural to use Python's powerful list constructs when possible. The form is specified as a series of lists. Each "row" of the GUI is represented as a list of Elements. **Dictionaries** Want to view your form's results as a dictionary instead of a list... no problem, just use the `key` keyword on your elements. For complex forms with a lot of values that need to be changed frequently, this is by far the best way of consuming the results. diff --git a/readme_creator/show_all_tags.py b/readme_creator/show_all_tags.py index 60ba1c19..478c0ba5 100644 --- a/readme_creator/show_all_tags.py +++ b/readme_creator/show_all_tags.py @@ -9,7 +9,7 @@ import PySimpleGUIlib """ -layout = [[PySimpleGUIlib.Output(size=(80,20))]] +layout = [[PySimpleGUIlib.Output(size=(80,50))]] window = PySimpleGUIlib.Window('Dump of tags', layout, resizable=True).Finalize() psg_members = inspect.getmembers(PySimpleGUIlib)