LOTS of new doc strings. Renamed some functions to begin with _. Window.Show, ReadNonBlocking, Added giant licensing info
This commit is contained in:
parent
9adb0e3691
commit
dab3f1f1f3
349
PySimpleGUI.py
349
PySimpleGUI.py
|
@ -1,8 +1,103 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
version = __version__ = "4.1.0.5 Unreleased"
|
version = __version__ = "4.1.0.8 Unreleased"
|
||||||
|
|
||||||
|
|
||||||
|
# 888888ba .d88888b oo dP .88888. dP dP dP
|
||||||
|
# 88 `8b 88. "' 88 d8' `88 88 88 88
|
||||||
|
# a88aaaa8P' dP dP `Y88888b. dP 88d8b.d8b. 88d888b. 88 .d8888b. 88 88 88 88
|
||||||
|
# 88 88 88 `8b 88 88'`88'`88 88' `88 88 88ooood8 88 YP88 88 88 88
|
||||||
|
# 88 88. .88 d8' .8P 88 88 88 88 88. .88 88 88. ... Y8. .88 Y8. .8P 88
|
||||||
|
# dP `8888P88 Y88888P dP dP dP dP 88Y888P' dP `88888P' `88888' `Y88888P' dP
|
||||||
|
# .88 88
|
||||||
|
# d8888P dP
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# __ __
|
||||||
|
# / | / |
|
||||||
|
# $$ | ______ ______ ______ $$ |
|
||||||
|
# $$ | / \ / \ / \ $$ |
|
||||||
|
# $$ | /$$$$$$ |/$$$$$$ | $$$$$$ |$$ |
|
||||||
|
# $$ | $$ $$ |$$ | $$ | / $$ |$$ |
|
||||||
|
# $$ |_____ $$$$$$$$/ $$ \__$$ |/$$$$$$$ |$$ |
|
||||||
|
# $$ |$$ |$$ $$ |$$ $$ |$$ |
|
||||||
|
# $$$$$$$$/ $$$$$$$/ $$$$$$$ | $$$$$$$/ $$/
|
||||||
|
# / \__$$ |
|
||||||
|
# $$ $$/
|
||||||
|
# $$$$$$/
|
||||||
|
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright 2018, 2019 PySimpleGUI.org
|
||||||
|
|
||||||
|
OK, let's get the bullshit out of the way
|
||||||
|
|
||||||
|
This software is available for your use under a MODIFIED LGPL3+ license
|
||||||
|
|
||||||
|
This notice, these first 83 lines of code shall remain unchanged
|
||||||
|
|
||||||
|
# #
|
||||||
|
## ## #### ##### # ###### # ###### #####
|
||||||
|
# # # # # # # # # # # # # #
|
||||||
|
# # # # # # # # ##### # ##### # #
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
# # # # # # # # # # # #
|
||||||
|
# # #### ##### # # # ###### #####
|
||||||
|
|
||||||
|
|
||||||
|
888 .d8888b. 8888888b. 888 .d8888b.
|
||||||
|
888 d88P Y88b 888 Y88b 888 d88P Y88b
|
||||||
|
888 888 888 888 888 888 .d88P
|
||||||
|
888 888 888 d88P 888 8888" 888
|
||||||
|
888 888 88888 8888888P" 888 "Y8b. 8888888
|
||||||
|
888 888 888 888 888 888 888 888
|
||||||
|
888 Y88b d88P 888 888 Y88b d88P
|
||||||
|
88888888 "Y8888P88 888 88888888 "Y8888P"
|
||||||
|
|
||||||
|
|
||||||
|
And just what the fuck is that? Well, it's LPGL3+ and these FOUR simple stipulations.
|
||||||
|
1. These and all comments are to remain in this document
|
||||||
|
2. You will not post this software in a repository or a location for others to download from:
|
||||||
|
A. Unless you have made 10 lines of changes
|
||||||
|
3. Forking is OK and does NOT require any changes as long as it is obvious forked and stated on the page
|
||||||
|
where your software is being hosted. For example, GitHub does a fantastic job of indicating if a repository
|
||||||
|
is the result of a fork.
|
||||||
|
4. The "Official" version of PySimpleGUI and the associated documentation lives on two (and only two) places:
|
||||||
|
1. GitHub - (http://www.PySimpleGUI.com) currently pointing at:
|
||||||
|
# https://github.com/PySimpleGUI/PySimpleGUI
|
||||||
|
2. Read the Docs (via http://www.PySimpleGUI.org). Currently is pointed at:
|
||||||
|
https://pysimplegui.readthedocs.io/en/latest/
|
||||||
|
If you've obtained this software in any other way, then those listed here, then SUPPORT WILL NOT BE PROVIDED.
|
||||||
|
Please don't waste anyone's time by filing an Issue unless you have a genuine copy of the software.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
I absolutely hate having to include that nonsense, but every word is there for solid reasons.
|
||||||
|
|
||||||
|
How about having FUN with this package?? Terrible note to begin this journey of actually having fun making
|
||||||
|
GUI based applications so I'll try to make it up to you.
|
||||||
|
|
||||||
|
The first bit of good news for you is that literally 100s of pages of documentation await you. And nearly 200
|
||||||
|
Demo Programs have been written as a "jump start" mechanism to get your running as quickly as possible.
|
||||||
|
|
||||||
|
Some general bits of advice:
|
||||||
|
Upgrade your software! pip install --upgrade --no-cache-dir PySimpleGUI
|
||||||
|
If you're thinking of filing an Issue or posting a problem, Upgrade your software first
|
||||||
|
There are constantly something new and interesting coming out of this project so stay current if you can
|
||||||
|
|
||||||
|
The FASTEST WAY to learn PySimpleGUI is to begin to play with it, and to read the documentation.
|
||||||
|
http://www.PySimpleGUI.org
|
||||||
|
http://Cookbook.PySimpleGUI.org
|
||||||
|
|
||||||
|
The User Manual and the Cookbook are both designed to paint some nice looking GUIs on your screen within 5 minutes of you deciding to PySimpleGUI out.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
# do the Python 2 or 3 check so the right tkinter stuff can get pulled in
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
if sys.version_info[0] >= 3:
|
if sys.version_info[0] >= 3:
|
||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
from tkinter import filedialog
|
from tkinter import filedialog
|
||||||
|
@ -10,7 +105,7 @@ if sys.version_info[0] >= 3:
|
||||||
from tkinter import ttk
|
from tkinter import ttk
|
||||||
import tkinter.scrolledtext as tkst
|
import tkinter.scrolledtext as tkst
|
||||||
import tkinter.font
|
import tkinter.font
|
||||||
else:
|
else: # Do NOT remove any of these regardless of what your IDE or lint says. They are transformed in the 3 to 2 process
|
||||||
import Tkinter as tk
|
import Tkinter as tk
|
||||||
import tkFileDialog
|
import tkFileDialog
|
||||||
import ttk
|
import ttk
|
||||||
|
@ -24,19 +119,10 @@ import pickle
|
||||||
import calendar
|
import calendar
|
||||||
import textwrap
|
import textwrap
|
||||||
import inspect
|
import inspect
|
||||||
from typing import List, Any, Union
|
from typing import List, Any, Union, Tuple, Dict
|
||||||
from random import randint
|
from random import randint
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
# 888888ba .d88888b oo dP .88888. dP dP dP
|
|
||||||
# 88 `8b 88. "' 88 d8' `88 88 88 88
|
|
||||||
# a88aaaa8P' dP dP `Y88888b. dP 88d8b.d8b. 88d888b. 88 .d8888b. 88 88 88 88
|
|
||||||
# 88 88 88 `8b 88 88'`88'`88 88' `88 88 88ooood8 88 YP88 88 88 88
|
|
||||||
# 88 88. .88 d8' .8P 88 88 88 88 88. .88 88 88. ... Y8. .88 Y8. .8P 88
|
|
||||||
# dP `8888P88 Y88888P dP dP dP dP 88Y888P' dP `88888P' `88888' `Y88888P' dP
|
|
||||||
# .88 88
|
|
||||||
# d8888P dP
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
g_time_start = 0
|
g_time_start = 0
|
||||||
|
@ -1315,7 +1401,7 @@ class Spin(Element):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param values: List[Any] List of valid values
|
:param values: List[Any] List of valid values
|
||||||
:param initial_value: [Any] Initial item to show in window. Choose from list of values supplied
|
:param initial_value: (Any) Initial item to show in window. Choose from list of values supplied
|
||||||
:param disabled: (bool) set disable state
|
:param disabled: (bool) set disable state
|
||||||
:param change_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
|
: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. Spin events happen when an item changes
|
:param enable_events: (bool) Turns on the element specific events. Spin events happen when an item changes
|
||||||
|
@ -1411,7 +1497,9 @@ class Spin(Element):
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Multiline(Element):
|
class Multiline(Element):
|
||||||
"""
|
"""
|
||||||
Multiline Element - Display and read multiple lines of text. This is both an input and output element.
|
Multiline Element - Display and/or read multiple lines of text. This is both an input and output element.
|
||||||
|
Other PySimpleGUI ports have a separate MultilineInput and MultilineOutput elements. May want to split this
|
||||||
|
one up in the future too.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, border_width=None,
|
def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, border_width=None,
|
||||||
|
@ -1452,8 +1540,7 @@ class Multiline(Element):
|
||||||
self.ChangeSubmits = change_submits or enable_events
|
self.ChangeSubmits = change_submits or enable_events
|
||||||
self.RightClickMenu = right_click_menu
|
self.RightClickMenu = right_click_menu
|
||||||
self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
|
self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH
|
||||||
self.TKText = self.Widget = None # type: tk.scrolledtext.ScrolledText
|
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,
|
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)
|
||||||
return
|
return
|
||||||
|
@ -1508,14 +1595,14 @@ class Multiline(Element):
|
||||||
"""
|
"""
|
||||||
Return current contents of the Multiline Element
|
Return current contents of the Multiline Element
|
||||||
|
|
||||||
:return: (str) current contents of the Multiline Input element
|
:return: (str) current contents of the Multiline Element (used as an input type of Multiline
|
||||||
"""
|
"""
|
||||||
|
|
||||||
return self.TKText.get(1.0, tk.END)
|
return self.TKText.get(1.0, tk.END)
|
||||||
|
|
||||||
def SetFocus(self, force=False):
|
def SetFocus(self, force=False):
|
||||||
"""
|
"""
|
||||||
Moves the focus to this Multiline
|
Moves the focus (that little blinking cursor) to this Multiline Element
|
||||||
|
|
||||||
:param force: (bool). If True, will call focus_force instead of focus_set
|
:param force: (bool). If True, will call focus_force instead of focus_set
|
||||||
"""
|
"""
|
||||||
|
@ -1537,8 +1624,7 @@ class Multiline(Element):
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class Text(Element):
|
class Text(Element):
|
||||||
"""
|
"""
|
||||||
Text - Display some text in the window. Usually this means a single line of text. However, the text can also
|
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.
|
||||||
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,
|
def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=False, enable_events=False,
|
||||||
|
@ -1619,28 +1705,28 @@ T = Text
|
||||||
# StatusBar #
|
# StatusBar #
|
||||||
# ---------------------------------------------------------------------- #
|
# ---------------------------------------------------------------------- #
|
||||||
class StatusBar(Element):
|
class StatusBar(Element):
|
||||||
""" """
|
"""
|
||||||
|
A StatusBar Element creates the sunken text-filled strip at the bottom. Many Windows programs have this line
|
||||||
|
"""
|
||||||
def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, enable_events=False,
|
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,
|
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):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param text: (required) text that is to be displayed in the widget
|
:param text: Text that is to be displayed in the widget
|
||||||
:param size: (w,h) w=characters-wide, h=rows-high
|
:param size: (w,h) w=characters-wide, h=rows-high
|
||||||
:param auto_size_text: True if size should fit the text length
|
:param auto_size_text: True if size should fit the text length
|
||||||
:param click_submits: ????????????????????
|
:param click_submits: (bool) DO NOT USE. Only listed for backwards compat - Use enable_events instead
|
||||||
:param enable_events: Turns on the element specific events.(Default = False)
|
:param enable_events: (bool) Turns on the element specific events. StatusBar events occur when the bar is clicked
|
||||||
:param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID` (Default value = RELIEF_SUNKEN)
|
:param relief: relief style. Values are same as progress meter relief values. Can be a constant or a string: `RELIEF_RAISED RELIEF_SUNKEN RELIEF_FLAT RELIEF_RIDGE RELIEF_GROOVE RELIEF_SOLID`
|
||||||
:param font: specifies the font family, size, etc
|
:param font: Union[str, tuple] specifies the font family, size, etc
|
||||||
:param text_color: color of the text
|
:param text_color: (str) color of the text
|
||||||
:param background_color: color of background
|
:param background_color: (str) color of background
|
||||||
:param justification: justification for data display
|
:param justification: (str) how string should be aligned within space provided by size. Valid choices = `left`, `right`, `center`
|
||||||
:param pad: Amount of padding to put around 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: Used with window.FindElement and with return values to uniquely identify this element to uniquely identify this 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 tooltip: (str) text, that will appear when mouse hovers over the element
|
||||||
:param visible: set visibility state of the element (Default = True)
|
:param visible: (bool) set visibility state of the element
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.DisplayText = text
|
self.DisplayText = text
|
||||||
|
@ -1663,11 +1749,11 @@ class StatusBar(Element):
|
||||||
"""
|
"""
|
||||||
Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior
|
Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior
|
||||||
|
|
||||||
:param value: ??????????????????????????
|
:param value: (str) new text to show
|
||||||
:param background_color: color of background
|
:param background_color: (str) color of background
|
||||||
:param text_color: color of the text
|
:param text_color: (str) color of the text
|
||||||
:param font: specifies the font family, size, etc
|
:param font: Union[str, tuple] specifies the font family, size, etc
|
||||||
:param visible: (bool) control visibility of element
|
:param visible: (bool) set visibility state of the element
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if value is not None:
|
if value is not None:
|
||||||
|
@ -4625,39 +4711,38 @@ class Window:
|
||||||
disable_minimize=False, right_click_menu=None, transparent_color=None, debugger_enabled=True):
|
disable_minimize=False, right_click_menu=None, transparent_color=None, debugger_enabled=True):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
:param title:
|
:param title: (str) The title that will be displayed in the Titlebar and on the Taskbar
|
||||||
:param layout:
|
:param layout: List[List[Elements]] The layout for the window. Can also be specified in the Layout method
|
||||||
:param default_element_size: (Default value = DEFAULT_ELEMENT_SIZE)
|
:param default_element_size: Tuple[int, int] (width, height) size in characters (wide) and rows (high) for all elements in this window
|
||||||
:param default_button_element_size:
|
:param default_button_element_size: Tuple[int, int] (width, height) size in characters (wide) and rows (high) for all Button elements in this window
|
||||||
:param auto_size_text: True if size should fit the text length
|
:param auto_size_text: (bool) True if Elements in Window should be sized to exactly fir the length of text
|
||||||
:param auto_size_buttons:
|
:param auto_size_buttons: (bool) True if Buttons in this Window should be sized to exactly fit the text on this.
|
||||||
:param location: (Default = (None))
|
:param location: Tuple[int, int] (x,y) location, in pixels, to locate the upper left corner of the window on the screen. Default is to center on screen.
|
||||||
:param size: (w,h) w=characters-wide, h=rows-high (Default = (None))
|
:param size: Tuple[int, int] (width, height) size in pixels for this window. Normally the window is autosized to fit contents, not set to an absolute size by the user
|
||||||
:param element_padding:
|
:param element_padding: Tuple[int, int] or ((int, int),(int,int)) Default amount of padding to put around elements in window (left/right, top/bottom) or ((left, right), (top, bottom))
|
||||||
:param margins: (Default = (None))
|
:param margins: Tuple[int, int] (left/right, top/bottom) Amount of pixels to leave inside the window's frame around the edges before your elements are shown.
|
||||||
:param button_color: button color (foreground, background)
|
:param button_color: Tuple[str, str] (text color, button color) Default button colors for all buttons in the window
|
||||||
:param font: specifies the font family, size, etc
|
:param font: Union[str, tuple] specifies the font family, size. Uses one of two font specifications formats
|
||||||
:param progress_bar_color: (Default = (None))
|
:param progress_bar_color: Tuple[str, str] (bar color, background color) Sets the default colors for all progress bars in the window
|
||||||
:param background_color: color of background
|
:param background_color: (str) color of background
|
||||||
:param border_depth:
|
:param border_depth: (int) Default border depth (width) for all elements in the window
|
||||||
:param auto_close: (Default = False)
|
:param auto_close: (bool) If True, the window will automatically close itself
|
||||||
:param auto_close_duration: (Default value = DEFAULT_AUTOCLOSE_TIME)
|
:param auto_close_duration: (int) Number of seconds to wait before closing the window
|
||||||
:param icon: Icon to display. Filled in with default icon in init (Default value = None)
|
:param icon: Union[str, str] Can be either a filename or Base64 value.
|
||||||
:param force_toplevel: (Default = False)
|
:param force_toplevel: (bool) If True will cause this window to skip the normal use of a hidden master window
|
||||||
:param alpha_channel: (Default value = 1)
|
:param alpha_channel: (float) Sets the opacity of the window. 0 = invisible 1 = completely visible. Values bewteen 0 & 1 will produce semi-transparent windows in SOME environments (The Raspberry Pi always has this value at 1 and cannot change.
|
||||||
:param return_keyboard_events: (Default = False)
|
:param return_keyboard_events: (bool) if True key presses on the keyboard will be returned as Events from Read calls
|
||||||
:param use_default_focus: (Default = True)
|
:param use_default_focus: (bool) If True will use the default focus algorithm to set the focus to the "Correct" element
|
||||||
:param text_justification:
|
:param text_justification: (str) Union ['left', 'right', 'center'] Default text justification for all Text Elements in window
|
||||||
:param no_titlebar: (Default = False)
|
:param no_titlebar: (bool) If true, no titlebar nor frame will be shown on window. This means you cannot minimize the window and it will not show up on the taskbar
|
||||||
:param grab_anywhere: If True can grab anywhere to move the window (Default = False)
|
:param grab_anywhere: (bool) If True can use mouse to click and drag to move the window. Almost every location of the window will work except input fields on some systems
|
||||||
:param location: Location on screen to display
|
:param keep_on_top: (bool) If True, window will be created on top of all other windows on screen. It can be bumped down if another window created with this parm
|
||||||
:param resizable: (Default = False)
|
:param resizable: (bool) If True, allows the user to resize the window. Note the not all Elements will change size or location when resizing.
|
||||||
:param disable_close: (Default = False)
|
:param disable_close: (bool) If True, the X button in the top right corner of the window will no work. Use with caution and always give a way out toyour users
|
||||||
:param disable_minimize: (Default = False)
|
:param disable_minimize: (bool) if True the user won't be able to minimize window. Good for taking over entire screen and staying that way.
|
||||||
:param right_click_menu: List[List[str]] see "Right Click Menus" for format
|
:param right_click_menu: List[List[str]] see "Right Click Menus" for format
|
||||||
:param transparent_color:
|
:param transparent_color: (str) Any portion of the window that has this color will be completely transparent. You can even click through these spots to the window under this window.
|
||||||
:param debugger_enabled: (Default = True)
|
:param debugger_enabled: (bool) If True then the internal debugger will be enabled
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT
|
self.AutoSizeText = auto_size_text if auto_size_text is not None else DEFAULT_AUTOSIZE_TEXT
|
||||||
|
@ -4742,10 +4827,12 @@ class Window:
|
||||||
|
|
||||||
# ------------------------- Add ONE Row to Form ------------------------- #
|
# ------------------------- Add ONE Row to Form ------------------------- #
|
||||||
def AddRow(self, *args):
|
def AddRow(self, *args):
|
||||||
"""Parms are a variable number of Elements
|
"""
|
||||||
|
Adds a single row of elements to a window's self.Rows variables.
|
||||||
:param *args:
|
Generally speaking this is NOT how users should be building Window layouts.
|
||||||
|
Users, create a single layout (a list of lists) and pass as a parameter to Window object, or call Window.Layout(layout)
|
||||||
|
|
||||||
|
:param *args: List[Elements]
|
||||||
"""
|
"""
|
||||||
NumRows = len(self.Rows) # number of existing rows is our row number
|
NumRows = len(self.Rows) # number of existing rows is our row number
|
||||||
CurrentRowNumber = NumRows # this row's number
|
CurrentRowNumber = NumRows # this row's number
|
||||||
|
@ -4780,8 +4867,9 @@ class Window:
|
||||||
# ------------------------- Add Multiple Rows to Form ------------------------- #
|
# ------------------------- Add Multiple Rows to Form ------------------------- #
|
||||||
def AddRows(self, rows):
|
def AddRows(self, rows):
|
||||||
"""
|
"""
|
||||||
|
Loops through a list of lists of elements and adds each row, list, to the layout
|
||||||
|
|
||||||
:param rows:
|
:param rows: List[List[Elements]] A list of a list of elements
|
||||||
|
|
||||||
"""
|
"""
|
||||||
for row in rows:
|
for row in rows:
|
||||||
|
@ -4789,9 +4877,12 @@ class Window:
|
||||||
|
|
||||||
def Layout(self, rows):
|
def Layout(self, rows):
|
||||||
"""
|
"""
|
||||||
|
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.
|
||||||
|
|
||||||
:param rows:
|
:param rows: List[List[Elements]] Your entire layout
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.AddRows(rows)
|
self.AddRows(rows)
|
||||||
self.BuildKeyDict()
|
self.BuildKeyDict()
|
||||||
|
@ -4799,31 +4890,32 @@ class Window:
|
||||||
|
|
||||||
def LayoutAndRead(self, rows, non_blocking=False):
|
def LayoutAndRead(self, rows, non_blocking=False):
|
||||||
"""
|
"""
|
||||||
|
Deprecated. Now you layout your window's rows (layout) and then separately call Read.
|
||||||
:param rows:
|
:param rows:
|
||||||
:param non_blocking: (Default = False)
|
:param non_blocking: (Default = False)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
raise DeprecationWarning(
|
raise DeprecationWarning(
|
||||||
'LayoutAndRead is no longer supported... change your call window.Layout(layout).Read()')
|
'LayoutAndRead is no longer supported... change your call window.Layout(layout).Read()\nor window(title, layout).Read()')
|
||||||
# self.AddRows(rows)
|
# self.AddRows(rows)
|
||||||
# self.Show(non_blocking=non_blocking)
|
# self._Show(non_blocking=non_blocking)
|
||||||
# return self.ReturnValues
|
# return self.ReturnValues
|
||||||
|
|
||||||
def LayoutAndShow(self, rows):
|
def LayoutAndShow(self, rows):
|
||||||
"""
|
"""
|
||||||
|
Deprecated - do not use any longer. Layout your window and then call Read. Or can add a Finalize call before the Read
|
||||||
:param rows:
|
:param rows:
|
||||||
|
|
||||||
"""
|
"""
|
||||||
raise DeprecationWarning('LayoutAndShow is no longer supported... ')
|
raise DeprecationWarning('LayoutAndShow is no longer supported... ')
|
||||||
|
|
||||||
# ------------------------- ShowForm THIS IS IT! ------------------------- #
|
|
||||||
def Show(self, non_blocking=False):
|
def _Show(self, non_blocking=False):
|
||||||
"""
|
"""
|
||||||
|
NOT TO BE CALLED BY USERS. INTERNAL ONLY!
|
||||||
|
It's this
|
||||||
|
|
||||||
:param non_blocking: (Default = False)
|
:param non_blocking: (bool) if True, this is a non-blocking call
|
||||||
|
|
||||||
"""
|
"""
|
||||||
self.Shown = True
|
self.Shown = True
|
||||||
# Compute num rows & num cols (it'll come in handy debugging)
|
# Compute num rows & num cols (it'll come in handy debugging)
|
||||||
|
@ -4861,9 +4953,13 @@ class Window:
|
||||||
# ------------------------- SetIcon - set the window's fav icon ------------------------- #
|
# ------------------------- SetIcon - set the window's fav icon ------------------------- #
|
||||||
def SetIcon(self, icon=None, pngbase64=None):
|
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 bytes object
|
||||||
|
* a BASE64 encoded file held in a variable
|
||||||
|
|
||||||
:param icon:
|
:param icon: (str) Filename or bytes object
|
||||||
:param pngbase64:
|
:param pngbase64: (str) Base64 encoded GIF or PNG file
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if type(icon) is bytes:
|
if type(icon) is bytes:
|
||||||
|
@ -4890,21 +4986,32 @@ class Window:
|
||||||
|
|
||||||
def _GetElementAtLocation(self, location):
|
def _GetElementAtLocation(self, location):
|
||||||
"""
|
"""
|
||||||
|
Given a (row, col) location in a layout, return the element located at that position
|
||||||
|
|
||||||
:param location:
|
:param location: Tuple[int, int] Return the element located at (row, col) in layout
|
||||||
|
:return: (Element) The Element located at that position in this window
|
||||||
"""
|
"""
|
||||||
|
|
||||||
(row_num, col_num) = location
|
(row_num, col_num) = location
|
||||||
row = self.Rows[row_num]
|
row = self.Rows[row_num]
|
||||||
element = row[col_num]
|
element = row[col_num]
|
||||||
return element
|
return element
|
||||||
|
|
||||||
def _GetDefaultElementSize(self):
|
def _GetDefaultElementSize(self):
|
||||||
""" """
|
"""
|
||||||
|
Returns the default elementSize
|
||||||
|
|
||||||
|
:return: Tuple[int, int] (width, height) of the default element size
|
||||||
|
"""
|
||||||
|
|
||||||
return self.DefaultElementSize
|
return self.DefaultElementSize
|
||||||
|
|
||||||
def _AutoCloseAlarmCallback(self):
|
def _AutoCloseAlarmCallback(self):
|
||||||
""" """
|
"""
|
||||||
|
Function that's called by tkinter when autoclode timer expires. Closes the window
|
||||||
|
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
try:
|
try:
|
||||||
window = self
|
window = self
|
||||||
if window:
|
if window:
|
||||||
|
@ -4918,7 +5025,11 @@ class Window:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _TimeoutAlarmCallback(self):
|
def _TimeoutAlarmCallback(self):
|
||||||
""" """
|
"""
|
||||||
|
Read Timeout Alarm callback. Will kick a mainloop call out of the tkinter event loop and cause it to return
|
||||||
|
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
# first, get the results table built
|
# first, get the results table built
|
||||||
# modify the Results table in the parent FlexForm object
|
# modify the Results table in the parent FlexForm object
|
||||||
# print('TIMEOUT CALLBACK')
|
# print('TIMEOUT CALLBACK')
|
||||||
|
@ -4931,17 +5042,21 @@ class Window:
|
||||||
|
|
||||||
def Read(self, timeout=None, timeout_key=TIMEOUT_KEY):
|
def Read(self, timeout=None, timeout_key=TIMEOUT_KEY):
|
||||||
"""
|
"""
|
||||||
|
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.
|
||||||
|
|
||||||
:param timeout: timeout to wait, till Read will execute itself
|
:param timeout: (int) Milliseconds to wait until the Read will return IF no other GUI events happen first
|
||||||
:param timeout_key: (Default value = TIMEOUT_KEY)
|
:param 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
|
||||||
"""
|
"""
|
||||||
# ensure called only 1 time through a single read cycle
|
# ensure called only 1 time through a single read cycle
|
||||||
if not Window.read_call_from_debugger:
|
if not Window.read_call_from_debugger:
|
||||||
_refresh_debugger()
|
_refresh_debugger()
|
||||||
timeout = int(timeout) if timeout is not None else None
|
timeout = int(timeout) if timeout is not None else None
|
||||||
if timeout == 0: # timeout of zero runs the old readnonblocking
|
if timeout == 0: # timeout of zero runs the old readnonblocking
|
||||||
event, values = self.ReadNonBlocking()
|
event, values = self._ReadNonBlocking()
|
||||||
if event is None:
|
if event is None:
|
||||||
event = timeout_key
|
event = timeout_key
|
||||||
if values is None:
|
if values is None:
|
||||||
|
@ -4954,7 +5069,7 @@ class Window:
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
return None, None
|
return None, None
|
||||||
if not self.Shown:
|
if not self.Shown:
|
||||||
self.Show()
|
self._Show()
|
||||||
else:
|
else:
|
||||||
# if already have a button waiting, the return previously built results
|
# if already have a button waiting, the return previously built results
|
||||||
if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime:
|
if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime:
|
||||||
|
@ -5044,8 +5159,13 @@ class Window:
|
||||||
self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
|
self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout
|
||||||
return self.ReturnValues
|
return self.ReturnValues
|
||||||
|
|
||||||
def ReadNonBlocking(self):
|
def _ReadNonBlocking(self):
|
||||||
""" """
|
"""
|
||||||
|
Should be never called directly by the user. The user can call Window.Read(timeout=0) to get same effect
|
||||||
|
|
||||||
|
: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
|
||||||
|
"""
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
try:
|
try:
|
||||||
self.TKroot.quit()
|
self.TKroot.quit()
|
||||||
|
@ -5055,7 +5175,7 @@ class Window:
|
||||||
# print('DESTROY FAILED')
|
# print('DESTROY FAILED')
|
||||||
return None, None
|
return None, None
|
||||||
if not self.Shown:
|
if not self.Shown:
|
||||||
self.Show(non_blocking=True)
|
self._Show(non_blocking=True)
|
||||||
try:
|
try:
|
||||||
rc = self.TKroot.update()
|
rc = self.TKroot.update()
|
||||||
except:
|
except:
|
||||||
|
@ -5075,11 +5195,18 @@ class Window:
|
||||||
return BuildResults(self, False, self)
|
return BuildResults(self, False, self)
|
||||||
|
|
||||||
def Finalize(self):
|
def Finalize(self):
|
||||||
""" """
|
"""
|
||||||
|
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!
|
||||||
|
|
||||||
|
:return: (Window) Returns 'self' so that method "Chaining" can happen (read up about it as it's very cool!)
|
||||||
|
"""
|
||||||
|
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
return self
|
return self
|
||||||
if not self.Shown:
|
if not self.Shown:
|
||||||
self.Show(non_blocking=True)
|
self._Show(non_blocking=True)
|
||||||
try:
|
try:
|
||||||
rc = self.TKroot.update()
|
rc = self.TKroot.update()
|
||||||
except:
|
except:
|
||||||
|
@ -5089,8 +5216,17 @@ class Window:
|
||||||
# return None, None
|
# return None, None
|
||||||
return self
|
return self
|
||||||
|
|
||||||
|
|
||||||
def Refresh(self):
|
def Refresh(self):
|
||||||
""" """
|
"""
|
||||||
|
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
|
||||||
|
|
||||||
|
: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
|
||||||
|
"""
|
||||||
|
|
||||||
if self.TKrootDestroyed:
|
if self.TKrootDestroyed:
|
||||||
return self
|
return self
|
||||||
try:
|
try:
|
||||||
|
@ -5350,6 +5486,7 @@ class Window:
|
||||||
pass
|
pass
|
||||||
# if down to 1 window, try and destroy the hidden window, if there is one
|
# if down to 1 window, try and destroy the hidden window, if there is one
|
||||||
if Window.NumOpenWindows == 1:
|
if Window.NumOpenWindows == 1:
|
||||||
|
# print('Trying to destroy hidden')
|
||||||
try:
|
try:
|
||||||
Window.hidden_master_root.destroy()
|
Window.hidden_master_root.destroy()
|
||||||
Window.NumOpenWindows = 0 # if no hidden window, then this won't execute
|
Window.NumOpenWindows = 0 # if no hidden window, then this won't execute
|
||||||
|
@ -8122,7 +8259,6 @@ def StartupTK(my_flex_form: Window):
|
||||||
# print('Starting TK open Windows = {}'.format(ow))
|
# print('Starting TK open Windows = {}'.format(ow))
|
||||||
if ENABLE_TK_WINDOWS:
|
if ENABLE_TK_WINDOWS:
|
||||||
root = tk.Tk()
|
root = tk.Tk()
|
||||||
Window.IncrementOpenCount()
|
|
||||||
elif not ow and not my_flex_form.ForceTopLevel:
|
elif not ow and not my_flex_form.ForceTopLevel:
|
||||||
# if first window being created, make a throwaway, hidden master root. This stops one user
|
# if first window being created, make a throwaway, hidden master root. This stops one user
|
||||||
# window from becoming the child of another user window. All windows are children of this
|
# window from becoming the child of another user window. All windows are children of this
|
||||||
|
@ -10127,6 +10263,9 @@ class _Debugger():
|
||||||
try:
|
try:
|
||||||
result = eval('{}'.format(cmd), myglobals, mylocals)
|
result = eval('{}'.format(cmd), myglobals, mylocals)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if sys.version_info[0] < 3:
|
||||||
|
result = 'Not available in Python 2'
|
||||||
|
else:
|
||||||
try:
|
try:
|
||||||
result = exec('{}'.format(cmd), myglobals, mylocals)
|
result = exec('{}'.format(cmd), myglobals, mylocals)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
Loading…
Reference in New Issue