From d16b55d437a721d6dcb0e26e1f6ad594d0c27eb2 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <13696193+MikeTheWatchGuy@users.noreply.github.com> Date: Tue, 2 Apr 2019 19:18:58 -0400 Subject: [PATCH 1/4] docs/cookbook.md updated from https://stackedit.io/ --- docs/cookbook.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/cookbook.md b/docs/cookbook.md index 1d28c70f..7b96c8c1 100644 --- a/docs/cookbook.md +++ b/docs/cookbook.md @@ -925,8 +925,7 @@ There are a number of features used in this Recipe including: * Button * Dictionary Return values * Update of Elements in window (Input, Text) -* do_not_clear of Input Elements - + ![keypad 2](https://user-images.githubusercontent.com/13696193/44640891-57504d80-a992-11e8-93f4-4e97e586505e.jpg) @@ -1550,8 +1549,9 @@ That's all... Run your `my_program.exe` file on the Windows machine of your choo Your EXE file should run without creating a "shell window". Only the GUI window should show up on your taskbar. \ No newline at end of file From 2d3d53c062080896a028aade22b55b386a9153eb Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <13696193+MikeTheWatchGuy@users.noreply.github.com> Date: Tue, 2 Apr 2019 19:37:05 -0400 Subject: [PATCH 2/4] docs/cookbook.md updated from https://stackedit.io/ --- docs/cookbook.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/cookbook.md b/docs/cookbook.md index 7b96c8c1..e20467d7 100644 --- a/docs/cookbook.md +++ b/docs/cookbook.md @@ -124,7 +124,7 @@ while True: # Event Loop window.Close() ``` - + # Simple Data Entry - Return Values As List @@ -1549,9 +1549,9 @@ That's all... Run your `my_program.exe` file on the Windows machine of your choo Your EXE file should run without creating a "shell window". Only the GUI window should show up on your taskbar. \ No newline at end of file From f6cb9ca430977864e08a74371fcae2932a96ecf8 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy <13696193+MikeTheWatchGuy@users.noreply.github.com> Date: Tue, 2 Apr 2019 19:38:39 -0400 Subject: [PATCH 3/4] docs/cookbook.md updated from https://stackedit.io/ --- docs/cookbook.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/cookbook.md b/docs/cookbook.md index e20467d7..9bff6667 100644 --- a/docs/cookbook.md +++ b/docs/cookbook.md @@ -124,7 +124,7 @@ while True: # Event Loop window.Close() ``` - + # Simple Data Entry - Return Values As List @@ -1549,9 +1549,9 @@ That's all... Run your `my_program.exe` file on the Windows machine of your choo Your EXE file should run without creating a "shell window". Only the GUI window should show up on your taskbar. \ No newline at end of file From 7190c4639abafd3d10a4dc7b0b73f808aaf1d6a8 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Thu, 4 Apr 2019 09:38:24 -0400 Subject: [PATCH 4/4] Removed port from GitHub as it's not usable yet --- PySimpleGUIKivy/PySimpleGUIKivy.py | 6310 ---------------------------- 1 file changed, 6310 deletions(-) delete mode 100644 PySimpleGUIKivy/PySimpleGUIKivy.py diff --git a/PySimpleGUIKivy/PySimpleGUIKivy.py b/PySimpleGUIKivy/PySimpleGUIKivy.py deleted file mode 100644 index cc8ccf87..00000000 --- a/PySimpleGUIKivy/PySimpleGUIKivy.py +++ /dev/null @@ -1,6310 +0,0 @@ -#!/usr/bin/python3 -import sys -import types -import datetime -import textwrap -import pickle -import calendar - -from kivy.app import App as kvApp -from kivy.uix.label import Label as kvLabel -from kivy.uix.textinput import TextInput as kvTextInput -from kivy.uix.button import Button as kvButton -from kivy.core.window import Window as kvWindow - -from kivy.uix.stacklayout import StackLayout -from kivy.uix.boxlayout import BoxLayout as kvBoxLayout -from kivy.uix.gridlayout import GridLayout as kvGridLayout -from kivy.uix.anchorlayout import AnchorLayout as kvAnchorLayout -from kivy.uix.floatlayout import FloatLayout as kvFloatLayout -from kivy.uix.relativelayout import RelativeLayout as kvRelativeLayout -from kivy.graphics import Rectangle, Color -from kivy.uix.widget import Widget as kvWidget - -from kivy.utils import get_color_from_hex - -from kivy.config import Config as kvConfig - - -g_time_start = 0 -g_time_end = 0 -g_time_delta = 0 - -import time - - -def TimerStart(): - global g_time_start - - g_time_start = time.time() - - -def TimerStop(): - global g_time_delta, g_time_end - - g_time_end = time.time() - g_time_delta = g_time_end - g_time_start - print(g_time_delta) - - -""" - Welcome to the "core" PySimpleGUI code.... - - It's a mess.... really... it's a mess internally... it's the external-facing interfaces that - are not a mess. The Elements and the methods for them are well-designed. - PEP8 - this code is far far from PEP8 compliant. - It was written PRIOR to learning that PEP8 existed. - - The variable and function naming in particular are not compliant. There is - liberal use of CamelVariableAndFunctionNames. If you've got a serious enough problem with this - that you'll pass on this package, then that's your right and I invite you to do so. However, if - perhaps you're a practical thinker where it's the results that matter, then you'll have no - trouble with this code base. There is consisency however. - - I truly hope you get a lot of enjoyment out of using PySimpleGUI. It came from good intentions. -""" - -# ----====----====----==== Constants the user CAN safely change ====----====----====----# -DEFAULT_WINDOW_ICON = 'default_icon.ico' -DEFAULT_ELEMENT_SIZE = (45, 1) # In CHARACTERS -DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS -DEFAULT_MARGINS = (10, 5) # Margins for each LEFT/RIGHT margin is first term -DEFAULT_ELEMENT_PADDING = (5, 3) # Padding between elements (row, col) in pixels -DEFAULT_AUTOSIZE_TEXT = True -DEFAULT_AUTOSIZE_BUTTONS = True -DEFAULT_FONT = ("Helvetica", 10) -DEFAULT_TEXT_JUSTIFICATION = 'left' -DEFAULT_BORDER_WIDTH = 1 -DEFAULT_AUTOCLOSE_TIME = 3 # time in seconds to show an autoclose form -DEFAULT_DEBUG_WINDOW_SIZE = (80, 20) -DEFAULT_WINDOW_LOCATION = (None, None) -MAX_SCROLLED_TEXT_BOX_HEIGHT = 50 -DEFAULT_TOOLTIP_TIME = 400 -#################### COLOR STUFF #################### -BLUES = ("#082567", "#0A37A3", "#00345B") -PURPLES = ("#480656", "#4F2398", "#380474") -GREENS = ("#01826B", "#40A860", "#96D2AB", "#00A949", "#003532") -YELLOWS = ("#F3FB62", "#F0F595") -TANS = ("#FFF9D5", "#F4EFCF", "#DDD8BA") -NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), - ('#000000', '#FFFFFF'), - ('#FFFFFF', '#000000'), - (YELLOWS[0], PURPLES[1]), - (YELLOWS[0], GREENS[3]), - (YELLOWS[0], BLUES[2])) - -COLOR_SYSTEM_DEFAULT = '1234567890' # Colors should never be this long -if sys.platform == 'darwin': - DEFAULT_BUTTON_COLOR = COLOR_SYSTEM_DEFAULT # Foreground, Background (None, None) == System Default - OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = COLOR_SYSTEM_DEFAULT # Colors should never be this long -else: - DEFAULT_BUTTON_COLOR = ('#FFFFFF', BLUES[0]) # Foreground, Background (None, None) == System Default - OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('#FFFFFF', BLUES[0]) # Colors should never be this long - -DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") -DEFAULT_BACKGROUND_COLOR = None -DEFAULT_ELEMENT_BACKGROUND_COLOR = None -DEFAULT_ELEMENT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT -DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = None -DEFAULT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT -DEFAULT_INPUT_ELEMENTS_COLOR = COLOR_SYSTEM_DEFAULT -DEFAULT_INPUT_TEXT_COLOR = COLOR_SYSTEM_DEFAULT -DEFAULT_SCROLLBAR_COLOR = None -# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[0]) # (Text, Background) or (Color "on", Color) as a way to remember -# DEFAULT_BUTTON_COLOR = (GREENS[3], TANS[0]) # Foreground, Background (None, None) == System Default -# DEFAULT_BUTTON_COLOR = (YELLOWS[0], GREENS[4]) # Foreground, Background (None, None) == System Default -# DEFAULT_BUTTON_COLOR = ('white', 'black') # Foreground, Background (None, None) == System Default -# DEFAULT_BUTTON_COLOR = (YELLOWS[0], PURPLES[2]) # Foreground, Background (None, None) == System Default -# DEFAULT_PROGRESS_BAR_COLOR = (GREENS[2], GREENS[0]) # a nice green progress bar -# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[1], BLUES[1]) # a nice green progress bar -# DEFAULT_PROGRESS_BAR_COLOR = (BLUES[0], BLUES[0]) # a nice green progress bar -# DEFAULT_PROGRESS_BAR_COLOR = (PURPLES[1],PURPLES[0]) # a nice purple progress bar - -# A transparent button is simply one that matches the background -TRANSPARENT_BUTTON = ('#F0F0F0', '#F0F0F0') -# -------------------------------------------------------------------------------- -# Progress Bar Relief Choices -RELIEF_RAISED = 'raised' -RELIEF_SUNKEN = 'sunken' -RELIEF_FLAT = 'flat' -RELIEF_RIDGE = 'ridge' -RELIEF_GROOVE = 'groove' -RELIEF_SOLID = 'solid' - -DEFAULT_PROGRESS_BAR_COLOR = (GREENS[0], '#D0D0D0') # a nice green progress bar -DEFAULT_PROGRESS_BAR_SIZE = (25, 20) # Size of Progress Bar (characters for length, pixels for width) -DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 -DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE -PROGRESS_BAR_STYLES = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative') -DEFAULT_PROGRESS_BAR_STYLE = 'default' -DEFAULT_METER_ORIENTATION = 'Horizontal' -DEFAULT_SLIDER_ORIENTATION = 'vertical' -DEFAULT_SLIDER_BORDER_WIDTH = 1 -DEFAULT_SLIDER_RELIEF = 00000 -DEFAULT_FRAME_RELIEF = 00000 - -DEFAULT_LISTBOX_SELECT_MODE = 00000 -SELECT_MODE_MULTIPLE = 00000 -LISTBOX_SELECT_MODE_MULTIPLE = 'multiple' -SELECT_MODE_BROWSE = 00000 -LISTBOX_SELECT_MODE_BROWSE = 'browse' -SELECT_MODE_EXTENDED =00000 -LISTBOX_SELECT_MODE_EXTENDED = 'extended' -SELECT_MODE_SINGLE = 00000 -LISTBOX_SELECT_MODE_SINGLE = 'single' - -TABLE_SELECT_MODE_NONE = 00000 -TABLE_SELECT_MODE_BROWSE = 00000 -TABLE_SELECT_MODE_EXTENDED = 00000 -DEFAULT_TABLE_SECECT_MODE = TABLE_SELECT_MODE_EXTENDED - -TITLE_LOCATION_TOP = 00000 -TITLE_LOCATION_BOTTOM = 00000 -TITLE_LOCATION_LEFT = 00000 -TITLE_LOCATION_RIGHT = 00000 -TITLE_LOCATION_TOP_LEFT = 00000 -TITLE_LOCATION_TOP_RIGHT = 00000 -TITLE_LOCATION_BOTTOM_LEFT = 00000 -TITLE_LOCATION_BOTTOM_RIGHT = 00000 - -THEME_DEFAULT = 'default' -THEME_WINNATIVE = 'winnative' -THEME_CLAM = 'clam' -THEME_ALT = 'alt' -THEME_CLASSIC = 'classic' -THEME_VISTA = 'vista' -THEME_XPNATIVE = 'xpnative' - -# DEFAULT_METER_ORIENTATION = 'Vertical' -# ----====----====----==== Constants the user should NOT f-with ====----====----====----# -ThisRow = 555666777 # magic number - -# DEFAULT_WINDOW_ICON = '' -MESSAGE_BOX_LINE_WIDTH = 60 - -# "Special" Key Values.. reserved -# Key representing a Read timeout -TIMEOUT_KEY = '__TIMEOUT__' -# Key indicating should not create any return values for element -WRITE_ONLY_KEY = '__WRITE ONLY__' - - -# a shameful global variable. This represents the top-level window information. Needed because opening a second window is different than opening the first. -class MyWindows(): - def __init__(self): - self.NumOpenWindows = 0 - self.user_defined_icon = None - self.hidden_master_root = None - - def Decrement(self): - self.NumOpenWindows -= 1 * (self.NumOpenWindows != 0) # decrement if not 0 - # print('---- DECREMENTING Num Open Windows = {} ---'.format(self.NumOpenWindows)) - - def Increment(self): - self.NumOpenWindows += 1 - # print('++++ INCREMENTING Num Open Windows = {} ++++'.format(self.NumOpenWindows)) - - -_my_windows = MyWindows() # terrible hack using globals... means need a class for collecing windows - - -# ====================================================================== # -# One-liner functions that are handy as f_ck # -# ====================================================================== # -def RGB(red, green, blue): return '#%02x%02x%02x' % (red, green, blue) - - -# ====================================================================== # -# Enums for types # -# ====================================================================== # -# ------------------------- Button types ------------------------- # -# todo Consider removing the Submit, Cancel types... they are just 'RETURN' type in reality -# uncomment this line and indent to go back to using Enums -# class ButtonType(Enum): -BUTTON_TYPE_BROWSE_FOLDER = 1 -BUTTON_TYPE_BROWSE_FILE = 2 -BUTTON_TYPE_BROWSE_FILES = 21 -BUTTON_TYPE_SAVEAS_FILE = 3 -BUTTON_TYPE_CLOSES_WIN = 5 -BUTTON_TYPE_CLOSES_WIN_ONLY = 6 -BUTTON_TYPE_READ_FORM = 7 -BUTTON_TYPE_REALTIME = 9 -BUTTON_TYPE_CALENDAR_CHOOSER = 30 -BUTTON_TYPE_COLOR_CHOOSER = 40 - -# ------------------------- Element types ------------------------- # -# class ElementType(Enum): -ELEM_TYPE_TEXT = 'text' -ELEM_TYPE_INPUT_TEXT = 'input' -ELEM_TYPE_INPUT_COMBO = 'combo' -ELEM_TYPE_INPUT_OPTION_MENU = 'option menu' -ELEM_TYPE_INPUT_RADIO = 'radio' -ELEM_TYPE_INPUT_MULTILINE = 'multiline' -ELEM_TYPE_MULTILINE_OUTPUT = 'multioutput' -ELEM_TYPE_INPUT_CHECKBOX = 'checkbox' -ELEM_TYPE_INPUT_SPIN = 'spind' -ELEM_TYPE_BUTTON = 'button' -ELEM_TYPE_IMAGE = 'image' -ELEM_TYPE_CANVAS = 'canvas' -ELEM_TYPE_FRAME = 'frame' -ELEM_TYPE_GRAPH = 'graph' -ELEM_TYPE_TAB = 'tab' -ELEM_TYPE_TAB_GROUP = 'tabgroup' -ELEM_TYPE_INPUT_SLIDER = 'slider' -ELEM_TYPE_INPUT_DIAL = 'dial' -ELEM_TYPE_INPUT_LISTBOX = 'listbox' -ELEM_TYPE_OUTPUT = 'output' -ELEM_TYPE_COLUMN = 'column' -ELEM_TYPE_MENUBAR = 'menubar' -ELEM_TYPE_PROGRESS_BAR = 'progressbar' -ELEM_TYPE_BLANK = 'blank' -ELEM_TYPE_TABLE = 'table' -ELEM_TYPE_TREE = 'tree' -ELEM_TYPE_ERROR = 'error' -ELEM_TYPE_SEPARATOR = 'separator' -ELEM_TYPE_STRETCH = 'stretch' -ELEM_TYPE_BUTTONMENU = 'buttonmenu' - -# ------------------------- Popup Buttons Types ------------------------- # -POPUP_BUTTONS_YES_NO = 1 -POPUP_BUTTONS_CANCELLED = 2 -POPUP_BUTTONS_ERROR = 3 -POPUP_BUTTONS_OK_CANCEL = 4 -POPUP_BUTTONS_OK = 0 -POPUP_BUTTONS_NO_BUTTONS = 5 - - -# ------------------------------------------------------------------------- # -# ToolTip used by the Elements # -# ------------------------------------------------------------------------- # - -class ToolTip: - """ Create a tooltip for a given widget - - (inspired by https://stackoverflow.com/a/36221216) - """ - - def __init__(self, widget, text, timeout=DEFAULT_TOOLTIP_TIME): - self.widget = widget - self.text = text - self.timeout = timeout - # self.wraplength = wraplength if wraplength else widget.winfo_screenwidth() // 2 - self.tipwindow = None - self.id = None - self.x = self.y = 0 - self.widget.bind("", self.enter) - self.widget.bind("", self.leave) - self.widget.bind("", self.leave) - - def enter(self, event=None): - self.schedule() - - def leave(self, event=None): - self.unschedule() - self.hidetip() - - def schedule(self): - self.unschedule() - self.id = self.widget.after(self.timeout, self.showtip) - - def unschedule(self): - if self.id: - self.widget.after_cancel(self.id) - self.id = None - - def showtip(self): - if self.tipwindow: - return - x = self.widget.winfo_rootx() + 20 - y = self.widget.winfo_rooty() + self.widget.winfo_height() - 20 - self.tipwindow = tk.Toplevel(self.widget) - self.tipwindow.wm_overrideredirect(True) - self.tipwindow.wm_geometry("+%d+%d" % (x, y)) - label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT, - background="#ffffe0", relief=tk.SOLID, borderwidth=1) - label.pack() - - def hidetip(self): - if self.tipwindow: - self.tipwindow.destroy() - self.tipwindow = None - - -# ---------------------------------------------------------------------- # -# Cascading structure.... Objects get larger # -# Button # -# Element # -# Row # -# Form # -# ---------------------------------------------------------------------- # -# ------------------------------------------------------------------------- # -# Element CLASS # -# ------------------------------------------------------------------------- # -class Element(): - 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): - self.Size = size - self.Type = type - self.AutoSizeText = auto_size_text - self.Pad = DEFAULT_ELEMENT_PADDING if pad is None else pad - self.Font = font - - self.TKStringVar = None - self.TKIntVar = None - self.TKText = None - self.TKEntry = None - self.TKImage = None - - self.ParentForm = None - self.ParentContainer = None # will be a Form, Column, or Frame element - self.TextInputDefault = None - self.Position = (0, 0) # Default position Row 0, Col 0 - self.BackgroundColor = background_color if background_color is not None else DEFAULT_ELEMENT_BACKGROUND_COLOR - self.TextColor = text_color if text_color is not None else DEFAULT_ELEMENT_TEXT_COLOR - self.Key = key # dictionary key for return values - self.Tooltip = tooltip - self.TooltipObject = None - - def FindReturnKeyBoundButton(self, form): - for row in form.Rows: - for element in row: - if element.Type == ELEM_TYPE_BUTTON: - if element.BindReturnKey: - return element - if element.Type == ELEM_TYPE_COLUMN: - rc = self.FindReturnKeyBoundButton(element) - if rc is not None: - return rc - if element.Type == ELEM_TYPE_FRAME: - rc = self.FindReturnKeyBoundButton(element) - if rc is not None: - return rc - if element.Type == ELEM_TYPE_TAB_GROUP: - rc = self.FindReturnKeyBoundButton(element) - if rc is not None: - return rc - if element.Type == ELEM_TYPE_TAB: - rc = self.FindReturnKeyBoundButton(element) - if rc is not None: - return rc - return None - - def TextClickedHandler(self, event): - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = self.DisplayText - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - pass # TODO kick users out of mainloop .quit - - def ReturnKeyHandler(self, event): - MyForm = self.ParentForm - button_element = self.FindReturnKeyBoundButton(MyForm) - if button_element is not None: - button_element.ButtonCallBack() - - def ListboxSelectHandler(self, event): - # first, get the results table built - # modify the Results table in the parent FlexForm object - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick the users out of the mainloop - - def ComboboxSelectHandler(self, event): - # first, get the results table built - # modify the Results table in the parent FlexForm object - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - pass # TODO kick users out of mainloop .quit - - def RadioHandler(self): - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - pass # TODO kick users out of mainloop .quit - - def CheckboxHandler(self): - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - pass # TODO kick users out of mainloop .quit - - def TabGroupSelectHandler(self, event): - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - pass # TODO kick users out of mainloop .quit - - def KeyboardHandler(self, event): - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - pass # TODO kick users out of mainloop .quit - - def __del__(self): - pass - -# ---------------------------------------------------------------------- # -# Input Class # -# ---------------------------------------------------------------------- # -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, - do_not_clear=False, key=None, focus=False, pad=None): - ''' - Input a line of text Element - :param default_text: Default value to display - :param size: Size of field in characters - :param password_char: If non-blank, will display this character for every character typed - :param background_color: Color for Element. Text or RGB Hex - ''' - self.DefaultText = default_text - self.PasswordCharacter = password_char - bg = background_color if background_color is not None else DEFAULT_INPUT_ELEMENTS_COLOR - fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR - self.Focus = focus - self.do_not_clear = do_not_clear - self.Justification = justification - self.Disabled = disabled - self.ChangeSubmits = change_submits - super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad, - font=font, tooltip=tooltip) - - def Update(self, value=None, disabled=None): - if disabled is True: - self.TKEntry['state'] = 'disabled' - elif disabled is False: - self.TKEntry['state'] = 'normal' - if value is not None: - try: - self.TKStringVar.set(value) - except: - pass - self.DefaultText = value - - def Get(self): - return self.TKStringVar.get() - - def SetFocus(self): - try: - self.TKEntry.focus_set() - except: - pass - - def __del__(self): - super().__del__() - - -# ------------------------- INPUT TEXT Element lazy functions ------------------------- # -In = InputText -Input = InputText - - -# ---------------------------------------------------------------------- # -# Combo # -# ---------------------------------------------------------------------- # -class InputCombo(Element): - def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None, - text_color=None, change_submits=False, disabled=False, key=None, pad=None, tooltip=None, - readonly=False, font=None): - ''' - Input Combo Box Element (also called Dropdown box) - :param values: - :param size: Size of field in characters - :param auto_size_text: True if should shrink field to fit the default text - :param background_color: Color for Element. Text or RGB Hex - ''' - self.Values = values - self.DefaultValue = default_value - self.ChangeSubmits = change_submits - self.TKCombo = None - # self.InitializeAsDisabled = disabled - self.Disabled = disabled - self.Readonly = readonly - bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR - 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) - - def Update(self, value=None, values=None, set_to_index=None, disabled=None, readonly=None, font=None): - if values is not None: - try: - self.TKCombo['values'] = values - self.TKCombo.current(0) - except: - pass - self.Values = values - if value is not None: - for index, v in enumerate(self.Values): - if v == value: - try: - self.TKCombo.current(index) - except: - pass - self.DefaultValue = value - break - if set_to_index is not None: - try: - self.TKCombo.current(set_to_index) - self.DefaultValue = self.Values[set_to_index] - except: - pass - if disabled == True: - self.TKCombo['state'] = 'disable' - elif disabled == False: - self.TKCombo['state'] = 'enable' - if readonly is not None: - self.Readonly = readonly - if self.Readonly: - self.TKCombo['state'] = 'readonly' - if font is not None: - self.TKText.configure(font=font) - - def __del__(self): - try: - self.TKCombo.__del__() - except: - pass - super().__del__() - - -# ------------------------- INPUT COMBO Element lazy functions ------------------------- # -Combo = InputCombo -DropDown = InputCombo -Drop = InputCombo - - -# ---------------------------------------------------------------------- # -# Option Menu # -# ---------------------------------------------------------------------- # -class OptionMenu(Element): - 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): - ''' - InputOptionMenu - :param values: - :param default_value: - :param size: - :param disabled: - :param auto_size_text: - :param background_color: - :param text_color: - :param key: - :param pad: - :param tooltip: - ''' - self.Values = values - self.DefaultValue = default_value - self.TKOptionMenu = None - self.Disabled = disabled - bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR - 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) - - def Update(self, value=None, values=None, disabled=None): - if values is not None: - self.Values = values - if self.Values is not None: - for index, v in enumerate(self.Values): - if v == value: - try: - self.TKStringVar.set(value) - except: - pass - self.DefaultValue = value - break - if disabled == True: - self.TKOptionMenu['state'] = 'disabled' - elif disabled == False: - self.TKOptionMenu['state'] = 'normal' - - def __del__(self): - try: - self.TKOptionMenu.__del__() - except: - pass - super().__del__() - - -# ------------------------- OPTION MENU Element lazy functions ------------------------- # -InputOptionMenu = OptionMenu - - -# ---------------------------------------------------------------------- # -# Listbox # -# ---------------------------------------------------------------------- # -class Listbox(Element): - def __init__(self, values, default_values=None, select_mode=None, change_submits=False, bind_return_key=False, - size=(None, None), disabled=False, auto_size_text=None, font=None, background_color=None, - text_color=None, key=None, pad=None, tooltip=None): - ''' - Listbox Element - :param values: - :param default_values: - :param select_mode: - :param change_submits: - :param bind_return_key: - :param size: - :param disabled: - :param auto_size_text: - :param font: - :param background_color: - :param text_color: - :param key: - :param pad: - :param tooltip: - ''' - self.Values = values - self.DefaultValues = default_values - self.TKListbox = None - self.ChangeSubmits = change_submits - self.BindReturnKey = bind_return_key - self.Disabled = disabled - if select_mode == LISTBOX_SELECT_MODE_BROWSE: - self.SelectMode = SELECT_MODE_BROWSE - elif select_mode == LISTBOX_SELECT_MODE_EXTENDED: - self.SelectMode = SELECT_MODE_EXTENDED - elif select_mode == LISTBOX_SELECT_MODE_MULTIPLE: - self.SelectMode = SELECT_MODE_MULTIPLE - elif select_mode == LISTBOX_SELECT_MODE_SINGLE: - self.SelectMode = SELECT_MODE_SINGLE - else: - self.SelectMode = DEFAULT_LISTBOX_SELECT_MODE - bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR - fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR - - 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) - - def Update(self, values=None, disabled=None): - if disabled == True: - self.TKListbox.configure(state='disabled') - elif disabled == False: - self.TKListbox.configure(state='normal') - if values is not None: - self.TKListbox.delete(0, 'end') - for item in values: - self.TKListbox.insert(tk.END, item) - self.TKListbox.selection_set(0, 0) - self.Values = values - - def SetValue(self, values): - for index, item in enumerate(self.Values): - try: - if item in values: - self.TKListbox.selection_set(index) - else: - self.TKListbox.selection_clear(index) - except: - pass - self.DefaultValues = values - - def GetListValues(self): - return self.Values - - def __del__(self): - try: - self.TKListBox.__del__() - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# Radio # -# ---------------------------------------------------------------------- # -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): - ''' - Radio Button Element - :param text: - :param group_id: - :param default: - :param disabled: - :param size: - :param auto_size_text: - :param background_color: - :param text_color: - :param font: - :param key: - :param pad: - :param tooltip: - :param change_submits: - ''' - self.InitialState = default - self.Text = text - self.TKRadio = None - self.GroupID = group_id - self.Value = None - self.Disabled = disabled - self.TextColor = text_color or DEFAULT_TEXT_COLOR - self.ChangeSubmits = change_submits - - 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) - - def Update(self, value=None, disabled=None): - location = EncodeRadioRowCol(self.Position[0], self.Position[1]) - if value is not None: - try: - self.TKIntVar.set(location) - except: - pass - self.InitialState = value - if disabled == True: - self.TKRadio['state'] = 'disabled' - elif disabled == False: - self.TKRadio['state'] = 'normal' - - def __del__(self): - try: - self.TKRadio.__del__() - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# Checkbox # -# ---------------------------------------------------------------------- # -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, disabled=False, key=None, pad=None, tooltip=None): - ''' - Checkbox Element - :param text: - :param default: - :param size: - :param auto_size_text: - :param font: - :param background_color: - :param text_color: - :param change_submits: - :param disabled: - :param key: - :param pad: - :param tooltip: - ''' - self.Text = text - self.InitialState = default - self.Value = None - self.TKCheckbutton = None - self.Disabled = disabled - self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR - self.ChangeSubmits = change_submits - - 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) - - def Get(self): - return self.TKIntVar.get() - - def Update(self, value=None, disabled=None): - if value is not None: - try: - self.TKIntVar.set(value) - self.InitialState = value - except: - pass - if disabled == True: - self.TKCheckbutton.configure(state='disabled') - elif disabled == False: - self.TKCheckbutton.configure(state='normal') - - def __del__(self): - super().__del__() - - -# ------------------------- CHECKBOX Element lazy functions ------------------------- # -CB = Checkbox -CBox = Checkbox -Check = Checkbox - - -# ---------------------------------------------------------------------- # -# Spin # -# ---------------------------------------------------------------------- # - -class Spin(Element): - # Values = None - # TKSpinBox = None - def __init__(self, values, initial_value=None, disabled=False, change_submits=False, size=(None, None), - auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, - tooltip=None): - ''' - Spinner Element - :param values: - :param initial_value: - :param disabled: - :param change_submits: - :param size: - :param auto_size_text: - :param font: - :param background_color: - :param text_color: - :param key: - :param pad: - :param tooltip: - ''' - self.Values = values - self.DefaultValue = initial_value - self.ChangeSubmits = change_submits - self.TKSpinBox = None - self.Disabled = disabled - bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR - 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) - return - - def Update(self, value=None, values=None, disabled=None): - if values != None: - old_value = self.TKStringVar.get() - self.Values = values - self.TKSpinBox.configure(values=values) - self.TKStringVar.set(old_value) - if value is not None: - try: - self.TKStringVar.set(value) - except: - pass - self.DefaultValue = value - if disabled == True: - self.TKSpinBox.configure(state='disabled') - elif disabled == False: - self.TKSpinBox.configure(state='normal') - - def SpinChangedHandler(self, event): - # first, get the results table built - # modify the Results table in the parent FlexForm object - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick the users out of the mainloop - - def __del__(self): - try: - self.TKSpinBox.__del__() - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# Multiline # -# ---------------------------------------------------------------------- # -class Multiline(Element): - def __init__(self, default_text='', enter_submits=False, disabled=False, autoscroll=False, size=(None, None), - auto_size_text=None, background_color=None, text_color=None, change_submits=False, do_not_clear=False, - key=None, focus=False, - font=None, pad=None, tooltip=None): - ''' - Multiline Element - :param default_text: - :param enter_submits: - :param disabled: - :param autoscroll: - :param size: - :param auto_size_text: - :param background_color: - :param text_color: - :param do_not_clear: - :param key: - :param focus: - :param pad: - :param tooltip: - :param font: - ''' - self.DefaultText = default_text - self.EnterSubmits = enter_submits - bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR - self.Focus = focus - self.do_not_clear = do_not_clear - fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR - self.Autoscroll = autoscroll - self.Disabled = disabled - self.ChangeSubmits = change_submits - - 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) - return - - def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None): - if value is not None: - try: - if not append: - self.TKText.delete('1.0', tk.END) - self.TKText.insert(tk.END, value) - except: - pass - self.DefaultText = value - if self.Autoscroll: - self.TKText.see(tk.END) - if disabled == True: - self.TKText.configure(state='disabled') - elif disabled == False: - self.TKText.configure(state='normal') - if background_color is not None: - self.TKText.configure(background=background_color) - if text_color is not None: - self.TKText.configure(fg=text_color) - if font is not None: - self.TKText.configure(font=font) - - def Get(self): - return self.TKText.get(1.0, tk.END) - - def SetFocus(self): - try: - self.TKText.focus_set() - except: - pass - - def __del__(self): - super().__del__() - - -# ---------------------------------------------------------------------- # -# Text # -# ---------------------------------------------------------------------- # -class Text(Element): - def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, relief=None, font=None, - text_color=None, background_color=None, justification=None, pad=None, key=None, tooltip=None): - ''' - Text Element - :param text: - :param size: - :param auto_size_text: - :param click_submits: - :param relief: - :param font: - :param text_color: - :param background_color: - :param justification: - :param pad: - :param key: - :param tooltip: - ''' - self.DisplayText = text - self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR - self.Justification = justification - self.Relief = relief - self.ClickSubmits = click_submits - if background_color is None: - bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR - else: - bg = background_color - 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) - return - - def Update(self, value=None, background_color=None, text_color=None, font=None): - if value is not None: - self.DisplayText = value - stringvar = self.TKStringVar - stringvar.set(value) - if background_color is not None: - self.TKText.configure(background=background_color) - if text_color is not None: - self.TKText.configure(fg=text_color) - if font is not None: - self.TKText.configure(font=font) - - def __del__(self): - super().__del__() - - -# ------------------------- Text Element lazy functions ------------------------- # -Txt = Text -T = Text - - -# ---------------------------------------------------------------------- # -# TKProgressBar # -# Emulate the TK ProgressBar using canvas and rectangles -# ---------------------------------------------------------------------- # - -class TKProgressBar(): - def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], style=DEFAULT_PROGRESS_BAR_STYLE, - relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH, - orientation='horizontal', BarColor=(None, None), key=None): - self.Length = length - self.Width = width - self.Max = max - self.Orientation = orientation - self.Count = None - self.PriorCount = 0 - - if orientation[0].lower() == 'h': - s = ttk.Style() - s.theme_use(style) - if BarColor != COLOR_SYSTEM_DEFAULT: - s.configure(str(key) + "my.Horizontal.TProgressbar", background=BarColor[0], troughcolor=BarColor[1], - troughrelief=relief, borderwidth=border_width, thickness=width) - else: - s.configure(str(key) + "my.Horizontal.TProgressbar", troughrelief=relief, borderwidth=border_width, - thickness=width) - - self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max, - style=str(key) + 'my.Horizontal.TProgressbar', length=length, - orient=tk.HORIZONTAL, mode='determinate') - else: - s = ttk.Style() - s.theme_use(style) - if BarColor != COLOR_SYSTEM_DEFAULT: - s.configure(str(length) + str(width) + "my.Vertical.TProgressbar", background=BarColor[0], - troughcolor=BarColor[1], troughrelief=relief, borderwidth=border_width, thickness=width) - else: - s.configure(str(length) + str(width) + "my.Vertical.TProgressbar", troughrelief=relief, - borderwidth=border_width, thickness=width) - self.TKProgressBarForReal = ttk.Progressbar(root, maximum=self.Max, - style=str(length) + str(width) + 'my.Vertical.TProgressbar', - length=length, orient=tk.VERTICAL, mode='determinate') - - def Update(self, count=None, max=None): - if max is not None: - self.Max = max - try: - self.TKProgressBarForReal.config(maximum=max) - except: - return False - if count is not None and count > self.Max: return False - if count is not None: - try: - self.TKProgressBarForReal['value'] = count - except: - return False - return True - - def __del__(self): - try: - self.TKProgressBarForReal.__del__() - except: - pass - - -# ---------------------------------------------------------------------- # -# TKOutput # -# New Type of TK Widget that's a Text Widget in disguise # -# Note that it's inherited from the TKFrame class so that the # -# Scroll bar will span the length of the frame # -# ---------------------------------------------------------------------- # -class TKOutput(): - def __init__(self, parent, width, height, bd, background_color=None, text_color=None, font=None, pad=None): - self.previous_stdout = sys.stdout - self.previous_stderr = sys.stderr - - sys.stdout = self - sys.stderr = self - - def write(self, txt): - pass - - def Close(self): - sys.stdout = self.previous_stdout - sys.stderr = self.previous_stderr - - def flush(self): - sys.stdout = self.previous_stdout - sys.stderr = self.previous_stderr - - def __del__(self): - sys.stdout = self.previous_stdout - sys.stderr = self.previous_stderr - - -# ---------------------------------------------------------------------- # -# Output # -# Routes stdout, stderr to a scrolled window # -# ---------------------------------------------------------------------- # -class Output(Element): - def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None, - key=None): - ''' - Output Element - :param size: - :param background_color: - :param text_color: - :param pad: - :param font: - :param tooltip: - :param key: - ''' - self._TKOut = None - bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR - fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR - - super().__init__(ELEM_TYPE_OUTPUT, size=size, background_color=bg, text_color=fg, pad=pad, font=font, - tooltip=tooltip, key=key) - - @property - def TKOut(self): - if self._TKOut is None: - print('*** Did you forget to call Finalize()? Your code should look something like: ***') - print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') - return self._TKOut - - def Update(self, value=None): - if value is not None: - # try: - self._TKOut.output.delete('1.0', tk.END) - self._TKOut.output.insert(tk.END, value) - # except: - # pass - - def __del__(self): - try: - self._TKOut.__del__() - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# Button Class # -# ---------------------------------------------------------------------- # -class Button(Element): - def __init__(self, button_text='', button_type=BUTTON_TYPE_READ_FORM, target=(None, None), tooltip=None, - file_types=(("ALL Files", "*.*"),), initial_folder=None, disabled=False, change_submits=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): - ''' - Button Element - :param button_text: - :param button_type: - :param target: - :param tooltip: - :param file_types: - :param initial_folder: - :param disabled: - :param image_filename: - :param image_size: - :param image_subsample: - :param border_width: - :param size: - :param auto_size_button: - :param button_color: - :param default_value: - :param font: - :param bind_return_key: - :param focus: - :param pad: - :param key: - ''' - self.AutoSizeButton = auto_size_button - self.BType = button_type - self.FileTypes = file_types - self.TKButton = None - self.Target = target - self.ButtonText = button_text - self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR - self.ImageFilename = image_filename - self.ImageData = image_data - self.ImageSize = image_size - self.ImageSubsample = image_subsample - self.UserData = None - self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH - self.BindReturnKey = bind_return_key - self.Focus = focus - self.TKCal = None - self.CalendarCloseWhenChosen = None - self.DefaultDate_M_D_Y = (None, None, None) - self.InitialFolder = initial_folder - self.Disabled = disabled - self.ChangeSubmits = change_submits - - super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip) - return - - # Realtime button release callback - def ButtonReleaseCallBack(self, parm): - self.LastButtonClickedWasRealtime = False - self.ParentForm.LastButtonClicked = None - - # Realtime button callback - def ButtonPressCallBack(self, parm): - self.ParentForm.LastButtonClickedWasRealtime = True - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = self.ButtonText - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick out of loop if read was called - - # ------- Button Callback ------- # - def ButtonCallBack(self): - global _my_windows - - # print('Button callback') - - # print(f'Parent = {self.ParentForm} Position = {self.Position}') - # Buttons modify targets or return from the form - # If modifying target, get the element object at the target and modify its StrVar - target = self.Target - target_element = None - if target[0] == ThisRow: - target = [self.Position[0], target[1]] - if target[1] < 0: - target[1] = self.Position[1] + target[1] - strvar = None - should_submit_window = False - if target == (None, None): - strvar = self.TKStringVar - else: - if not isinstance(target, str): - if target[0] < 0: - target = [self.Position[0] + target[0], target[1]] - target_element = self.ParentContainer._GetElementAtLocation(target) - else: - target_element = self.ParentForm.FindElement(target) - try: - strvar = target_element.TKStringVar - except: - pass - try: - if target_element.ChangeSubmits: - should_submit_window = True - except: - pass - filetypes = (("ALL Files", "*.*"),) if self.FileTypes is None else self.FileTypes - if self.BType == BUTTON_TYPE_BROWSE_FOLDER: - folder_name = tk.filedialog.askdirectory(initialdir=self.InitialFolder) # show the 'get folder' dialog box - if folder_name != '': - try: - strvar.set(folder_name) - self.TKStringVar.set(folder_name) - except: - pass - elif self.BType == BUTTON_TYPE_BROWSE_FILE: - if sys.platform == 'darwin': - file_name = tk.filedialog.askopenfilename( - initialdir=self.InitialFolder) # show the 'get file' dialog box - else: - file_name = tk.filedialog.askopenfilename(filetypes=filetypes, - initialdir=self.InitialFolder) # show the 'get file' dialog box - if file_name != '': - strvar.set(file_name) - self.TKStringVar.set(file_name) - elif self.BType == BUTTON_TYPE_COLOR_CHOOSER: - color = tk.colorchooser.askcolor() # show the 'get file' dialog box - color = color[1] # save only the #RRGGBB portion - strvar.set(color) - self.TKStringVar.set(color) - elif self.BType == BUTTON_TYPE_BROWSE_FILES: - if sys.platform == 'darwin': - file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder) - else: - file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder) - if file_name != '': - file_name = ';'.join(file_name) - strvar.set(file_name) - self.TKStringVar.set(file_name) - elif self.BType == BUTTON_TYPE_SAVEAS_FILE: - if sys.platform == 'darwin': - file_name = tk.filedialog.asksaveasfilename( - initialdir=self.InitialFolder) # show the 'get file' dialog box - else: - file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes, - initialdir=self.InitialFolder) # show the 'get file' dialog box - if file_name != '': - strvar.set(file_name) - self.TKStringVar.set(file_name) - elif self.BType == BUTTON_TYPE_CLOSES_WIN: # this is a return type button so GET RESULTS and destroy window - # first, get the results table built - # modify the Results table in the parent FlexForm object - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = self.ButtonText - self.ParentForm.FormRemainedOpen = False - self.ParentForm._Close() - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() - if self.ParentForm.NonBlocking: - self.ParentForm.TKroot.destroy() - _my_windows.Decrement() - elif self.BType == BUTTON_TYPE_READ_FORM: # LEAVE THE WINDOW OPEN!! DO NOT CLOSE - # first, get the results table built - # modify the Results table in the parent FlexForm object - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = self.ButtonText - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: # if this window is running the mainloop, kick out - self.ParentForm.TKroot.quit() # kick the users out of the mainloop - elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop - self.ParentForm._Close() - if self.ParentForm.NonBlocking: - self.ParentForm.TKroot.destroy() - _my_windows.Decrement() - elif self.BType == BUTTON_TYPE_CALENDAR_CHOOSER: # this is a return type button so GET RESULTS and destroy window - should_submit_window = False - root = tk.Toplevel() - root.title('Calendar Chooser') - self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, - close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y) - self.TKCal.pack(expand=1, fill='both') - root.update() - - if should_submit_window: - self.ParentForm.LastButtonClicked = target_element.Key - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick the users out of the mainloop - - return - - def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None): - try: - if text is not None: - self.TKButton.configure(text=text) - self.ButtonText = text - if button_color != (None, None): - self.TKButton.config(foreground=button_color[0], background=button_color[1]) - except: - return - if disabled == True: - self.TKButton['state'] = 'disabled' - elif disabled == False: - self.TKButton['state'] = 'normal' - if image_data is not None: - image = tk.PhotoImage(data=image_data) - width, height = image.width(), image.height() - self.TKButton.config(image=image, width=width, height=height) - self.TKButton.image = image - if image_filename is not None: - self.TKButton.config(highlightthickness=0) - photo = tk.PhotoImage(file=image_filename) - width, height = photo.width(), photo.height() - self.TKButton.config(image=photo, width=width, height=height) - self.TKButton.image = photo - - def GetText(self): - return self.ButtonText - - def __del__(self): - try: - self.TKButton.__del__() - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# ProgreessBar # -# ---------------------------------------------------------------------- # -class ProgressBar(Element): - 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): - ''' - ProgressBar Element - :param max_value: - :param orientation: - :param size: - :param auto_size_text: - :param bar_color: - :param style: - :param border_width: - :param relief: - :param key: - :param pad: - ''' - self.MaxValue = max_value - self.TKProgressBar = None - self.Cancelled = False - self.NotRunning = True - self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION - self.BarColor = bar_color - self.BarStyle = style if style else DEFAULT_PROGRESS_BAR_STYLE - self.BorderWidth = border_width if border_width else DEFAULT_PROGRESS_BAR_BORDER_WIDTH - 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) - - # returns False if update failed - def UpdateBar(self, current_count, max=None): - if self.ParentForm.TKrootDestroyed: - return False - self.TKProgressBar.Update(current_count, max=max) - try: - self.ParentForm.TKroot.update() - except: - _my_windows.Decrement() - return False - return True - - def __del__(self): - try: - self.TKProgressBar.__del__() - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# Image # -# ---------------------------------------------------------------------- # -class Image(Element): - def __init__(self, filename=None, data=None, background_color=None, size=(None, None), pad=None, key=None, - tooltip=None): - ''' - Image Element - :param filename: - :param data: - :param background_color: - :param size: - :param pad: - :param key: - :param tooltip: - ''' - self.Filename = filename - self.Data = data - self.tktext_label = None - self.BackgroundColor = background_color - if data is None and filename is None: - print('* Warning... no image specified in Image Element! *') - super().__init__(ELEM_TYPE_IMAGE, size=size, background_color=background_color, pad=pad, key=key, - tooltip=tooltip) - return - - def Update(self, filename=None, data=None, size=(None, None)): - if filename is not None: - image = tk.PhotoImage(file=filename) - elif data is not None: - # if type(data) is bytes: - try: - image = tk.PhotoImage(data=data) - except: - return # an error likely means the window has closed so exit - # else: - # image = data - else: - return - width, height = size[0] or image.width(), size[1] or image.height() - self.tktext_label.configure(image=image, width=width, height=height) - self.tktext_label.image = image - - def __del__(self): - super().__del__() - - -# ---------------------------------------------------------------------- # -# Canvas # -# ---------------------------------------------------------------------- # -class Canvas(Element): - def __init__(self, canvas=None, background_color=None, size=(None, None), pad=None, key=None, tooltip=None): - ''' - Canvas Element - :param canvas: - :param background_color: - :param size: - :param pad: - :param key: - :param tooltip: - ''' - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - self._TKCanvas = canvas - - super().__init__(ELEM_TYPE_CANVAS, background_color=background_color, size=size, pad=pad, key=key, - tooltip=tooltip) - return - - @property - def TKCanvas(self): - if self._TKCanvas is None: - print('*** Did you forget to call Finalize()? Your code should look something like: ***') - print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') - return self._TKCanvas - - def __del__(self): - super().__del__() - - -# ---------------------------------------------------------------------- # -# Graph # -# ---------------------------------------------------------------------- # -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, key=None, - tooltip=None): - ''' - Graph Element - :param canvas_size: - :param graph_bottom_left: - :param graph_top_right: - :param background_color: - :param pad: - :param key: - :param tooltip: - ''' - self.CanvasSize = canvas_size - self.BottomLeft = graph_bottom_left - self.TopRight = graph_top_right - self._TKCanvas = None - self._TKCanvas2 = None - self.ChangeSubmits = change_submits - self.DragSubmits = drag_submits - self.ClickPosition = (None, None) - self.MouseButtonDown = False - super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key, - tooltip=tooltip) - return - - def _convert_xy_to_canvas_xy(self, x_in, y_in): - if None in (x_in, y_in): - return None, None - scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) - scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) - new_x = 0 + scale_x * (x_in - self.BottomLeft[0]) - new_y = self.CanvasSize[1] + scale_y * (y_in - self.BottomLeft[1]) - return new_x, new_y - - def _convert_canvas_xy_to_xy(self, x_in, y_in): - if None in (x_in, y_in): - return None, None - scale_x = (self.CanvasSize[0] - 0) / (self.TopRight[0] - self.BottomLeft[0]) - scale_y = (0 - self.CanvasSize[1]) / (self.TopRight[1] - self.BottomLeft[1]) - - new_x = x_in / scale_x + self.BottomLeft[0] - new_y = (y_in - self.CanvasSize[1]) / scale_y + self.BottomLeft[1] - return int(new_x), int(new_y) - - def DrawLine(self, point_from, point_to, color='black', width=1): - if point_from == (None, None): - return - converted_point_from = self._convert_xy_to_canvas_xy(point_from[0], point_from[1]) - converted_point_to = self._convert_xy_to_canvas_xy(point_to[0], point_to[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - return self._TKCanvas2.create_line(converted_point_from, converted_point_to, width=width, fill=color) - - def DrawPoint(self, point, size=2, color='black'): - if point == (None, None): - return - converted_point = self._convert_xy_to_canvas_xy(point[0], point[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - return self._TKCanvas2.create_oval(converted_point[0] - size, converted_point[1] - size, - converted_point[0] + size, converted_point[1] + size, fill=color, - outline=color) - - def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'): - if center_location == (None, None): - return - converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - return self._TKCanvas2.create_oval(converted_point[0] - radius, converted_point[1] - radius, - converted_point[0] + radius, converted_point[1] + radius, fill=fill_color, - outline=line_color) - - def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None): - converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) - converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - return self._TKCanvas2.create_oval(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], - converted_bottom_right[1], fill=fill_color, outline=line_color) - - def DrawArc(self, top_left, bottom_right, extent, start_angle, style=None, arc_color='black'): - converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) - converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) - tkstyle = tk.PIESLICE if style is None else style - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - return self._TKCanvas2.create_arc(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], - converted_bottom_right[1], extent=extent, start=start_angle, style=tkstyle, - outline=arc_color) - - def DrawRectangle(self, top_left, bottom_right, fill_color=None, line_color=None): - converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) - converted_bottom_right = self._convert_xy_to_canvas_xy(bottom_right[0], bottom_right[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - return self._TKCanvas2.create_rectangle(converted_top_left[0], converted_top_left[1], converted_bottom_right[0], - converted_bottom_right[1], fill=fill_color, outline=line_color) - - def DrawText(self, text, location, color='black', font=None, angle=0): - if location == (None, None): - return - converted_point = self._convert_xy_to_canvas_xy(location[0], location[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - text_id = self._TKCanvas2.create_text(converted_point[0], converted_point[1], text=text, font=font, fill=color, - angle=angle) - return text_id - - def Erase(self): - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - self._TKCanvas2.delete('all') - - def Update(self, background_color): - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - self._TKCanvas2.configure(background=background_color) - - def Move(self, x_direction, y_direction): - zero_converted = self._convert_xy_to_canvas_xy(0, 0) - shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) - shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) - if self._TKCanvas2 is None: - print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') - print('Call Window.Finalize() prior to this operation') - return None - self._TKCanvas2.move('all', shift_amount[0], shift_amount[1]) - - def MoveFigure(self, figure, x_direction, y_direction): - zero_converted = self._convert_xy_to_canvas_xy(0, 0) - shift_converted = self._convert_xy_to_canvas_xy(x_direction, y_direction) - shift_amount = (shift_converted[0] - zero_converted[0], shift_converted[1] - zero_converted[1]) - if figure is None: - print('*** WARNING - Your figure is None. It most likely means your did not Finalize your Window ***') - print('Call Window.Finalize() prior to all graph operations') - return None - self._TKCanvas2.move(figure, shift_amount[0], shift_amount[1]) - - @property - def TKCanvas(self): - if self._TKCanvas2 is None: - print('*** Did you forget to call Finalize()? Your code should look something like: ***') - print('*** form = sg.Window("My Form").Layout(layout).Finalize() ***') - return self._TKCanvas2 - - # Realtime button release callback - def ButtonReleaseCallBack(self, event): - self.ClickPosition = (None, None) - self.LastButtonClickedWasRealtime = not self.DragSubmits - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() - if self.DragSubmits: - self.ParentForm.LastButtonClicked = None - self.MouseButtonDown = False - - # Realtime button callback - def ButtonPressCallBack(self, event): - self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) - self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick out of loop if read was called - self.MouseButtonDown = True - - # Realtime button callback - def MotionCallBack(self, event): - if not self.MouseButtonDown: - return - self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) - self.ParentForm.LastButtonClickedWasRealtime = self.DragSubmits - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '__GRAPH__' # need to put something rather than None - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick out of loop if read was called - - def __del__(self): - super().__del__() - - -# ---------------------------------------------------------------------- # -# Frame # -# ---------------------------------------------------------------------- # -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): - ''' - Frame Element - :param title: - :param layout: - :param title_color: - :param background_color: - :param title_location: - :param relief: - :param size: - :param font: - :param pad: - :param border_width: - :param key: - :param tooltip: - ''' - self.UseDictionary = False - self.ReturnValues = None - self.ReturnValuesList = [] - self.ReturnValuesDictionary = {} - self.DictionaryKeyCounter = 0 - self.ParentWindow = None - self.Rows = [] - # self.ParentForm = None - self.TKFrame = None - self.Title = title - self.Relief = relief - self.TitleLocation = title_location - self.BorderWidth = border_width - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - - 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) - return - - def AddRow(self, *args): - ''' Parms are a variable number of Elements ''' - NumRows = len(self.Rows) # number of existing rows is our row number - CurrentRowNumber = NumRows # this row's number - CurrentRow = [] # start with a blank row and build up - # ------------------------- Add the elements to a row ------------------------- # - for i, element in enumerate(args): # Loop through list of elements and add them to the row - element.Position = (CurrentRowNumber, i) - element.ParentContainer = self - CurrentRow.append(element) - if element.Key is not None: - self.UseDictionary = True - # ------------------------- Append the row to list of Rows ------------------------- # - self.Rows.append(CurrentRow) - - def Layout(self, rows): - for row in rows: - self.AddRow(*row) - - def _GetElementAtLocation(self, location): - (row_num, col_num) = location - row = self.Rows[row_num] - element = row[col_num] - return element - - def __del__(self): - for row in self.Rows: - for element in row: - element.__del__() - super().__del__() - - -# ---------------------------------------------------------------------- # -# Separator # -# Routes stdout, stderr to a scrolled window # -# ---------------------------------------------------------------------- # -class VerticalSeparator(Element): - def __init__(self, pad=None): - ''' - VerticalSeperator - A separator that spans only 1 row in a vertical fashion - :param pad: - ''' - self.Orientation = 'vertical' # for now only vertical works - - super().__init__(ELEM_TYPE_SEPARATOR, pad=pad) - - def __del__(self): - super().__del__() - - -VSeperator = VerticalSeparator -VSep = VerticalSeparator - - -# ---------------------------------------------------------------------- # -# Tab # -# ---------------------------------------------------------------------- # -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): - ''' - Tab Element - :param title: - :param layout: - :param title_color: - :param background_color: - :param font: - :param pad: - :param disabled: - :param border_width: - :param key: - :param tooltip: - ''' - self.UseDictionary = False - self.ReturnValues = None - self.ReturnValuesList = [] - self.ReturnValuesDictionary = {} - self.DictionaryKeyCounter = 0 - self.ParentWindow = None - self.Rows = [] - self.TKFrame = None - self.Title = title - self.BorderWidth = border_width - self.Disabled = disabled - self.ParentNotebook = None - self.TabID = None - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - - self.Layout(layout) - - super().__init__(ELEM_TYPE_TAB, background_color=background_color, text_color=title_color, font=font, pad=pad, - key=key, tooltip=tooltip) - return - - def AddRow(self, *args): - ''' Parms are a variable number of Elements ''' - NumRows = len(self.Rows) # number of existing rows is our row number - CurrentRowNumber = NumRows # this row's number - CurrentRow = [] # start with a blank row and build up - # ------------------------- Add the elements to a row ------------------------- # - for i, element in enumerate(args): # Loop through list of elements and add them to the row - element.Position = (CurrentRowNumber, i) - element.ParentContainer = self - CurrentRow.append(element) - if element.Key is not None: - self.UseDictionary = True - # ------------------------- Append the row to list of Rows ------------------------- # - self.Rows.append(CurrentRow) - - def Layout(self, rows): - for row in rows: - self.AddRow(*row) - return self - - def Update(self, disabled=None): # TODO Disable / enable of tabs is not complete - if disabled is None: - return - self.Disabled = disabled - state = 'disabled' if disabled is True else 'normal' - self.ParentNotebook.tab(self.TabID, state=state) - return self - - def _GetElementAtLocation(self, location): - (row_num, col_num) = location - row = self.Rows[row_num] - element = row[col_num] - return element - - def __del__(self): - for row in self.Rows: - for element in row: - element.__del__() - super().__del__() - - -# ---------------------------------------------------------------------- # -# TabGroup # -# ---------------------------------------------------------------------- # -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, pad=None, border_width=None, theme=None, key=None, tooltip=None): - ''' - TabGroup Element - :param layout: - :param tab_location: - :param title_color: - :param selected_title_color: - :param background_color: - :param font: - :param change_submits: - :param pad: - :param border_width: - :param theme: - :param key: - :param tooltip: - ''' - self.UseDictionary = False - self.ReturnValues = None - self.ReturnValuesList = [] - self.ReturnValuesDictionary = {} - self.DictionaryKeyCounter = 0 - self.ParentWindow = None - self.SelectedTitleColor = selected_title_color - self.Rows = [] - self.TKNotebook = None - self.TabCount = 0 - self.BorderWidth = border_width - self.Theme = theme - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - self.ChangeSubmits = change_submits - self.TabLocation = tab_location - - 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) - return - - def AddRow(self, *args): - ''' Parms are a variable number of Elements ''' - NumRows = len(self.Rows) # number of existing rows is our row number - CurrentRowNumber = NumRows # this row's number - CurrentRow = [] # start with a blank row and build up - # ------------------------- Add the elements to a row ------------------------- # - for i, element in enumerate(args): # Loop through list of elements and add them to the row - element.Position = (CurrentRowNumber, i) - element.ParentContainer = self - CurrentRow.append(element) - if element.Key is not None: - self.UseDictionary = True - # ------------------------- Append the row to list of Rows ------------------------- # - self.Rows.append(CurrentRow) - - def Layout(self, rows): - for row in rows: - self.AddRow(*row) - - def _GetElementAtLocation(self, location): - (row_num, col_num) = location - row = self.Rows[row_num] - element = row[col_num] - return element - - def FindKeyFromTabName(self, tab_name): - for row in self.Rows: - for element in row: - if element.Title == tab_name: - return element.Key - return None - - def __del__(self): - for row in self.Rows: - for element in row: - element.__del__() - super().__del__() - - -# ---------------------------------------------------------------------- # -# Slider # -# ---------------------------------------------------------------------- # -class Slider(Element): - def __init__(self, range=(None, None), default_value=None, resolution=None, tick_interval=None, orientation=None, - border_width=None, relief=None, change_submits=False, disabled=False, size=(None, None), font=None, - background_color=None, text_color=None, key=None, pad=None, tooltip=None): - ''' - Slider Element - :param range: - :param default_value: - :param resolution: - :param orientation: - :param border_width: - :param relief: - :param change_submits: - :param disabled: - :param size: - :param font: - :param background_color: - :param text_color: - :param key: - :param pad: - :param tooltip: - ''' - self.TKScale = None - self.Range = (1, 10) if range == (None, None) else range - self.DefaultValue = self.Range[0] if default_value is None else default_value - self.Orientation = orientation if orientation else DEFAULT_SLIDER_ORIENTATION - self.BorderWidth = border_width if border_width else DEFAULT_SLIDER_BORDER_WIDTH - self.Relief = relief if relief else DEFAULT_SLIDER_RELIEF - self.Resolution = 1 if resolution is None else resolution - self.ChangeSubmits = change_submits - self.Disabled = disabled - self.TickInterval = tick_interval - temp_size = size - if temp_size == (None, None): - temp_size = (20, 20) if 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) - return - - def Update(self, value=None, range=(None, None), disabled=None): - 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 - if disabled == True: - self.TKScale['state'] = 'disabled' - elif disabled == False: - self.TKScale['state'] = 'normal' - - def SliderChangedHandler(self, event): - # first, get the results table built - # modify the Results table in the parent FlexForm object - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick the users out of the mainloop - - def __del__(self): - super().__del__() - - -# -# ---------------------------------------------------------------------- # -# Column # -# ---------------------------------------------------------------------- # -class Column(Element): - def __init__(self, layout, background_color=None, size=(None, None), pad=None, scrollable=False, - vertical_scroll_only=False, key=None): - ''' - Column Element - :param layout: - :param background_color: - :param size: - :param pad: - :param scrollable: - :param key: - ''' - self.UseDictionary = False - self.ReturnValues = None - self.ReturnValuesList = [] - self.ReturnValuesDictionary = {} - self.DictionaryKeyCounter = 0 - self.ParentWindow = None - self.Rows = [] - self.TKFrame = None - self.Scrollable = scrollable - self.VerticalScrollOnly = vertical_scroll_only - # self.ImageFilename = image_filename - # self.ImageData = image_data - # self.ImageSize = image_size - # self.ImageSubsample = image_subsample - bg = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - - self.Layout(layout) - - super().__init__(ELEM_TYPE_COLUMN, background_color=background_color, size=size, pad=pad, key=key) - return - - def AddRow(self, *args): - ''' Parms are a variable number of Elements ''' - NumRows = len(self.Rows) # number of existing rows is our row number - CurrentRowNumber = NumRows # this row's number - CurrentRow = [] # start with a blank row and build up - # ------------------------- Add the elements to a row ------------------------- # - for i, element in enumerate(args): # Loop through list of elements and add them to the row - element.Position = (CurrentRowNumber, i) - element.ParentContainer = self - CurrentRow.append(element) - if element.Key is not None: - self.UseDictionary = True - # ------------------------- Append the row to list of Rows ------------------------- # - self.Rows.append(CurrentRow) - - def Layout(self, rows): - for row in rows: - self.AddRow(*row) - - def _GetElementAtLocation(self, location): - (row_num, col_num) = location - row = self.Rows[row_num] - element = row[col_num] - return element - - def __del__(self): - for row in self.Rows: - for element in row: - element.__del__() - try: - del (self.TKFrame) - except: - pass - super().__del__() - - -# ---------------------------------------------------------------------- # -# Menu # -# ---------------------------------------------------------------------- # -class Menu(Element): - def __init__(self, menu_definition, background_color=None, size=(None, None), tearoff=False, pad=None, key=None): - ''' - Menu Element - :param menu_definition: - :param background_color: - :param size: - :param tearoff: - :param pad: - :param key: - ''' - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - self.MenuDefinition = menu_definition - self.TKMenu = None - self.Tearoff = tearoff - - super().__init__(ELEM_TYPE_MENUBAR, background_color=background_color, size=size, pad=pad, key=key) - return - - def MenuItemChosenCallback(self, item_chosen): - # print('IN MENU ITEM CALLBACK', item_chosen) - self.ParentForm.LastButtonClicked = item_chosen - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() # kick the users out of the mainloop - - def __del__(self): - super().__del__() - - -# ---------------------------------------------------------------------- # -# Table # -# ---------------------------------------------------------------------- # -class Table(Element): - def __init__(self, values, headings=None, visible_column_map=None, col_widths=None, def_col_width=10, - auto_size_columns=True, max_col_width=20, select_mode=None, display_row_numbers=False, num_rows=None, - font=None, justification='right', text_color=None, background_color=None, alternating_row_color=None, - size=(None, None), change_submits=False, bind_return_key=False, pad=None, key=None, tooltip=None): - ''' - Table Element - :param values: - :param headings: - :param visible_column_map: - :param col_widths: - :param def_col_width: - :param auto_size_columns: - :param max_col_width: - :param select_mode: - :param display_row_numbers: - :param font: - :param justification: - :param text_color: - :param background_color: - :param size: - :param pad: - :param key: - :param tooltip: - ''' - self.Values = values - self.ColumnHeadings = headings - self.ColumnsToDisplay = visible_column_map - self.ColumnWidths = col_widths - self.MaxColumnWidth = max_col_width - self.DefaultColumnWidth = def_col_width - self.AutoSizeColumns = auto_size_columns - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - self.TextColor = text_color - self.Justification = justification - self.InitialState = None - self.SelectMode = select_mode - self.DisplayRowNumbers = display_row_numbers - self.NumRows = num_rows if num_rows is not None else size[1] - self.TKTreeview = None - self.AlternatingRowColor = alternating_row_color - self.SelectedRows = [] - self.ChangeSubmits = change_submits - self.BindReturnKey = bind_return_key - self.StartingRowNumber = 0 # When displaying row numbers, where to start - self.RowHeaderText = 'Row' - super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, - size=size, pad=pad, key=key, tooltip=tooltip) - return - - def Update(self, values=None): - if values is not None: - children = self.TKTreeview.get_children() - for i in children: - self.TKTreeview.detach(i) - self.TKTreeview.delete(i) - children = self.TKTreeview.get_children() - # self.TKTreeview.delete(*self.TKTreeview.get_children()) - for i, value in enumerate(values): - if self.DisplayRowNumbers: - value = [i + self.StartingRowNumber] + value - id = self.TKTreeview.insert('', 'end', text=i, iid=i + 1, values=value, tag=i % 2) - if self.AlternatingRowColor is not None: - self.TKTreeview.tag_configure(1, background=self.AlternatingRowColor) - self.Values = values - self.SelectedRows = [] - - def treeview_selected(self, event): - selections = self.TKTreeview.selection() - self.SelectedRows = [int(x) - 1 for x in selections] - if self.ChangeSubmits: - MyForm = self.ParentForm - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() - - def treeview_double_click(self, event): - selections = self.TKTreeview.selection() - self.SelectedRows = [int(x) - 1 for x in selections] - if self.BindReturnKey: - MyForm = self.ParentForm - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() - - def __del__(self): - super().__del__() - - -# ---------------------------------------------------------------------- # -# Tree # -# ---------------------------------------------------------------------- # -class Tree(Element): - def __init__(self, data=None, headings=None, visible_column_map=None, col_widths=None, col0_width=10, - def_col_width=10, auto_size_columns=True, max_col_width=20, select_mode=None, show_expanded=False, - change_submits=False, font=None, - justification='right', text_color=None, background_color=None, num_rows=None, pad=None, key=None, - tooltip=None): - ''' - Tree Element - :param headings: - :param visible_column_map: - :param col_widths: - :param def_col_width: - :param auto_size_columns: - :param max_col_width: - :param select_mode: - :param font: - :param justification: - :param text_color: - :param background_color: - :param num_rows: - :param pad: - :param key: - :param tooltip: - ''' - self.TreeData = data - self.ColumnHeadings = headings - self.ColumnsToDisplay = visible_column_map - self.ColumnWidths = col_widths - self.MaxColumnWidth = max_col_width - self.DefaultColumnWidth = def_col_width - self.AutoSizeColumns = auto_size_columns - self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR - self.TextColor = text_color - self.Justification = justification - self.InitialState = None - self.SelectMode = select_mode - self.ShowExpanded = show_expanded - self.NumRows = num_rows - self.Col0Width = col0_width - self.TKTreeview = None - self.SelectedRows = [] - self.ChangeSubmits = change_submits - - super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, - key=key, tooltip=tooltip) - return - - def treeview_selected(self, event): - selections = self.TKTreeview.selection() - self.SelectedRows = [x for x in selections] - if self.ChangeSubmits: - MyForm = self.ParentForm - if self.Key is not None: - self.ParentForm.LastButtonClicked = self.Key - else: - self.ParentForm.LastButtonClicked = '' - self.ParentForm.FormRemainedOpen = True - if self.ParentForm.CurrentlyRunningMainloop: - self.ParentForm.TKroot.quit() - - def add_treeview_data(self, node): - # print(f'Inserting {node.key} under parent {node.parent}') - if node.key != '': - self.TKTreeview.insert(node.parent, 'end', node.key, text=node.text, values=node.values, - open=self.ShowExpanded) - for node in node.children: - self.add_treeview_data(node) - - def Update(self, values=None, key=None, value=None, text=None): - if values is not None: - children = self.TKTreeview.get_children() - for i in children: - self.TKTreeview.detach(i) - self.TKTreeview.delete(i) - children = self.TKTreeview.get_children() - self.TreeData = values - self.add_treeview_data(self.TreeData.root_node) - self.SelectedRows = [] - if key is not None: - item = self.TKTreeview.item(key) - if value is not None: - self.TKTreeview.item(key, values=value) - if text is not None: - self.TKTreeview.item(key, text=text) - item = self.TKTreeview.item(key) - return self - - def __del__(self): - super().__del__() - - -class TreeData(object): - class Node(object): - def __init__(self, parent, key, text, values): - self.parent = parent - self.children = [] - self.key = key - self.text = text - self.values = values - - def _Add(self, node): - self.children.append(node) - - def __init__(self): - self.tree_dict = {} - self.root_node = self.Node("", "", 'root', []) - self.tree_dict[""] = self.root_node - - def _AddNode(self, key, node): - self.tree_dict[key] = node - - def Insert(self, parent, key, text, values): - node = self.Node(parent, key, text, values) - self.tree_dict[key] = node - parent_node = self.tree_dict[parent] - parent_node._Add(node) - - def __repr__(self): - return self._NodeStr(self.root_node, 1) - - def _NodeStr(self, node, level): - return '\n'.join( - [str(node.key) + ' : ' + str(node.text)] + - [' ' * 4 * level + self._NodeStr(child, level + 1) for child in node.children]) - - -# ---------------------------------------------------------------------- # -# Error Element # -# ---------------------------------------------------------------------- # -class ErrorElement(Element): - def __init__(self, key=None): - ''' - Error Element - :param key: - ''' - self.Key = key - - super().__init__(ELEM_TYPE_ERROR, key=key) - return - - def Update(self, *args, **kwargs): - PopupError('Keyword error in Update', - 'You need to stop this madness and check your spelling', - 'Bad key = {}'.format(self.Key), - 'Your bad line of code may resemble this:', - 'window.FindElement("{}")'.format(self.Key)) - return self - - def Get(self): - return 'This is NOT a valid Element!\nSTOP trying to do things with it or I will have to crash at some point!' - - def __del__(self): - super().__del__() - - -# ------------------------------------------------------------------------- # -# Window CLASS # -# ------------------------------------------------------------------------- # -class Window: - - def __init__(self, title, default_element_size=DEFAULT_ELEMENT_SIZE, default_button_element_size=(None, None), - auto_size_text=None, auto_size_buttons=None, location=(None, None), size=(None, None), - button_color=None, font=None, - progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False, - auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=DEFAULT_WINDOW_ICON, force_toplevel=False, - 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): - ''' - Window - :param title: - :param default_element_size: - :param default_button_element_size: - :param auto_size_text: - :param auto_size_buttons: - :param location: - :param button_color: - :param font: - :param progress_bar_color: - :param background_color: - :param border_depth: - :param auto_close: - :param auto_close_duration: - :param icon: - :param force_toplevel: - :param return_keyboard_events: - :param use_default_focus: - :param text_justification: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param resizable: - ''' - 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.Rows = [] # a list of ELEMENTS for this row - self.DefaultElementSize = default_element_size - self.DefaultButtonElementSize = default_button_element_size if default_button_element_size != ( - None, None) else DEFAULT_BUTTON_ELEMENT_SIZE - self.Location = location - self.ButtonColor = button_color if button_color else DEFAULT_BUTTON_COLOR - self.BackgroundColor = background_color if background_color else DEFAULT_BACKGROUND_COLOR - self.ParentWindow = None - self.Font = font if font else DEFAULT_FONT - self.RadioDict = {} - self.BorderDepth = border_depth - self.WindowIcon = icon if icon is not None else _my_windows.user_defined_icon - self.AutoClose = auto_close - self.NonBlocking = False - self.TKroot = None - self.TKrootDestroyed = False - self.CurrentlyRunningMainloop = False - self.FormRemainedOpen = False - self.TKAfterID = None - self.ProgressBarColor = progress_bar_color - self.AutoCloseDuration = auto_close_duration - self.RootNeedsDestroying = False - self.Shown = False - self.ReturnValues = None - self.ReturnValuesList = [] - self.ReturnValuesDictionary = {} - self.DictionaryKeyCounter = 0 - self.LastButtonClicked = None - self.LastButtonClickedWasRealtime = False - self.UseDictionary = False - self.UseDefaultFocus = use_default_focus - self.ReturnKeyboardEvents = return_keyboard_events - self.LastKeyboardEvent = None - self.TextJustification = text_justification - self.NoTitleBar = no_titlebar - self.GrabAnywhere = grab_anywhere - self.KeepOnTop = keep_on_top - self.ForceTopLevel = force_toplevel - self.Resizable = resizable - self._AlphaChannel = alpha_channel - self.Timeout = None - self.TimeoutKey = '_timeout_' - self.TimerCancelled = False - self.DisableClose = disable_close - self._Hidden = False - self._Size = size - - - class MyKvAppClass(kvApp): - - # def __init(self, window): - # self.window = window - def set_window(self, window): - self.window = window - - def build(self): - layout = StartupTK(self.window) - return layout - - # ------------------------- Add ONE Row to Form ------------------------- # - def AddRow(self, *args): - ''' Parms are a variable number of Elements ''' - NumRows = len(self.Rows) # number of existing rows is our row number - CurrentRowNumber = NumRows # this row's number - CurrentRow = [] # start with a blank row and build up - # ------------------------- Add the elements to a row ------------------------- # - for i, element in enumerate(args): # Loop through list of elements and add them to the row - element.Position = (CurrentRowNumber, i) - element.ParentContainer = self - CurrentRow.append(element) - # ------------------------- Append the row to list of Rows ------------------------- # - self.Rows.append(CurrentRow) - - # ------------------------- Add Multiple Rows to Form ------------------------- # - def AddRows(self, rows): - for row in rows: - self.AddRow(*row) - - def Layout(self, rows): - self.AddRows(rows) - return self - - def LayoutAndRead(self, rows, non_blocking=False): - self.AddRows(rows) - self.Show(non_blocking=non_blocking) - return self.ReturnValues - - def LayoutAndShow(self, rows): - raise DeprecationWarning('LayoutAndShow is no longer supported... change your call to LayoutAndRead') - - # ------------------------- ShowForm THIS IS IT! ------------------------- # - def Show(self, non_blocking=False): - self.Shown = True - # Compute num rows & num cols (it'll come in handy debugging) - self.NumRows = len(self.Rows) - self.NumCols = max(len(row) for row in self.Rows) - self.NonBlocking = non_blocking - - # Search through entire form to see if any elements set the focus - # if not, then will set the focus to the first input element - found_focus = False - for row in self.Rows: - for element in row: - try: - if element.Focus: - found_focus = True - except: - pass - try: - if element.Key is not None: - self.UseDictionary = True - except: - pass - - if not found_focus and self.UseDefaultFocus: - self.UseDefaultFocus = True - else: - self.UseDefaultFocus = False - # -=-=-=-=-=-=-=-=- RUN the GUI -=-=-=-=-=-=-=-=- ## - # StartupTK(self) - self.KVApp = Window.MyKvAppClass() - self.KVApp.set_window(self) - self.KVApp.run() - # If a button or keyboard event happened but no results have been built, build the results - if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: - return BuildResults(self, False, self) - return self.ReturnValues - - # ------------------------- SetIcon - set the window's fav icon ------------------------- # - def SetIcon(self, icon=None, pngbase64=None): - if pngbase64 != None: - img = tkinter.PhotoImage(data=pngbase64) - wicon = img - else: - wicon = icon - self.WindowIcon = wicon - self.KVApp.icon = wicon - - def _GetElementAtLocation(self, location): - (row_num, col_num) = location - row = self.Rows[row_num] - element = row[col_num] - return element - - def _GetDefaultElementSize(self): - return self.DefaultElementSize - - def _AutoCloseAlarmCallback(self): - try: - window = self - if window: - if window.NonBlocking: - self.CloseNonBlockingForm() - else: - window._Close() - self.TKroot.quit() - self.RootNeedsDestroying = True - except: - pass - - def _TimeoutAlarmCallback(self): - # first, get the results table built - # modify the Results table in the parent FlexForm object - # print('TIMEOUT CALLBACK') - if self.TimerCancelled: - # print('** timer was cancelled **') - return - self.LastButtonClicked = self.TimeoutKey - self.FormRemainedOpen = True - self.TKroot.quit() # kick the users out of the mainloop - - def Read(self, timeout=None, timeout_key=TIMEOUT_KEY): - if timeout == 0: # timeout of zero runs the old readnonblocking - event, values = self.ReadNonBlocking() - if event is None: - event = timeout_key - if values is None: - event = None - return event, values # make event None if values was None and return - # Read with a timeout - self.Timeout = timeout - self.TimeoutKey = timeout_key - self.NonBlocking = False - if self.TKrootDestroyed: - return None, None - if not self.Shown: - self.Show() - else: - # if already have a button waiting, the return previously built results - if self.LastButtonClicked is not None and not self.LastButtonClickedWasRealtime: - # print(f'*** Found previous clicked saved {self.LastButtonClicked}') - results = BuildResults(self, False, self) - self.LastButtonClicked = None - return results - InitializeResults(self) - # if the last button clicked was realtime, emulate a read non-blocking - # the idea is to quickly return realtime buttons without any blocks until released - if self.LastButtonClickedWasRealtime: - # print(f'RTime down {self.LastButtonClicked}' ) - try: - rc = self.TKroot.update() - except: - self.TKrootDestroyed = True - _my_windows.Decrement() - print('ROOT Destroyed') - results = BuildResults(self, False, self) - if results[0] != None and results[0] != timeout_key: - return results - else: - pass - - # else: - # print("** REALTIME PROBLEM FOUND **", results) - - # normal read blocking code.... - if timeout != None: - self.TimerCancelled = False - self.TKAfterID = self.TKroot.after(timeout, self._TimeoutAlarmCallback) - self.CurrentlyRunningMainloop = True - # print(f'In main {self.Title}') - self.TKroot.protocol("WM_DESTROY_WINDOW", self.OnClosingCallback) - self.TKroot.protocol("WM_DELETE_WINDOW", self.OnClosingCallback) - self.TKroot.mainloop() - # print('Out main') - self.CurrentlyRunningMainloop = False - # if self.LastButtonClicked != TIMEOUT_KEY: - # print(f'Window {self.Title} Last button clicked = {self.LastButtonClicked}') - try: - self.TKroot.after_cancel(self.TKAfterID) - except: - pass - # print('** tkafter cancel failed **') - self.TimerCancelled = True - if self.RootNeedsDestroying: - print('*** DESTROYING LATE ***') - self.TKroot.destroy() - _my_windows.Decrement() - # if form was closed with X - if self.LastButtonClicked is None and self.LastKeyboardEvent is None and self.ReturnValues[0] is None: - _my_windows.Decrement() - # Determine return values - if self.LastKeyboardEvent is not None or self.LastButtonClicked is not None: - results = BuildResults(self, False, self) - if not self.LastButtonClickedWasRealtime: - self.LastButtonClicked = None - return results - else: - return self.ReturnValues - - def ReadNonBlocking(self): - if self.TKrootDestroyed: - try: - self.TKroot.quit() - self.TKroot.destroy() - except: - print('DESTROY FAILED') - return None, None - if not self.Shown: - self.Show(non_blocking=True) - try: - rc = self.TKroot.update() - except: - self.TKrootDestroyed = True - _my_windows.Decrement() - print("read failed") - # return None, None - if self.RootNeedsDestroying: - print('*** DESTROYING LATE ***') - self.TKroot.destroy() - _my_windows.Decrement() - return BuildResults(self, False, self) - - def Finalize(self): - if self.TKrootDestroyed: - return self - if not self.Shown: - self.Show(non_blocking=True) - try: - rc = self.TKroot.update() - except: - self.TKrootDestroyed = True - _my_windows.Decrement() - # return None, None - return self - - def Refresh(self): - if self.TKrootDestroyed: - return self - try: - rc = self.TKroot.update() - except: - pass - return self - - def Fill(self, values_dict): - FillFormWithValues(self, values_dict) - return self - - def FindElement(self, key): - element = _FindElementFromKeyInSubForm(self, key) - if element is None: - print('*** WARNING = FindElement did not find the key. Please check your key\'s spelling ***') - PopupError('Keyword error in FindElement Call', - 'Bad key = {}'.format(key), - 'Your bad line of code may resemble this:', - 'window.FindElement("{}")'.format(key)) - return ErrorElement(key=key) - return element - - def FindElementWithFocus(self): - element = _FindElementWithFocusInSubForm(self) - return element - - def SaveToDisk(self, filename): - try: - results = BuildResults(self, False, self) - with open(filename, 'wb') as sf: - pickle.dump(results[1], sf) - except: - print('*** Error saving form to disk ***') - - def LoadFromDisk(self, filename): - try: - with open(filename, 'rb') as df: - self.Fill(pickle.load(df)) - except: - print('*** Error loading form to disk ***') - - def GetScreenDimensions(self): - if self.TKrootDestroyed: - return None, None - 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 - - def Move(self, x, y): - try: - self.TKroot.geometry("+%s+%s" % (x, y)) - except: - pass - - def Minimize(self): - self.TKroot.iconify() - - def StartMove(self, event): - try: - self.TKroot.x = event.x - self.TKroot.y = event.y - except: - pass - - def StopMove(self, event): - try: - self.TKroot.x = None - self.TKroot.y = None - except: - pass - - def OnMotion(self, event): - try: - deltax = event.x - self.TKroot.x - deltay = event.y - self.TKroot.y - x = self.TKroot.winfo_x() + deltax - y = self.TKroot.winfo_y() + deltay - self.TKroot.geometry("+%s+%s" % (x, y)) - except: - pass - - def _KeyboardCallback(self, event): - self.LastButtonClicked = None - self.FormRemainedOpen = True - if event.char != '': - self.LastKeyboardEvent = event.char - else: - self.LastKeyboardEvent = str(event.keysym) + ':' + str(event.keycode) - if not self.NonBlocking: - BuildResults(self, False, self) - if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! - self.TKroot.quit() - - def _MouseWheelCallback(self, event): - self.LastButtonClicked = None - self.FormRemainedOpen = True - self.LastKeyboardEvent = 'MouseWheel:Down' if event.delta < 0 else 'MouseWheel:Up' - if not self.NonBlocking: - BuildResults(self, False, self) - if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! - self.TKroot.quit() - - def _Close(self): - try: - self.TKroot.update() - except: - pass - if not self.NonBlocking: - BuildResults(self, False, self) - if self.TKrootDestroyed: - return None - self.TKrootDestroyed = True - self.RootNeedsDestroying = True - return None - - def Close(self): - if self.TKrootDestroyed: - return - try: - self.TKroot.destroy() - _my_windows.Decrement() - except: - pass - - CloseNonBlockingForm = Close - CloseNonBlocking = Close - - # IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called - def OnClosingCallback(self): - global _my_windows - if self.DisableClose: - return - # print('Got closing callback') - if self.CurrentlyRunningMainloop: # quit if this is the current mainloop, otherwise don't quit! - self.TKroot.quit() # kick the users out of the mainloop - self.TKroot.destroy() # kick the users out of the mainloop - self.RootNeedsDestroying = True - else: - self.RootNeedsDestroying = True - self.TKrootDestroyed = True - - return - - def Disable(self): - self.TKroot.grab_set_global() - - def Enable(self): - self.TKroot.grab_release() - - def Hide(self): - self._Hidden = True - self.TKroot.withdraw() - - def UnHide(self): - if self._Hidden: - self.TKroot.deiconify() - self._Hidden = False - - def Disappear(self): - self.TKroot.attributes('-alpha', 0) - - def Reappear(self): - self.TKroot.attributes('-alpha', 255) - - def SetAlpha(self, alpha): - ''' - Change the window's transparency - :param alpha: From 0 to 1 with 0 being completely transparent - :return: - ''' - self._AlphaChannel = alpha - self.TKroot.attributes('-alpha', alpha) - - @property - def AlphaChannel(self): - return self._AlphaChannel - - @AlphaChannel.setter - def AlphaChannel(self, alpha): - self._AlphaChannel = alpha - self.TKroot.attributes('-alpha', alpha) - - def BringToFront(self): - try: - self.TKroot.lift() - except: - pass - - def CurrentLocation(self): - return int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y()) - - @property - def Size(self): - win_width = self.TKroot.winfo_width() - win_height = self.TKroot.winfo_height() - return win_width, win_height - - @Size.setter - def Size(self, size): - try: - self.TKroot.geometry("%sx%s" % (size[0], size[1])) - self.TKroot.update_idletasks() - except: - pass - - def __enter__(self): - return self - - def __exit__(self, *a): - self.__del__() - return False - - def __del__(self): - for row in self.Rows: - for element in row: - element.__del__() - - -FlexForm = Window - - -# ################################################################################ -# ################################################################################ -# END OF ELEMENT DEFINITIONS -# ################################################################################ -# ################################################################################ - - -# =========================================================================== # -# Button Lazy Functions so the caller doesn't have to define a bunch of stuff # -# =========================================================================== # - - -# ------------------------- 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, font=None, pad=None, - key=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, font=font, pad=pad, - key=key) - - -# ------------------------- 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, - font=None, disabled=False, - pad=None, key=None): - 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, disabled=disabled, button_color=button_color, font=font, pad=pad, - key=key) - - -# ------------------------- 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, - font=None, pad=None, key=None): - 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, tooltip=tooltip, size=size, - auto_size_button=auto_size_button, - disabled=disabled, button_color=button_color, font=font, pad=pad, key=key) - - -# ------------------------- 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, font=None, - pad=None, key=None): - 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, - font=font, pad=pad, key=key) - - -# ------------------------- 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, font=None, - pad=None, key=None): - 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, - font=font, pad=pad, key=key) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - 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) - - -# ------------------------- 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): - return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, - 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) - - -# ------------------------- 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): - return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN, image_filename=image_filename, - 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) - - -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): - return Button(button_text=button_text, button_type=BUTTON_TYPE_READ_FORM, image_filename=image_filename, - 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) - - -ReadFormButton = ReadButton -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): - return Button(button_text=button_text, button_type=BUTTON_TYPE_REALTIME, image_filename=image_filename, - 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) - - -# ------------------------- 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): - return Button(button_text=button_text, button_type=BUTTON_TYPE_CLOSES_WIN_ONLY, 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) - - -# ------------------------- Calendar Chooser Button lazy function ------------------------- # -def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None, 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): - button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target, - 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) - button.CalendarCloseWhenChosen = close_when_date_chosen - button.DefaultDate_M_D_Y = default_date_m_d_y - return button - - -# ------------------------- Calendar Chooser Button lazy function ------------------------- # -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): - return Button(button_text=button_text, button_type=BUTTON_TYPE_COLOR_CHOOSER, target=target, - 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) - - -##################################### ----- RESULTS ------ ################################################## - -def AddToReturnDictionary(form, element, value): - if element.Key is None: - form.ReturnValuesDictionary[form.DictionaryKeyCounter] = value - element.Key = form.DictionaryKeyCounter - form.DictionaryKeyCounter += 1 - else: - form.ReturnValuesDictionary[element.Key] = value - - -def AddToReturnList(form, value): - form.ReturnValuesList.append(value) - - -# ----------------------------------------------------------------------------# -# ------- FUNCTION InitializeResults. Sets up form results matrix --------# -def InitializeResults(form): - BuildResults(form, True, form) - return - - -# ===== Radio Button RadVar encoding and decoding =====# -# ===== The value is simply the row * 1000 + col =====# -def DecodeRadioRowCol(RadValue): - row = RadValue // 1000 - col = RadValue % 1000 - return row, col - - -def EncodeRadioRowCol(row, col): - RadValue = row * 1000 + col - return RadValue - - -# ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- # -# format of return values is -# (Button Pressed, input_values) -def BuildResults(form, initialize_only, top_level_form): - # Results for elements are: - # TEXT - Nothing - # INPUT - Read value from TK - # Button - Button Text and position as a Tuple - - # Get the initialized results so we don't have to rebuild - form.DictionaryKeyCounter = 0 - form.ReturnValuesDictionary = {} - form.ReturnValuesList = [] - BuildResultsForSubform(form, initialize_only, top_level_form) - if not top_level_form.LastButtonClickedWasRealtime: - top_level_form.LastButtonClicked = None - return form.ReturnValues - - -def BuildResultsForSubform(form, initialize_only, top_level_form): - button_pressed_text = top_level_form.LastButtonClicked - for row_num, row in enumerate(form.Rows): - for col_num, element in enumerate(row): - if element.Key is not None and WRITE_ONLY_KEY in str(element.Key): - continue - value = None - if element.Type == ELEM_TYPE_COLUMN: - element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter - element.ReturnValuesList = [] - element.ReturnValuesDictionary = {} - BuildResultsForSubform(element, initialize_only, top_level_form) - for item in element.ReturnValuesList: - AddToReturnList(top_level_form, item) - if element.UseDictionary: - top_level_form.UseDictionary = True - if element.ReturnValues[0] is not None: # if a button was clicked - button_pressed_text = element.ReturnValues[0] - - if element.Type == ELEM_TYPE_FRAME: - element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter - element.ReturnValuesList = [] - element.ReturnValuesDictionary = {} - BuildResultsForSubform(element, initialize_only, top_level_form) - for item in element.ReturnValuesList: - AddToReturnList(top_level_form, item) - if element.UseDictionary: - top_level_form.UseDictionary = True - if element.ReturnValues[0] is not None: # if a button was clicked - button_pressed_text = element.ReturnValues[0] - - if element.Type == ELEM_TYPE_TAB_GROUP: - element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter - element.ReturnValuesList = [] - element.ReturnValuesDictionary = {} - BuildResultsForSubform(element, initialize_only, top_level_form) - for item in element.ReturnValuesList: - AddToReturnList(top_level_form, item) - if element.UseDictionary: - top_level_form.UseDictionary = True - if element.ReturnValues[0] is not None: # if a button was clicked - button_pressed_text = element.ReturnValues[0] - - if element.Type == ELEM_TYPE_TAB: - element.DictionaryKeyCounter = top_level_form.DictionaryKeyCounter - element.ReturnValuesList = [] - element.ReturnValuesDictionary = {} - BuildResultsForSubform(element, initialize_only, top_level_form) - for item in element.ReturnValuesList: - AddToReturnList(top_level_form, item) - if element.UseDictionary: - top_level_form.UseDictionary = True - if element.ReturnValues[0] is not None: # if a button was clicked - button_pressed_text = element.ReturnValues[0] - - if not initialize_only: - if element.Type == ELEM_TYPE_INPUT_TEXT: - value = element.TKStringVar.get() - if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: - element.TKStringVar.set('') - elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: - value = element.TKIntVar.get() - value = (value != 0) - elif element.Type == ELEM_TYPE_INPUT_RADIO: - RadVar = element.TKIntVar.get() - this_rowcol = EncodeRadioRowCol(row_num, col_num) - value = RadVar == this_rowcol - elif element.Type == ELEM_TYPE_BUTTON: - if top_level_form.LastButtonClicked == element.ButtonText: - button_pressed_text = top_level_form.LastButtonClicked - if element.BType != BUTTON_TYPE_REALTIME: # Do not clear realtime buttons - top_level_form.LastButtonClicked = None - if element.BType == BUTTON_TYPE_CALENDAR_CHOOSER: - try: - value = element.TKCal.selection - except: - value = None - else: - try: - value = element.TKStringVar.get() - except: - value = None - elif element.Type == ELEM_TYPE_INPUT_COMBO: - value = element.TKStringVar.get() - elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: - value = element.TKStringVar.get() - elif element.Type == ELEM_TYPE_INPUT_LISTBOX: - try: - items = element.TKListbox.curselection() - value = [element.Values[int(item)] for item in items] - except: - value = '' - elif element.Type == ELEM_TYPE_INPUT_SPIN: - try: - value = element.TKStringVar.get() - except: - value = 0 - elif element.Type == ELEM_TYPE_INPUT_SLIDER: - try: - value = element.TKIntVar.get() - except: - value = 0 - elif element.Type == ELEM_TYPE_INPUT_MULTILINE: - try: - value = element.TKText.get(1.0, tk.END) - if not top_level_form.NonBlocking and not element.do_not_clear and not top_level_form.ReturnKeyboardEvents: - element.TKText.delete('1.0', tk.END) - except: - value = None - elif element.Type == ELEM_TYPE_TAB_GROUP: - try: - value = element.TKNotebook.tab(element.TKNotebook.index('current'))['text'] - tab_key = element.FindKeyFromTabName(value) - if tab_key is not None: - value = tab_key - except: - value = None - elif element.Type == ELEM_TYPE_TABLE: - value = element.SelectedRows - elif element.Type == ELEM_TYPE_TREE: - value = element.SelectedRows - elif element.Type == ELEM_TYPE_GRAPH: - value = element.ClickPosition - else: - value = None - - # if an input type element, update the results - if element.Type != ELEM_TYPE_BUTTON and \ - element.Type != ELEM_TYPE_TEXT and \ - element.Type != ELEM_TYPE_IMAGE and \ - element.Type != ELEM_TYPE_OUTPUT and \ - element.Type != ELEM_TYPE_PROGRESS_BAR and \ - element.Type != ELEM_TYPE_COLUMN and \ - element.Type != ELEM_TYPE_FRAME \ - and element.Type != ELEM_TYPE_TAB: - AddToReturnList(form, value) - AddToReturnDictionary(top_level_form, element, value) - elif (element.Type == ELEM_TYPE_BUTTON and - element.BType == BUTTON_TYPE_CALENDAR_CHOOSER and - element.Target == (None, None)) or \ - (element.Type == ELEM_TYPE_BUTTON and - element.BType == BUTTON_TYPE_COLOR_CHOOSER and - element.Target == (None, None)) or \ - (element.Type == ELEM_TYPE_BUTTON - and element.Key is not None and - (element.BType in (BUTTON_TYPE_SAVEAS_FILE, BUTTON_TYPE_BROWSE_FILE, BUTTON_TYPE_BROWSE_FILES, - BUTTON_TYPE_BROWSE_FOLDER))): - AddToReturnList(form, value) - AddToReturnDictionary(top_level_form, element, value) - - # if this is a column, then will fail so need to wrap with tr - try: - if form.ReturnKeyboardEvents and form.LastKeyboardEvent is not None: - button_pressed_text = form.LastKeyboardEvent - form.LastKeyboardEvent = None - except: - pass - - try: - form.ReturnValuesDictionary.pop(None, None) # clean up dictionary include None was included - except: - pass - - if not form.UseDictionary: - form.ReturnValues = button_pressed_text, form.ReturnValuesList - else: - form.ReturnValues = button_pressed_text, form.ReturnValuesDictionary - - return form.ReturnValues - - -def FillFormWithValues(form, values_dict): - FillSubformWithValues(form, values_dict) - - -def FillSubformWithValues(form, values_dict): - for row_num, row in enumerate(form.Rows): - for col_num, element in enumerate(row): - value = None - if element.Type == ELEM_TYPE_COLUMN: - FillSubformWithValues(element, values_dict) - if element.Type == ELEM_TYPE_FRAME: - FillSubformWithValues(element, values_dict) - if element.Type == ELEM_TYPE_TAB_GROUP: - FillSubformWithValues(element, values_dict) - if element.Type == ELEM_TYPE_TAB: - FillSubformWithValues(element, values_dict) - try: - value = values_dict[element.Key] - except: - continue - if element.Type == ELEM_TYPE_INPUT_TEXT: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_CHECKBOX: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_RADIO: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_COMBO: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_LISTBOX: - element.SetValue(value) - elif element.Type == ELEM_TYPE_INPUT_SLIDER: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_MULTILINE: - element.Update(value) - elif element.Type == ELEM_TYPE_INPUT_SPIN: - element.Update(value) - elif element.Type == ELEM_TYPE_BUTTON: - element.Update(value) - - -def _FindElementFromKeyInSubForm(form, key): - for row_num, row in enumerate(form.Rows): - for col_num, element in enumerate(row): - if element.Type == ELEM_TYPE_COLUMN: - matching_elem = _FindElementFromKeyInSubForm(element, key) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_FRAME: - matching_elem = _FindElementFromKeyInSubForm(element, key) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_TAB_GROUP: - matching_elem = _FindElementFromKeyInSubForm(element, key) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_TAB: - matching_elem = _FindElementFromKeyInSubForm(element, key) - if matching_elem is not None: - return matching_elem - if element.Key == key: - return element - - -def _FindElementWithFocusInSubForm(form): - for row_num, row in enumerate(form.Rows): - for col_num, element in enumerate(row): - if element.Type == ELEM_TYPE_COLUMN: - matching_elem = _FindElementWithFocusInSubForm(element) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_FRAME: - matching_elem = _FindElementWithFocusInSubForm(element) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_TAB_GROUP: - matching_elem = _FindElementWithFocusInSubForm(element) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_TAB: - matching_elem = _FindElementWithFocusInSubForm(element) - if matching_elem is not None: - return matching_elem - if element.Type == ELEM_TYPE_INPUT_TEXT: - if element.TKEntry is not None: - if element.TKEntry is element.TKEntry.focus_get(): - return element - if element.Type == ELEM_TYPE_INPUT_MULTILINE: - if element.TKText is not None: - if element.TKText is element.TKText.focus_get(): - return element - - -if sys.version_info[0] >= 3: - def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): - if type(sub_menu_info) is str: - if not is_sub_menu and not skip: - # print(f'Adding command {sub_menu_info}') - pos = sub_menu_info.find('&') - if pos != -1: - if pos == 0 or sub_menu_info[pos - 1] != "\\": - sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:] - if sub_menu_info == '---': - top_menu.add('separator') - else: - top_menu.add_command(label=sub_menu_info, underline=pos, - command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info)) - else: - i = 0 - while i < (len(sub_menu_info)): - item = sub_menu_info[i] - if i != len(sub_menu_info) - 1: - if type(sub_menu_info[i + 1]) == list: - new_menu = tk.Menu(top_menu, tearoff=element.Tearoff) - pos = sub_menu_info[i].find('&') - if pos != -1: - if pos == 0 or sub_menu_info[i][pos - 1] != "\\": - sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:] - top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos) - AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) - i += 1 # skip the next one - else: - AddMenuItem(top_menu, item, element) - else: - AddMenuItem(top_menu, item, element) - i += 1 -else: - def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): - if isinstance(sub_menu_info, types.StringType): - if not is_sub_menu and not skip: - # print(f'Adding command {sub_menu_info}') - pos = sub_menu_info.find('&') - if pos != -1: - if pos == 0 or sub_menu_info[pos - 1] != "\\": - sub_menu_info = sub_menu_info[:pos] + sub_menu_info[pos + 1:] - if sub_menu_info == '---': - top_menu.add('separator') - else: - top_menu.add_command(label=sub_menu_info, underline=pos, - command=lambda: Menu.MenuItemChosenCallback(element, sub_menu_info)) - else: - i = 0 - while i < (len(sub_menu_info)): - item = sub_menu_info[i] - if i != len(sub_menu_info) - 1: - if not isinstance(sub_menu_info[i + 1], types.StringType): - new_menu = tk.Menu(top_menu, tearoff=element.Tearoff) - pos = sub_menu_info[i].find('&') - if pos != -1: - if pos == 0 or sub_menu_info[i][pos - 1] != "\\": - sub_menu_info[i] = sub_menu_info[i][:pos] + sub_menu_info[i][pos + 1:] - top_menu.add_cascade(label=sub_menu_info[i], menu=new_menu, underline=pos) - AddMenuItem(new_menu, sub_menu_info[i + 1], element, is_sub_menu=True) - i += 1 # skip the next one - else: - AddMenuItem(top_menu, item, element) - else: - AddMenuItem(top_menu, item, element) - i += 1 - - -# ------------------------------------------------------------------------------------------------------------------ # -# ------------------------------------------------------------------------------------------------------------------ # -# ===================================== TK CODE STARTS HERE ====================================================== # -# ------------------------------------------------------------------------------------------------------------------ # -# ------------------------------------------------------------------------------------------------------------------ # - -def PackFormIntoFrame(form, containing_frame, toplevel_form): - def CharWidthInPixels(): - return tkinter.font.Font().measure('A') # single character width - - border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH - # --------------------------------------------------------------------------- # - # **************** Use FlexForm to build the tkinter window ********** ----- # - # Building is done row by row. # - # --------------------------------------------------------------------------- # - focus_set = False - ######################### LOOP THROUGH ROWS ######################### - # *********** ------- Loop through ROWS ------- ***********# - for row_num, flex_row in enumerate(form.Rows): - ######################### LOOP THROUGH ELEMENTS ON ROW ######################### - # *********** ------- Loop through ELEMENTS ------- ***********# - # *********** Make TK Row ***********# - tk_row_frame = kvBoxLayout() - for col_num, element in enumerate(flex_row): - element.ParentForm = toplevel_form # save the button's parent form object - if toplevel_form.Font and (element.Font == DEFAULT_FONT or not element.Font): - font = toplevel_form.Font - element.Font = font - elif element.Font is not None: - font = element.Font - else: - font = DEFAULT_FONT - # ------- Determine Auto-Size setting on a cascading basis ------- # - if element.AutoSizeText is not None: # if element overide - auto_size_text = element.AutoSizeText - elif toplevel_form.AutoSizeText is not None: # if form override - auto_size_text = toplevel_form.AutoSizeText - else: - auto_size_text = DEFAULT_AUTOSIZE_TEXT - element_type = element.Type - # Set foreground color - text_color = element.TextColor - # Determine Element size - element_size = element.Size - if (element_size == (None, None) and element_type not in ( - ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): # user did not specify a size - element_size = toplevel_form.DefaultElementSize - elif (element_size == (None, None) and element_type in (ELEM_TYPE_BUTTON, ELEM_TYPE_BUTTONMENU)): - element_size = toplevel_form.DefaultButtonElementSize - else: - auto_size_text = False # if user has specified a size then it shouldn't autosize - full_element_pad = [0, 0, 0, 0] # Top, Right, Bottom, Left - elementpad = element.Pad if element.Pad is not None else toplevel_form.ElementPadding - if type(elementpad[0]) != tuple: # left and right - full_element_pad[1] = full_element_pad[3] = elementpad[0] - else: - full_element_pad[3], full_element_pad[1] = elementpad[0] - if type(elementpad[1]) != tuple: # top and bottom - full_element_pad[0] = full_element_pad[2] = elementpad[1] - else: - full_element_pad[0], full_element_pad[2] = elementpad[1] - - border_depth = toplevel_form.BorderDepth if toplevel_form.BorderDepth is not None else DEFAULT_BORDER_WIDTH - try: - if element.BorderWidth is not None: - border_depth = element.BorderWidth - except: - pass - # ------------------------- COLUMN element ------------------------- # - if element_type == ELEM_TYPE_COLUMN: - pass - # if element.Scrollable: - # col_frame = TkScrollableFrame(tk_row_frame, - # element.VerticalScrollOnly) # do not use yet! not working - # PackFormIntoFrame(element, col_frame.TKFrame, toplevel_form) - # col_frame.TKFrame.update() - # if element.Size == (None, None): # if no size specified, use column width x column height/2 - # col_frame.canvas.config(width=col_frame.TKFrame.winfo_reqwidth(), - # height=col_frame.TKFrame.winfo_reqheight() / 2) - # else: - # col_frame.canvas.config(width=element.Size[0], height=element.Size[1]) - # - # if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): - # col_frame.canvas.config(background=element.BackgroundColor) - # col_frame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, - # highlightthickness=0) - # col_frame.config(background=element.BackgroundColor, borderwidth=0, highlightthickness=0) - # else: - # col_frame = tk.Frame(tk_row_frame) - # PackFormIntoFrame(element, col_frame, toplevel_form) - # - # col_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') - # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: - # col_frame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor, - # highlightcolor=element.BackgroundColor) - # ------------------------- TEXT element ------------------------- # - elif element_type == ELEM_TYPE_TEXT: - element.KV_Label = kvlabel = kvLabel(text=element.DisplayText, id=element.Key, markup=True) - if element.TextColor != COLOR_SYSTEM_DEFAULT: - kvlabel.color = get_color_from_hex(element.TextColor) - - def update_rect(widget, *args): - print(f'Update rect {widget, args}') - # - # widget.canvas.pos = - # widget.canvas.size = widget.size - - - if element.BackgroundColor not in (COLOR_SYSTEM_DEFAULT, None): - color = get_color_from_hex(element.BackgroundColor) - element.Rect = Rectangle(pos=kvlabel.pos, size=kvlabel.size, color=color, background_color=color) - kvlabel.canvas.add(element.Rect) - kvlabel.bind(pos=lambda x,y: update_rect(element), size=lambda x,y: update_rect(element)) - - tk_row_frame.add_widget(element.KV_Label) - # kvlabel.canvas.rectangle.size = tk_row_frame.size - # kvlabel.canvas.rectangle.pos = tk_row_frame.pos - - # tk_row_frame.background_color = get_color_from_hex(element.BackgroundColor) - # print(f'Row size is {tk_row_frame.size}') - # kvlabel.text_size =tk_row_frame.size - # kvlabel.halign = 'left' - - # if element.Justification is not None: - # justification = element.Justification - # elif toplevel_win.TextJustification is not None: - # justification = toplevel_win.TextJustification - # else: - # justification = DEFAULT_TEXT_JUSTIFICATION - # if justification[0] == 'c': - # element.QT_Label.setAlignment(Qt.AlignCenter) - # elif justification[0] == 'r': - # element.QT_Label.setAlignment(Qt.AlignRight) - # if not auto_size_text: - # if element_size[0] is not None: - # element.QT_Label.setFixedWidth(element_size[0]) - # if element_size[1] is not None: - # element.QT_Label.setFixedHeight(element_size[1]) - # # element.QT_Label.setWordWrap(True) - # style = create_style_from_font(font) - # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: - # style += 'color: %s;' % element.TextColor - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # style += 'background-color: %s;' % element.BackgroundColor - # element.QT_Label.setStyleSheet(style) - # - # if element.ClickSubmits: - # element.QT_Label.mousePressEvent = element.QtCallbackTextClicked - # - # if element.Relief is not None: - # if element.Relief in (RELIEF_RIDGE, RELIEF_RAISED): - # qlabel.setFrameStyle(QFrame.Panel | QFrame.Raised) - # elif element.Relief in (RELIEF_SUNKEN, RELIEF_GROOVE): - # qlabel.setFrameStyle(QFrame.Panel | QFrame.Sunken) - # elif element.Relief == RELIEF_FLAT: - # qlabel.setFrameStyle(QFrame.Panel | QFrame.NoFrame) - # - # if element.Margins is not None: - # m = element.Margins - # qlabel.setContentsMargins(m[0], m[2], m[1], m[3]) # L T B R - # if element.Tooltip: - # element.QT_Label.setToolTip(element.Tooltip) - - - - pass - # auto_size_text = element.AutoSizeText - # display_text = element.DisplayText # text to display - # if auto_size_text is False: - # width, height = element_size - # else: - # lines = display_text.split('\n') - # max_line_len = max([len(l) for l in lines]) - # num_lines = len(lines) - # if max_line_len > element_size[0]: # if text exceeds element size, the will have to wrap - # width = element_size[0] - # else: - # width = max_line_len - # height = num_lines - # ---===--- LABEL widget create and place --- # - # stringvar = tk.StringVar() - # element.TKStringVar = stringvar - # stringvar.set(display_text) - # if auto_size_text: - # width = 0 - # if element.Justification is not None: - # justification = element.Justification - # elif toplevel_form.TextJustification is not None: - # justification = toplevel_form.TextJustification - # else: - # justification = DEFAULT_TEXT_JUSTIFICATION - # justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT - # anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE - # tktext_label = tk.Label(tk_row_frame, textvariable=stringvar, width=width, height=height, - # justify=justify, bd=border_depth, font=font) - # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS - # wraplen = tktext_label.winfo_reqwidth() + 40 # width of widget in Pixels - # if not auto_size_text and height == 1: - # wraplen = 0 - # print("wraplen, width, height", wraplen, width, height) - # tktext_label.configure(anchor=anchor, wraplen=wraplen) # set wrap to width of widget - # if element.Relief is not None: - # tktext_label.configure(relief=element.Relief) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # tktext_label.configure(background=element.BackgroundColor) - # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: - # tktext_label.configure(fg=element.TextColor) - # tktext_label.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True) - # element.TKText = tktext_label - # if element.ClickSubmits: - # tktext_label.bind('', element.TextClickedHandler) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- BUTTON element ------------------------- # - elif element_type == ELEM_TYPE_BUTTON: - bg = get_color_from_hex(element.ButtonColor[1]) - fg = get_color_from_hex(element.ButtonColor[0]) - button = element.KV_Button = kvButton(text=element.ButtonText, id=element.Key, color=fg) - print(f'{element.ButtonColor[1]}') - button.background_color = bg - tk_row_frame.add_widget(element.KV_Button) - - # stringvar = tk.StringVar() - # element.TKStringVar = stringvar - # element.Location = (row_num, col_num) - # btext = element.ButtonText - # btype = element.BType - # if element.AutoSizeButton is not None: - # auto_size = element.AutoSizeButton - # else: - # auto_size = toplevel_form.AutoSizeButtons - # if auto_size is False or element.Size[0] is not None: - # width, height = element_size - # else: - # width = 0 - # height = toplevel_form.DefaultButtonElementSize[1] - # if element.ButtonColor != (None, None) and element.ButtonColor != DEFAULT_BUTTON_COLOR: - # bc = element.ButtonColor - # elif toplevel_form.ButtonColor != (None, None) and toplevel_form.ButtonColor != DEFAULT_BUTTON_COLOR: - # bc = toplevel_form.ButtonColor - # else: - # bc = DEFAULT_BUTTON_COLOR - # border_depth = element.BorderWidth - # if btype != BUTTON_TYPE_REALTIME: - # tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, - # command=element.ButtonCallBack, justify=tk.LEFT, bd=border_depth, font=font) - # else: - # tkbutton = tk.Button(tk_row_frame, text=btext, width=width, height=height, justify=tk.LEFT, - # bd=border_depth, 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: - # tkbutton.config(foreground=bc[0], background=bc[1], activebackground=bc[1]) - # elif bc[1] == COLOR_SYSTEM_DEFAULT: - # tkbutton.config(foreground=bc[0]) - # - # element.TKButton = tkbutton # not used yet but save the TK button in case - # wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels - # if element.ImageFilename: # if button has an image on it - # tkbutton.config(highlightthickness=0) - # photo = tk.PhotoImage(file=element.ImageFilename) - # if element.ImageSize != (None, None): - # width, height = element.ImageSize - # if element.ImageSubsample: - # photo = photo.subsample(element.ImageSubsample) - # else: - # width, height = photo.width(), photo.height() - # tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) - # tkbutton.image = photo - # if element.ImageData: # if button has an image on it - # tkbutton.config(highlightthickness=0) - # photo = tk.PhotoImage(data=element.ImageData) - # if element.ImageSize != (None, None): - # width, height = element.ImageSize - # if element.ImageSubsample: - # photo = photo.subsample(element.ImageSubsample) - # else: - # width, height = photo.width(), photo.height() - # tkbutton.config(image=photo, compound=tk.CENTER, width=width, height=height) - # tkbutton.image = photo - # if width != 0: - # tkbutton.configure(wraplength=wraplen + 10) # set wrap to width of widget - # tkbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.BindReturnKey: - # element.TKButton.bind('', element.ReturnKeyHandler) - # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): - # focus_set = True - # element.TKButton.bind('', element.ReturnKeyHandler) - # element.TKButton.focus_set() - # toplevel_form.TKroot.focus_force() - # if element.Disabled == True: - # element.TKButton['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # # ------------------------- INPUT (Single Line) element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_TEXT: - element.KV_TextInpput = kvinput = kvTextInput(text=element.DefaultText, multiline=False) - tk_row_frame.add_widget(element.KV_TextInpput) - - # default_text = element.DefaultText - # element.TKStringVar = tk.StringVar() - # element.TKStringVar.set(default_text) - # show = element.PasswordCharacter if element.PasswordCharacter else "" - # if element.Justification is not None: - # justification = element.Justification - # else: - # justification = DEFAULT_TEXT_JUSTIFICATION - # justify = tk.LEFT if justification == 'left' else tk.CENTER if justification == 'center' else tk.RIGHT - # # anchor = tk.NW if justification == 'left' else tk.N if justification == 'center' else tk.NE - # element.TKEntry = tk.Entry(tk_row_frame, width=element_size[0], textvariable=element.TKStringVar, - # bd=border_depth, font=font, show=show, justify=justify) - # if element.ChangeSubmits: - # element.TKEntry.bind('', element.KeyboardHandler) - # element.TKEntry.bind('', element.ReturnKeyHandler) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element.TKEntry.configure(background=element.BackgroundColor) - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # element.TKEntry.configure(fg=text_color) - # element.TKEntry.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='x') - # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): - # focus_set = True - # element.TKEntry.focus_set() - # if element.Disabled: - # element.TKEntry['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKEntry, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- COMBO BOX (Drop Down) element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_COMBO: - pass - - # max_line_len = max([len(str(l)) for l in element.Values]) - # if auto_size_text is False: - # width = element_size[0] - # else: - # width = max_line_len - # element.TKStringVar = tk.StringVar() - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # combostyle = ttk.Style() - # try: - # combostyle.theme_create('combostyle', - # settings={'TCombobox': - # {'configure': - # {'selectbackground': element.BackgroundColor, - # 'fieldbackground': element.BackgroundColor, - # 'foreground': text_color, - # 'background': element.BackgroundColor} - # }}) - # except: - # try: - # combostyle.theme_settings('combostyle', - # settings={'TCombobox': - # {'configure': - # {'selectbackground': element.BackgroundColor, - # 'fieldbackground': element.BackgroundColor, - # 'foreground': text_color, - # 'background': element.BackgroundColor} - # }}) - # except: - # pass - # # ATTENTION: this applies the new style 'combostyle' to all ttk.Combobox - # combostyle.theme_use('combostyle') - # element.TKCombo = ttk.Combobox(tk_row_frame, width=width, textvariable=element.TKStringVar, font=font) - # if element.Size[1] != 1 and element.Size[1] is not None: - # element.TKCombo.configure(height=element.Size[1]) - # # element.TKCombo['state']='readonly' - # element.TKCombo['values'] = element.Values - # - # # if element.InitializeAsDisabled: - # # element.TKCombo['state'] = 'disabled' - # # if element.BackgroundColor is not None: - # # element.TKCombo.configure(background=element.BackgroundColor) - # element.TKCombo.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.DefaultValue: - # for i, v in enumerate(element.Values): - # if v == element.DefaultValue: - # element.TKCombo.current(i) - # break - # else: - # element.TKCombo.current(0) - # if element.ChangeSubmits: - # element.TKCombo.bind('<>', element.ComboboxSelectHandler) - # if element.Readonly: - # element.TKCombo['state'] = 'readonly' - # if element.Disabled is True: # note overrides readonly if disabled - # element.TKCombo['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- OPTION MENU (Like ComboBox but different) element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_OPTION_MENU: - pass - # max_line_len = max([len(str(l)) for l in element.Values]) - # if auto_size_text is False: - # width = element_size[0] - # else: - # width = max_line_len - # element.TKStringVar = tk.StringVar() - # default = element.DefaultValue if element.DefaultValue else element.Values[0] - # element.TKStringVar.set(default) - # element.TKOptionMenu = tk.OptionMenu(tk_row_frame, element.TKStringVar, *element.Values) - # element.TKOptionMenu.config(highlightthickness=0, font=font, width=width) - # element.TKOptionMenu.config(borderwidth=border_depth) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element.TKOptionMenu.configure(background=element.BackgroundColor) - # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: - # element.TKOptionMenu.configure(fg=element.TextColor) - # element.TKOptionMenu.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.Disabled == True: - # element.TKOptionMenu['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # # ------------------------- LISTBOX element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_LISTBOX: - pass - # max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) != 0 else 0 - # if auto_size_text is False: - # width = element_size[0] - # else: - # width = max_line_len - # listbox_frame = tk.Frame(tk_row_frame) - # element.TKStringVar = tk.StringVar() - # element.TKListbox = tk.Listbox(listbox_frame, height=element_size[1], width=width, - # selectmode=element.SelectMode, font=font) - # for index, item in enumerate(element.Values): - # element.TKListbox.insert(tk.END, item) - # if element.DefaultValues is not None and item in element.DefaultValues: - # element.TKListbox.selection_set(index) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element.TKListbox.configure(background=element.BackgroundColor) - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # element.TKListbox.configure(fg=text_color) - # if element.ChangeSubmits: - # element.TKListbox.bind('<>', element.ListboxSelectHandler) - # vsb = tk.Scrollbar(listbox_frame, orient="vertical", command=element.TKListbox.yview) - # element.TKListbox.configure(yscrollcommand=vsb.set) - # element.TKListbox.pack(side=tk.LEFT) - # vsb.pack(side=tk.LEFT, fill='y') - # listbox_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.BindReturnKey: - # element.TKListbox.bind('', element.ListboxSelectHandler) - # element.TKListbox.bind('', element.ListboxSelectHandler) - # if element.Disabled == True: - # element.TKListbox['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKListbox, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- INPUT MULTI LINE element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_MULTILINE: - pass - # default_text = element.DefaultText - # width, height = element_size - # element.TKText = tk.scrolledtext.ScrolledText(tk_row_frame, width=width, height=height, wrap='word', - # bd=border_depth, font=font) - # element.TKText.insert(1.0, default_text) # set the default text - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element.TKText.configure(background=element.BackgroundColor) - # element.TKText.vbar.config(troughcolor=DEFAULT_SCROLLBAR_COLOR) - # element.TKText.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') - # if element.ChangeSubmits: - # element.TKText.bind('', element.KeyboardHandler) - # if element.EnterSubmits: - # element.TKText.bind('', element.ReturnKeyHandler) - # if element.Focus is True or (toplevel_form.UseDefaultFocus and not focus_set): - # focus_set = True - # element.TKText.focus_set() - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # element.TKText.configure(fg=text_color) - # if element.Disabled == True: - # element.TKText['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKText, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- INPUT CHECKBOX element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_CHECKBOX: - pass - # width = 0 if auto_size_text else element_size[0] - # default_value = element.InitialState - # element.TKIntVar = tk.IntVar() - # element.TKIntVar.set(default_value if default_value is not None else 0) - # if element.ChangeSubmits: - # element.TKCheckbutton = tk.Checkbutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, - # variable=element.TKIntVar, bd=border_depth, font=font, - # command=element.CheckboxHandler) - # else: - # element.TKCheckbutton = tk.Checkbutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, - # variable=element.TKIntVar, bd=border_depth, font=font) - # if default_value is None or element.Disabled: - # element.TKCheckbutton.configure(state='disable') - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element.TKCheckbutton.configure(background=element.BackgroundColor) - # element.TKCheckbutton.configure(selectcolor=element.BackgroundColor) - # element.TKCheckbutton.configure(activebackground=element.BackgroundColor) - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # element.TKCheckbutton.configure(fg=text_color) - # element.TKCheckbutton.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKCheckbutton, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # # ------------------------- PROGRESS BAR element ------------------------- # - elif element_type == ELEM_TYPE_PROGRESS_BAR: - pass - # # save this form because it must be 'updated' (refreshed) solely for the purpose of updating bar - # width = element_size[0] - # fnt = tkinter.font.Font() - # char_width = fnt.measure('A') # single character width - # progress_length = width * char_width - # progress_width = element_size[1] - # direction = element.Orientation - # if element.BarColor != (None, None): # if element has a bar color, use it - # bar_color = element.BarColor - # else: - # bar_color = DEFAULT_PROGRESS_BAR_COLOR - # element.TKProgressBar = TKProgressBar(tk_row_frame, element.MaxValue, progress_length, progress_width, - # orientation=direction, BarColor=bar_color, - # border_width=element.BorderWidth, relief=element.Relief, - # style=element.BarStyle, key=element.Key) - # element.TKProgressBar.TKProgressBarForReal.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # ------------------------- INPUT RADIO BUTTON element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_RADIO: - pass - # width = 0 if auto_size_text else element_size[0] - # default_value = element.InitialState - # ID = element.GroupID - # # see if ID has already been placed - # value = EncodeRadioRowCol(row_num, col_num) # value to set intvar to if this radio is selected - # if ID in toplevel_form.RadioDict: - # RadVar = toplevel_form.RadioDict[ID] - # else: - # RadVar = tk.IntVar() - # toplevel_form.RadioDict[ID] = RadVar - # element.TKIntVar = RadVar # store the RadVar in Radio object - # if default_value: # if this radio is the one selected, set RadVar to match - # element.TKIntVar.set(value) - # if element.ChangeSubmits: - # element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, - # variable=element.TKIntVar, value=value, bd=border_depth, font=font, - # command=element.RadioHandler) - # else: - # element.TKRadio = tk.Radiobutton(tk_row_frame, anchor=tk.NW, text=element.Text, width=width, - # variable=element.TKIntVar, value=value, bd=border_depth, font=font) - # if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): - # element.TKRadio.configure(background=element.BackgroundColor) - # element.TKRadio.configure(selectcolor=element.BackgroundColor) - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # element.TKRadio.configure(fg=text_color) - # if element.Disabled: - # element.TKRadio['state'] = 'disabled' - # element.TKRadio.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- INPUT SPIN Box element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_SPIN: - pass - # width, height = element_size - # width = 0 if auto_size_text else element_size[0] - # element.TKStringVar = tk.StringVar() - # element.TKSpinBox = tk.Spinbox(tk_row_frame, values=element.Values, textvariable=element.TKStringVar, - # width=width, bd=border_depth) - # element.TKStringVar.set(element.DefaultValue) - # element.TKSpinBox.configure(font=font) # set wrap to width of widget - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element.TKSpinBox.configure(background=element.BackgroundColor) - # element.TKSpinBox.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # element.TKSpinBox.configure(fg=text_color) - # if element.ChangeSubmits: - # element.TKSpinBox.bind('', element.SpinChangedHandler) - # if element.Disabled == True: - # element.TKSpinBox['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- OUTPUT element ------------------------- # - elif element_type == ELEM_TYPE_OUTPUT: - pass - # width, height = element_size - # element._TKOut = TKOutput(tk_row_frame, width=width, height=height, bd=border_depth, - # background_color=element.BackgroundColor, text_color=text_color, font=font, - # pad=element.Pad) - # element._TKOut.pack(side=tk.LEFT, expand=True, fill='both') - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element._TKOut, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- IMAGE element ------------------------- # - elif element_type == ELEM_TYPE_IMAGE: - pass - # if element.Filename is not None: - # photo = tk.PhotoImage(file=element.Filename) - # elif element.Data is not None: - # photo = tk.PhotoImage(data=element.Data) - # else: - # photo = None - # print('*ERROR laying out form.... Image Element has no image specified*') - # - # if photo is not None: - # if element_size == ( - # None, None) or element_size == None or element_size == toplevel_form.DefaultElementSize: - # width, height = photo.width(), photo.height() - # else: - # width, height = element_size - # if photo is not None: - # element.tktext_label = tk.Label(tk_row_frame, image=photo, width=width, height=height, - # bd=border_depth) - # else: - # element.tktext_label = tk.Label(tk_row_frame, width=width, height=height, bd=border_depth) - # if element.BackgroundColor is not None: - # element.tktext_label.config(background=element.BackgroundColor); - # - # element.tktext_label.image = photo - # # tktext_label.configure(anchor=tk.NW, image=photo) - # element.tktext_label.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.tktext_label, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- Canvas element ------------------------- # - elif element_type == ELEM_TYPE_CANVAS: - pass - # width, height = element_size - # if element._TKCanvas is None: - # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) - # else: - # element._TKCanvas.master = tk_row_frame - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) - # element._TKCanvas.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - - # ------------------------- Graph element ------------------------- # - elif element_type == ELEM_TYPE_GRAPH: - pass - # width, height = element_size - # if element._TKCanvas is None: - # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) - # else: - # element._TKCanvas.master = tk_row_frame - # element._TKCanvas2 = tk.Canvas(element._TKCanvas, width=width, height=height, bd=border_depth) - # element._TKCanvas2.pack(side=tk.LEFT) - # element._TKCanvas2.addtag_all('mytag') - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0) - # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) - # element._TKCanvas.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # if element.ChangeSubmits: - # element._TKCanvas2.bind('', element.ButtonReleaseCallBack) - # element._TKCanvas2.bind('', element.ButtonPressCallBack) - # if element.DragSubmits: - # element._TKCanvas2.bind('', element.MotionCallBack) - # ------------------------- MENUBAR element ------------------------- # - elif element_type == ELEM_TYPE_MENUBAR: - pass - # menu_def = element.MenuDefinition - # element.TKMenu = tk.Menu(toplevel_form.TKroot, tearoff=element.Tearoff) # create the menubar - # menubar = element.TKMenu - # for menu_entry in menu_def: - # # print(f'Adding a Menubar ENTRY {menu_entry}') - # baritem = tk.Menu(menubar, tearoff=element.Tearoff) - # pos = menu_entry[0].find('&') - # # print(pos) - # if pos != -1: - # if pos == 0 or menu_entry[0][pos - 1] != "\\": - # menu_entry[0] = menu_entry[0][:pos] + menu_entry[0][pos + 1:] - # menubar.add_cascade(label=menu_entry[0], menu=baritem, underline=pos) - # if len(menu_entry) > 1: - # AddMenuItem(baritem, menu_entry[1], element) - # toplevel_form.TKroot.configure(menu=element.TKMenu) - # ------------------------- Frame element ------------------------- # - elif element_type == ELEM_TYPE_FRAME: - pass - # labeled_frame = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief) - # PackFormIntoFrame(element, labeled_frame, toplevel_form) - # labeled_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: - # labeled_frame.configure(background=element.BackgroundColor, - # highlightbackground=element.BackgroundColor, - # highlightcolor=element.BackgroundColor) - # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: - # labeled_frame.configure(foreground=element.TextColor) - # if font is not None: - # labeled_frame.configure(font=font) - # if element.TitleLocation is not None: - # labeled_frame.configure(labelanchor=element.TitleLocation) - # if element.BorderWidth is not None: - # labeled_frame.configure(borderwidth=element.BorderWidth) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(labeled_frame, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- Tab element ------------------------- # - elif element_type == ELEM_TYPE_TAB: - pass - # element.TKFrame = tk.Frame(form.TKNotebook) - # PackFormIntoFrame(element, element.TKFrame, toplevel_form) - # if element.Disabled: - # form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled') - # else: - # form.TKNotebook.add(element.TKFrame, text=element.Title) - # form.TKNotebook.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # element.ParentNotebook = form.TKNotebook - # element.TabID = form.TabCount - # form.TabCount += 1 - # if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: - # element.TKFrame.configure(background=element.BackgroundColor, - # highlightbackground=element.BackgroundColor, - # highlightcolor=element.BackgroundColor) - # # if element.TextColor != COLOR_SYSTEM_DEFAULT and element.TextColor is not None: - # # element.TKFrame.configure(foreground=element.TextColor) - # - # # ttk.Style().configure("TNotebook", background='red') - # # ttk.Style().map("TNotebook.Tab", background=[("selected", 'orange')], - # # foreground=[("selected", 'green')]) - # # ttk.Style().configure("TNotebook.Tab", background='blue', foreground='yellow') - # - # if element.BorderWidth is not None: - # element.TKFrame.configure(borderwidth=element.BorderWidth) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKFrame, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- TabGroup element ------------------------- # - elif element_type == ELEM_TYPE_TAB_GROUP: - pass - - # custom_style = str(element.Key) + 'customtab.TNotebook' - # style = ttk.Style(tk_row_frame) - # if element.Theme is not None: - # style.theme_use(element.Theme) - # if element.TabLocation is not None: - # position_dict = {'left': 'w', 'right': 'e', 'top': 'n', 'bottom': 's', 'lefttop': 'wn', - # 'leftbottom': 'ws', 'righttop': 'en', 'rightbottom': 'es', 'bottomleft': 'sw', - # 'bottomright': 'se', 'topleft': 'nw', 'topright': 'ne'} - # try: - # tab_position = position_dict[element.TabLocation] - # except: - # tab_position = position_dict['top'] - # style.configure(custom_style, tabposition=tab_position) - # - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # style.configure(custom_style, background=element.BackgroundColor, foreground='purple') - # - # # style.theme_create("yummy", parent="alt", settings={ - # # "TNotebook": {"configure": {"tabmargins": [2, 5, 2, 0]}}, - # # "TNotebook.Tab": { - # # "configure": {"padding": [5, 1], "background": mygreen}, - # # "map": {"background": [("selected", myred)], - # # "expand": [("selected", [1, 1, 1, 0])]}}}) - # - # # style.configure(custom_style+'.Tab', background='red') - # if element.SelectedTitleColor != None: - # style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)]) - # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: - # style.configure(custom_style + '.Tab', foreground=element.TextColor) - # # style.configure(custom_style, background='blue', foreground='yellow') - # - # element.TKNotebook = ttk.Notebook(tk_row_frame, style=custom_style) - # - # PackFormIntoFrame(element, toplevel_form.TKroot, toplevel_form) - # - # if element.ChangeSubmits: - # element.TKNotebook.bind('<>', element.TabGroupSelectHandler) - # if element.BorderWidth is not None: - # element.TKNotebook.configure(borderwidth=element.BorderWidth) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- SLIDER Box element ------------------------- # - elif element_type == ELEM_TYPE_INPUT_SLIDER: - pass - # slider_length = element_size[0] * CharWidthInPixels() - # slider_width = element_size[1] - # element.TKIntVar = tk.IntVar() - # element.TKIntVar.set(element.DefaultValue) - # if element.Orientation[0] == 'v': - # range_from = element.Range[1] - # range_to = element.Range[0] - # slider_length += DEFAULT_MARGINS[1] * (element_size[0] * 2) # add in the padding - # else: - # range_from = element.Range[0] - # range_to = element.Range[1] - # if element.ChangeSubmits: - # tkscale = tk.Scale(tk_row_frame, orient=element.Orientation, variable=element.TKIntVar, - # from_=range_from, to_=range_to, resolution=element.Resolution, - # length=slider_length, width=slider_width, bd=element.BorderWidth, - # relief=element.Relief, font=font, tickinterval=element.TickInterval, - # command=element.SliderChangedHandler) - # else: - # tkscale = tk.Scale(tk_row_frame, orient=element.Orientation, variable=element.TKIntVar, - # from_=range_from, to_=range_to, resolution=element.Resolution, - # length=slider_length, width=slider_width, bd=element.BorderWidth, - # relief=element.Relief, font=font, tickinterval=element.TickInterval) - # tkscale.config(highlightthickness=0) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # tkscale.configure(background=element.BackgroundColor) - # if DEFAULT_SCROLLBAR_COLOR != COLOR_SYSTEM_DEFAULT: - # tkscale.config(troughcolor=DEFAULT_SCROLLBAR_COLOR) - # if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: - # tkscale.configure(fg=text_color) - # tkscale.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - # element.TKScale = tkscale - # if element.Disabled == True: - # element.TKScale['state'] = 'disabled' - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKScale, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- TABLE element ------------------------- # - elif element_type == ELEM_TYPE_TABLE: - pass - # frame = tk.Frame(tk_row_frame) - # - # height = element.NumRows - # if element.Justification == 'left': - # anchor = tk.W - # elif element.Justification == 'right': - # anchor = tk.E - # else: - # anchor = tk.CENTER - # column_widths = {} - # for row in element.Values: - # for i, col in enumerate(row): - # col_width = min(len(str(col)), element.MaxColumnWidth) - # try: - # if col_width > column_widths[i]: - # column_widths[i] = col_width - # except: - # column_widths[i] = col_width - # if element.ColumnsToDisplay is None: - # displaycolumns = element.ColumnHeadings - # else: - # displaycolumns = [] - # for i, should_display in enumerate(element.ColumnsToDisplay): - # if should_display: - # displaycolumns.append(element.ColumnHeadings[i]) - # column_headings = element.ColumnHeadings - # if element.DisplayRowNumbers: # if display row number, tack on the numbers to front of columns - # displaycolumns = [element.RowHeaderText, ] + displaycolumns - # column_headings = [element.RowHeaderText, ] + element.ColumnHeadings - # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, - # displaycolumns=displaycolumns, show='headings', height=height, - # selectmode=element.SelectMode) - # treeview = element.TKTreeview - # if element.DisplayRowNumbers: - # treeview.heading(element.RowHeaderText, text=element.RowHeaderText) # make a dummy heading - # treeview.column(element.RowHeaderText, width=50, anchor=anchor) - # for i, heading in enumerate(element.ColumnHeadings): - # treeview.heading(heading, text=heading) - # if element.AutoSizeColumns: - # width = max(column_widths[i], len(heading)) - # else: - # try: - # width = element.ColumnWidths[i] - # except: - # width = element.DefaultColumnWidth - # - # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) - # # Insert values into the tree - # for i, value in enumerate(element.Values): - # if element.DisplayRowNumbers: - # value = [i + element.StartingRowNumber] + value - # id = treeview.insert('', 'end', text=value, iid=i + 1, values=value, tag=i % 2) - # if element.AlternatingRowColor is not None: - # treeview.tag_configure(1, background=element.AlternatingRowColor) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # ttk.Style().configure("Treeview", background=element.BackgroundColor, - # fieldbackground=element.BackgroundColor) - # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: - # ttk.Style().configure("Treeview", foreground=element.TextColor) - # # scrollable_frame.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], expand=True, fill='both') - # treeview.bind("<>", element.treeview_selected) - # if element.BindReturnKey: - # treeview.bind('', element.treeview_double_click) - # treeview.bind('', element.treeview_double_click) - # scrollbar = tk.Scrollbar(frame) - # scrollbar.pack(side=tk.RIGHT, fill='y') - # scrollbar.config(command=treeview.yview) - # treeview.configure(yscrollcommand=scrollbar.set) - # - # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') - # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) - # if element.Tooltip is not None: - # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- Tree element ------------------------- # - elif element_type == ELEM_TYPE_TREE: - pass - # frame = tk.Frame(tk_row_frame) - # - # height = element.NumRows - # if element.Justification == 'left': # justification - # anchor = tk.W - # elif element.Justification == 'right': - # anchor = tk.E - # else: - # anchor = tk.CENTER - # - # if element.ColumnsToDisplay is None: # Which cols to display - # displaycolumns = element.ColumnHeadings - # else: - # displaycolumns = [] - # for i, should_display in enumerate(element.ColumnsToDisplay): - # if should_display: - # displaycolumns.append(element.ColumnHeadings[i]) - # column_headings = element.ColumnHeadings - # # ------------- GET THE TREEVIEW WIDGET ------------- - # element.TKTreeview = ttk.Treeview(frame, columns=column_headings, - # displaycolumns=displaycolumns, show='tree headings', height=height, - # selectmode=element.SelectMode, ) - # treeview = element.TKTreeview - # for i, heading in enumerate(element.ColumnHeadings): # Configure cols + headings - # treeview.heading(heading, text=heading) - # if element.AutoSizeColumns: - # width = min(element.MaxColumnWidth, len(heading) + 1) - # else: - # try: - # width = element.ColumnWidths[i] - # except: - # width = element.DefaultColumnWidth - # treeview.column(heading, width=width * CharWidthInPixels(), anchor=anchor) - # - # def add_treeview_data(node): - # # print(f'Inserting {node.key} under parent {node.parent}') - # if node.key != '': - # treeview.insert(node.parent, 'end', node.key, text=node.text, values=node.values, - # open=element.ShowExpanded) - # for node in node.children: - # add_treeview_data(node) - # - # add_treeview_data(element.TreeData.root_node) - # treeview.column('#0', width=element.Col0Width * CharWidthInPixels(), anchor=anchor) - # # ----- configure colors ----- - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # ttk.Style().configure("Treeview", background=element.BackgroundColor, - # fieldbackground=element.BackgroundColor) - # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: - # ttk.Style().configure("Treeview", foreground=element.TextColor) - # - # scrollbar = tk.Scrollbar(frame) - # scrollbar.pack(side=tk.RIGHT, fill='y') - # scrollbar.config(command=treeview.yview) - # treeview.configure(yscrollcommand=scrollbar.set) - # element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') - # frame.pack(side=tk.LEFT, expand=True, padx=0, pady=0) - # treeview.bind("<>", element.treeview_selected) - # if element.Tooltip is not None: # tooltip - # element.TooltipObject = ToolTip(element.TKTreeview, text=element.Tooltip, - # timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- Separator element ------------------------- # - elif element_type == ELEM_TYPE_SEPARATOR: - pass - # separator = ttk.Separator(tk_row_frame, orient=element.Orientation, ) - # separator.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1], fill='both', expand=True) - # - # # ............................DONE WITH ROW pack the row of widgets ..........................# - # done with row, pack the row of widgets - containing_frame.add_widget(tk_row_frame) - # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) - # tk_row_frame.pack(side=tk.TOP, anchor='nw', padx=DEFAULT_MARGINS[0], expand=False) - # if form.BackgroundColor is not None and form.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # tk_row_frame.configure(background=form.BackgroundColor) - # toplevel_form.TKroot.configure(padx=DEFAULT_MARGINS[0], pady=DEFAULT_MARGINS[1]) - return - - -def ConvertFlexToTK(window): - master = window.TKroot - # Set Title - # master.title(MyFlexForm.Title) - master = 00000 - - InitializeResults(window) - if window.NoTitleBar: - window.TKroot.wm_overrideredirect(True) - PackFormIntoFrame(window, master, window) - # ....................................... DONE creating and laying out window ..........................# - # if MyFlexForm._Size != (None, None): - # master.geometry("%sx%s" % (MyFlexForm._Size[0], MyFlexForm._Size[1])) - - # Center in middle of screen - # screen_width = master.winfo_screenwidth() # get window info to move to middle of screen - # screen_height = master.winfo_screenheight() - # if window.Location != (None, None): - # x, y = window.Location - # elif DEFAULT_WINDOW_LOCATION != (None, None): - # x, y = DEFAULT_WINDOW_LOCATION - # else: - # master.update_idletasks() # don't forget to do updates or values are bad - # win_width = master.winfo_width() - # win_height = master.winfo_height() - # x = screen_width / 2 - win_width / 2 - # y = screen_height / 2 - win_height / 2 - # if y + win_height > screen_height: - # y = screen_height - win_height - # if x + win_width > screen_width: - # x = screen_width - win_width - # - # move_string = '+%i+%i' % (int(x), int(y)) - # master.geometry(move_string) - # - # master.update_idletasks() # don't forget - - return - - -# ----====----====----====----====----==== STARTUP TK ====----====----====----====----====----# -def StartupTK(window): - global _my_windows - - ow = _my_windows.NumOpenWindows - - # print('Starting TK open Windows = {}'.format(ow)) - # if not ow and not window.ForceTopLevel: - # 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 - # hidden window - # _my_windows.Increment() - # _my_windows.hidden_master_root = tk.Tk() - # _my_windows.hidden_master_root.attributes('-alpha', 0) # HIDE this window really really really good - - # root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' - # root.wm_overrideredirect(True) - # if window.BackgroundColor is not None and window.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # root.configure(background=window.BackgroundColor) - _my_windows.Increment() - - root = window.KVApp - main_window_layout = kvBoxLayout(orientation='vertical') - - # window.TKroot = root - # Make moveable window - # if (window.GrabAnywhere is not False and not ( - # window.NonBlocking and window.GrabAnywhere is not True)): - # root.bind("", window.StartMove) - # root.bind("", window.StopMove) - # root.bind("", window.OnMotion) - - # if not window.Resizable: - # root.resizable(False, False) - - # if window.KeepOnTop: - # root.wm_attributes("-topmost", 1) - - # ConvertFlexToTK(window) - - # master = window.TKroot - # Set Title - root.title = window.Title - master = 00000 - - # if window.NoTitleBar: - # window.TKroot.wm_overrideredirect(True) - InitializeResults(window) - - PackFormIntoFrame(window, main_window_layout, window) - - window.SetIcon(window.WindowIcon) - window.KVApp.opacity = window.AlphaChannel - kvWindow.color = get_color_from_hex('#111111') - if window._Size != (None, None): - kvWindow.size = window._Size - - - # root.attributes('-alpha', window.AlphaChannel) # Make window visible again - - # if window.ReturnKeyboardEvents and not window.NonBlocking: - # root.bind("", window._KeyboardCallback) - # root.bind("", window._MouseWheelCallback) - # elif window.ReturnKeyboardEvents: - # root.bind("", window._KeyboardCallback)PySimpleGUIKivy.py - # root.bind("", window._MouseWheelCallback) - - # if window.AutoClose: - # duration = DEFAULT_AUTOCLOSE_TIME if window.AutoCloseDuration is None else window.AutoCloseDuration - # window.TKAfterID = root.after(duration * 1000, window._AutoCloseAlarmCallback) - # - # if window.Timeout != None: - # window.TKAfterID = root.after(window.Timeout, window._TimeoutAlarmCallback) - # if window.NonBlocking: - # window.TKroot.protocol("WM_DESTROY_WINDOW", window.OnClosingCallback) - # window.TKroot.protocol("WM_DELETE_WINDOW", window.OnClosingCallback) - # else: # it's a blocking form - # print('..... CALLING MainLoop') - # window.CurrentlyRunningMainloop = True - # window.TKroot.protocol("WM_DESTROY_WINDOW", window.OnClosingCallback) - # window.TKroot.protocol("WM_DELETE_WINDOW", window.OnClosingCallback) - # window.TKroot.mainloop() - # window.CurrentlyRunningMainloop = False - # window.TimerCancelled = True - # print('..... BACK from MainLoop') - # if not window.FormRemainedOpen: - # _my_windows.Decrement() - # if window.RootNeedsDestroying: - # window.TKroot.destroy() - # window.RootNeedsDestroying = False - return main_window_layout - - -# ==============================_GetNumLinesNeeded ==# -# Helper function for determining how to wrap text # -# ===================================================# -def _GetNumLinesNeeded(text, max_line_width): - if max_line_width == 0: - return 1 - lines = text.split('\n') - num_lines = len(lines) # number of original lines of text - max_line_len = max([len(l) for l in lines]) # longest line - lines_used = [] - for L in lines: - lines_used.append(len(L) // max_line_width + (len(L) % max_line_width > 0)) # fancy math to round up - total_lines_needed = sum(lines_used) - return total_lines_needed - - -# ============================== PROGRESS METER ========================================== # - -def ConvertArgsToSingleString(*args): - max_line_total, width_used, total_lines, = 0, 0, 0 - single_line_message = '' - # loop through args and built a SINGLE string from them - for message in args: - # fancy code to check if string and convert if not is not need. Just always convert to string :-) - # if not isinstance(message, str): message = str(message) - message = str(message) - longest_line_len = max([len(l) for l in message.split('\n')]) - width_used = max(longest_line_len, width_used) - max_line_total = max(max_line_total, width_used) - lines_needed = _GetNumLinesNeeded(message, width_used) - total_lines += lines_needed - single_line_message += message + '\n' - return single_line_message, width_used, total_lines - - -# ============================== ProgressMeter =====# -# ===================================================# -def _ProgressMeter(title, max_value, *args, orientation=None, bar_color=(None, None), button_color=None, - size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): - ''' - Create and show a form on tbe caller's behalf. - :param title: - :param max_value: - :param args: ANY number of arguments the caller wants to display - :param orientation: - :param bar_color: - :param size: - :param Style: - :param StyleOffset: - :return: ProgressBar object that is in the form - ''' - local_orientation = DEFAULT_METER_ORIENTATION if orientation is None else orientation - local_border_width = DEFAULT_PROGRESS_BAR_BORDER_WIDTH if border_width is None else border_width - bar2 = ProgressBar(max_value, orientation=local_orientation, size=size, bar_color=bar_color, - border_width=local_border_width, relief=DEFAULT_PROGRESS_BAR_RELIEF) - form = Window(title, auto_size_text=True, grab_anywhere=grab_anywhere) - - # Form using a horizontal bar - if local_orientation[0].lower() == 'h': - single_line_message, width, height = ConvertArgsToSingleString(*args) - bar2.TextToDisplay = single_line_message - bar2.MaxValue = max_value - bar2.CurrentValue = 0 - bar_text = Text(single_line_message, size=(width, height + 3), auto_size_text=True) - form.AddRow(bar_text) - form.AddRow((bar2)) - form.AddRow((CloseButton('Cancel', button_color=button_color))) - else: - single_line_message, width, height = ConvertArgsToSingleString(*args) - bar2.TextToDisplay = single_line_message - bar2.MaxValue = max_value - bar2.CurrentValue = 0 - bar_text = Text(single_line_message, size=(width, height + 3), auto_size_text=True) - form.AddRow(bar2, bar_text) - form.AddRow((CloseButton('Cancel', button_color=button_color))) - - form.NonBlocking = True - form.Show(non_blocking=True) - return bar2, bar_text - - -# ============================== ProgressMeterUpdate =====# -def _ProgressMeterUpdate(bar, value, text_elem, *args): - ''' - Update the progress meter for a form - :param form: class ProgressBar - :param value: int - :return: True if not cancelled, OK....False if Error - ''' - global _my_windows - if bar == None: return False - if bar.BarExpired: return False - message, w, h = ConvertArgsToSingleString(*args) - text_elem.Update(message) - # bar.TextToDisplay = message - bar.CurrentValue = value - rc = bar.UpdateBar(value) - if value >= bar.MaxValue or not rc: - bar.BarExpired = True - bar.ParentForm._Close() - if rc: # if update was OK but bar expired, decrement num windows - _my_windows.Decrement() - if bar.ParentForm.RootNeedsDestroying: - try: - bar.ParentForm.TKroot.destroy() - # there is a bug with progress meters not decrementing the number of windows - # correctly when the X is used to close the window - # uncommenting this line fixes that problem, but causes a double-decrement when - # the cancel button is used... damned if you do, damned if you don't, so I'm choosing - # don't, as in don't decrement too many times. It's OK now to have a mismatch in - # number of windows because of the "hidden" master window. This ensures all windows - # will be toplevel. Sorry about the bug, but the user never sees any problems as a result - # _my_windows.Decrement() - except: - pass - bar.ParentForm.RootNeedsDestroying = False - bar.ParentForm.__del__() - return False - - return rc - - -# ============================== EASY PROGRESS METER ========================================== # -# class to hold the easy meter info (a global variable essentialy) -class EasyProgressMeterDataClass(): - def __init__(self, title='', current_value=1, max_value=10, start_time=None, stat_messages=()): - self.Title = title - self.CurrentValue = current_value - self.MaxValue = max_value - self.StartTime = start_time - self.StatMessages = stat_messages - self.ParentForm = None - self.MeterID = None - self.MeterText = None - - # =========================== COMPUTE PROGRESS STATS ======================# - def ComputeProgressStats(self): - utc = datetime.datetime.utcnow() - time_delta = utc - self.StartTime - total_seconds = time_delta.total_seconds() - if not total_seconds: - total_seconds = 1 - try: - time_per_item = total_seconds / self.CurrentValue - except: - time_per_item = 1 - seconds_remaining = (self.MaxValue - self.CurrentValue) * time_per_item - time_remaining = str(datetime.timedelta(seconds=seconds_remaining)) - time_remaining_short = (time_remaining).split(".")[0] - time_delta_short = str(time_delta).split(".")[0] - total_time = time_delta + datetime.timedelta(seconds=seconds_remaining) - total_time_short = str(total_time).split(".")[0] - self.StatMessages = [ - '{} of {}'.format(self.CurrentValue, self.MaxValue), - '{} %'.format(100 * self.CurrentValue // self.MaxValue), - '', - ' {:6.2f} Iterations per Second'.format(self.CurrentValue / total_seconds), - ' {:6.2f} Seconds per Iteration'.format(total_seconds / (self.CurrentValue if self.CurrentValue else 1)), - '', - '{} Elapsed Time'.format(time_delta_short), - '{} Time Remaining'.format(time_remaining_short), - '{} Estimated Total Time'.format(total_time_short)] - return - - -# ============================== EasyProgressMeter =====# -def EasyProgressMeter(title, current_value, max_value, *args, orientation=None, bar_color=(None, None), - button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None): - ''' - A ONE-LINE progress meter. Add to your code where ever you need a meter. No need for a second - function call before your loop. You've got enough code to write! - :param title: Title will be shown on the window - :param current_value: Current count of your items - :param max_value: Max value your count will ever reach. This indicates it should be closed - :param args: VARIABLE number of arguements... you request it, we'll print it no matter what the item! - :param orientation: - :param bar_color: - :param size: - :param Style: - :param StyleOffset: - :return: False if should stop the meter - ''' - local_border_width = DEFAULT_PROGRESS_BAR_BORDER_WIDTH if not border_width else border_width - # STATIC VARIABLE! - # This is a very clever form of static variable using a function attribute - # If the variable doesn't yet exist, then it will create it and initialize with the 3rd parameter - EasyProgressMeter.Data = getattr(EasyProgressMeter, 'Data', EasyProgressMeterDataClass()) - # if no meter currently running - if EasyProgressMeter.Data.MeterID is None: # Starting a new meter - print( - "Please change your call of EasyProgressMeter to use OneLineProgressMeter. EasyProgressMeter will be removed soon") - if int(current_value) >= int(max_value): - return False - del (EasyProgressMeter.Data) - EasyProgressMeter.Data = EasyProgressMeterDataClass(title, 1, int(max_value), datetime.datetime.utcnow(), []) - EasyProgressMeter.Data.ComputeProgressStats() - message = "\n".join([line for line in EasyProgressMeter.Data.StatMessages]) - EasyProgressMeter.Data.MeterID, EasyProgressMeter.Data.MeterText = _ProgressMeter(title, int(max_value), - message, *args, - orientation=orientation, - bar_color=bar_color, - size=size, - button_color=button_color, - border_width=local_border_width) - EasyProgressMeter.Data.ParentForm = EasyProgressMeter.Data.MeterID.ParentForm - return True - # if exactly the same values as before, then ignore. - if EasyProgressMeter.Data.MaxValue == max_value and EasyProgressMeter.Data.CurrentValue == current_value: - return True - if EasyProgressMeter.Data.MaxValue != int(max_value): - EasyProgressMeter.Data.MeterID = None - EasyProgressMeter.Data.ParentForm = None - del (EasyProgressMeter.Data) - EasyProgressMeter.Data = EasyProgressMeterDataClass() # setup a new progress meter - return True # HAVE to return TRUE or else the new meter will thing IT is failing when it hasn't - EasyProgressMeter.Data.CurrentValue = int(current_value) - EasyProgressMeter.Data.MaxValue = int(max_value) - EasyProgressMeter.Data.ComputeProgressStats() - message = '' - for line in EasyProgressMeter.Data.StatMessages: - message = message + str(line) + '\n' - message = "\n".join(EasyProgressMeter.Data.StatMessages) - args = args + (message,) - rc = _ProgressMeterUpdate(EasyProgressMeter.Data.MeterID, current_value, - EasyProgressMeter.Data.MeterText, *args) - # if counter >= max then the progress meter is all done. Indicate none running - if current_value >= EasyProgressMeter.Data.MaxValue or not rc: - EasyProgressMeter.Data.MeterID = None - del (EasyProgressMeter.Data) - EasyProgressMeter.Data = EasyProgressMeterDataClass() # setup a new progress meter - return False # even though at the end, return True so don't cause error with the app - return rc # return whatever the update told us - - -def EasyProgressMeterCancel(title, *args): - EasyProgressMeter.EasyProgressMeterData = getattr(EasyProgressMeter, 'EasyProgressMeterData', - EasyProgressMeterDataClass()) - if EasyProgressMeter.EasyProgressMeterData.MeterID is not None: - # tell the normal meter update that we're at max value which will close the meter - rc = EasyProgressMeter(title, EasyProgressMeter.EasyProgressMeterData.MaxValue, - EasyProgressMeter.EasyProgressMeterData.MaxValue, ' *** CANCELLING ***', - 'Caller requested a cancel', *args) - return rc - return True - - -# global variable containing dictionary will all currently running one-line progress meters. -_one_line_progress_meters = {} - - -# ============================== OneLineProgressMeter =====# -def OneLineProgressMeter(title, current_value, max_value, key, *args, orientation=None, bar_color=(None, None), - button_color=None, size=DEFAULT_PROGRESS_BAR_SIZE, border_width=None, grab_anywhere=False): - global _one_line_progress_meters - - local_border_width = DEFAULT_PROGRESS_BAR_BORDER_WIDTH if border_width is not None else border_width - try: - meter_data = _one_line_progress_meters[key] - except: # a new meater is starting - if int(current_value) >= int(max_value): # if already expired then it's an old meter, ignore - return False - meter_data = EasyProgressMeterDataClass(title, 1, int(max_value), datetime.datetime.utcnow(), []) - _one_line_progress_meters[key] = meter_data - meter_data.ComputeProgressStats() - message = "\n".join([line for line in meter_data.StatMessages]) - meter_data.MeterID, meter_data.MeterText = _ProgressMeter(title, int(max_value), message, *args, - orientation=orientation, bar_color=bar_color, - size=size, button_color=button_color, - border_width=local_border_width, - grab_anywhere=grab_anywhere) - meter_data.ParentForm = meter_data.MeterID.ParentForm - return True - - # if exactly the same values as before, then ignore, return success. - if meter_data.MaxValue == max_value and meter_data.CurrentValue == current_value: - return True - meter_data.CurrentValue = int(current_value) - meter_data.MaxValue = int(max_value) - meter_data.ComputeProgressStats() - message = '' - for line in meter_data.StatMessages: - message = message + str(line) + '\n' - message = "\n".join(meter_data.StatMessages) - args = args + (message,) - rc = _ProgressMeterUpdate(meter_data.MeterID, current_value, - meter_data.MeterText, *args) - # if counter >= max then the progress meter is all done. Indicate none running - if current_value >= meter_data.MaxValue or not rc: - del _one_line_progress_meters[key] - return False - return rc # return whatever the update told us - - -def OneLineProgressMeterCancel(key): - global _one_line_progress_meters - - try: - meter_data = _one_line_progress_meters[key] - except: # meter is already deleted - return - OneLineProgressMeter('', meter_data.MaxValue, meter_data.MaxValue, key=key) - - -# input is #RRGGBB -# output is #RRGGBB -def GetComplimentaryHex(color): - # strip the # from the beginning - color = color[1:] - # convert the string into hex - color = int(color, 16) - # invert the three bytes - # as good as substracting each of RGB component by 255(FF) - comp_color = 0xFFFFFF ^ color - # convert the color back to hex by prefixing a # - comp_color = "#%06X" % comp_color - return comp_color - - -# ======================== EasyPrint =====# -# ===================================================# -_easy_print_data = None # global variable... I'm cheating - - -class DebugWin(): - def __init__(self, size=(None, None), location=(None, None), font=None, no_titlebar=False, no_button=False, - grab_anywhere=False, keep_on_top=False): - # Show a form that's a running counter - win_size = size if size != (None, None) else DEFAULT_DEBUG_WINDOW_SIZE - self.window = Window('Debug Window', no_titlebar=no_titlebar, auto_size_text=True, location=location, - font=font or ('Courier New', 10), grab_anywhere=grab_anywhere, keep_on_top=keep_on_top) - self.output_element = Output(size=win_size) - if no_button: - self.layout = [[self.output_element]] - else: - self.layout = [ - [self.output_element], - [DummyButton('Quit')] - ] - self.window.AddRows(self.layout) - self.window.Read(timeout=0) # Show a non-blocking form, returns immediately - return - - def Print(self, *args, end=None, sep=None): - sepchar = sep if sep is not None else ' ' - endchar = end if end is not None else '\n' - - if self.window is None: # if window was destroyed already, just print - print(*args, sep=sepchar, end=endchar) - return - - event, values = self.window.Read(timeout=0) - if event == 'Quit' or event is None: - self.Close() - print(*args, sep=sepchar, end=endchar) - # Add extra check to see if the window was closed... if closed by X sometimes am not told - try: - state = self.window.TKroot.state() - except: - self.Close() - - def Close(self): - self.window.Close() - self.window.__del__() - self.window = None - - -def PrintClose(): - EasyPrintClose() - - -def EasyPrint(*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): - global _easy_print_data - - if _easy_print_data is None: - _easy_print_data = DebugWin(size=size, location=location, font=font, no_titlebar=no_titlebar, - no_button=no_button, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top) - _easy_print_data.Print(*args, end=end, sep=sep) - - -Print = EasyPrint -eprint = EasyPrint - - -def EasyPrintClose(): - global _easy_print_data - if _easy_print_data is not None: - _easy_print_data.Close() - _easy_print_data = None - - -# ======================== Scrolled Text Box =====# -# ===================================================# -def PopupScrolled(*args, button_color=None, yes_no=False, auto_close=False, auto_close_duration=None, - size=(None, None)): - if not args: return - width, height = size - width = width if width else MESSAGE_BOX_LINE_WIDTH - form = Window(args[0], auto_size_text=True, button_color=button_color, auto_close=auto_close, - auto_close_duration=auto_close_duration) - max_line_total, max_line_width, total_lines, height_computed = 0, 0, 0, 0 - complete_output = '' - for message in args: - # fancy code to check if string and convert if not is not need. Just always convert to string :-) - # if not isinstance(message, str): message = str(message) - message = str(message) - longest_line_len = max([len(l) for l in message.split('\n')]) - width_used = min(longest_line_len, width) - max_line_total = max(max_line_total, width_used) - max_line_width = width - lines_needed = _GetNumLinesNeeded(message, width_used) - height_computed += lines_needed - complete_output += message + '\n' - total_lines += lines_needed - height_computed = MAX_SCROLLED_TEXT_BOX_HEIGHT if height_computed > MAX_SCROLLED_TEXT_BOX_HEIGHT else height_computed - if height: - height_computed = height - form.AddRow(Multiline(complete_output, size=(max_line_width, height_computed))) - pad = max_line_total - 15 if max_line_total > 15 else 1 - # show either an OK or Yes/No depending on paramater - if yes_no: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Yes(), No()) - button, values = form.Read() - return button - else: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False), Button('OK', size=(5, 1), button_color=button_color)) - button, values = form.Read() - return button - - -ScrolledTextBox = PopupScrolled - - -# ============================== SetGlobalIcon ======# -# Sets the icon to be used by default # -# ===================================================# -def SetGlobalIcon(icon): - global _my_windows - - try: - with open(icon, 'r') as icon_file: - pass - except: - raise FileNotFoundError - _my_windows.user_defined_icon = icon - return True - - -# ============================== SetOptions =========# -# Sets the icon to be used by default # -# ===================================================# -def SetOptions(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), - tooltip_time=None): - global DEFAULT_ELEMENT_SIZE - global DEFAULT_BUTTON_ELEMENT_SIZE - global DEFAULT_MARGINS # Margins for each LEFT/RIGHT margin is first term - global DEFAULT_ELEMENT_PADDING # Padding between elements (row, col) in pixels - global DEFAULT_AUTOSIZE_TEXT - global DEFAULT_AUTOSIZE_BUTTONS - global DEFAULT_FONT - global DEFAULT_BORDER_WIDTH - global DEFAULT_AUTOCLOSE_TIME - global DEFAULT_BUTTON_COLOR - global MESSAGE_BOX_LINE_WIDTH - global DEFAULT_PROGRESS_BAR_BORDER_WIDTH - global DEFAULT_PROGRESS_BAR_STYLE - global DEFAULT_PROGRESS_BAR_RELIEF - global DEFAULT_PROGRESS_BAR_COLOR - global DEFAULT_PROGRESS_BAR_SIZE - global DEFAULT_TEXT_JUSTIFICATION - global DEFAULT_DEBUG_WINDOW_SIZE - global DEFAULT_SLIDER_BORDER_WIDTH - global DEFAULT_SLIDER_RELIEF - global DEFAULT_SLIDER_ORIENTATION - global DEFAULT_BACKGROUND_COLOR - global DEFAULT_INPUT_ELEMENTS_COLOR - global DEFAULT_ELEMENT_BACKGROUND_COLOR - global DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR - global DEFAULT_SCROLLBAR_COLOR - global DEFAULT_TEXT_COLOR - global DEFAULT_WINDOW_LOCATION - global DEFAULT_ELEMENT_TEXT_COLOR - global DEFAULT_INPUT_TEXT_COLOR - global DEFAULT_TOOLTIP_TIME - global _my_windows - - if icon: - try: - with open(icon, 'r') as icon_file: - pass - except: - raise FileNotFoundError - _my_windows.user_defined_icon = icon - - if button_color != None: - DEFAULT_BUTTON_COLOR = button_color - - if element_size != (None, None): - DEFAULT_ELEMENT_SIZE = element_size - - if button_element_size != (None, None): - DEFAULT_BUTTON_ELEMENT_SIZE = button_element_size - - if margins != (None, None): - DEFAULT_MARGINS = margins - - if element_padding != (None, None): - DEFAULT_ELEMENT_PADDING = element_padding - - if auto_size_text != None: - DEFAULT_AUTOSIZE_TEXT = auto_size_text - - if auto_size_buttons != None: - DEFAULT_AUTOSIZE_BUTTONS = auto_size_buttons - - if font != None: - DEFAULT_FONT = font - - if border_width != None: - DEFAULT_BORDER_WIDTH = border_width - - if autoclose_time != None: - DEFAULT_AUTOCLOSE_TIME = autoclose_time - - if message_box_line_width != None: - MESSAGE_BOX_LINE_WIDTH = message_box_line_width - - if progress_meter_border_depth != None: - DEFAULT_PROGRESS_BAR_BORDER_WIDTH = progress_meter_border_depth - - if progress_meter_style != None: - DEFAULT_PROGRESS_BAR_STYLE = progress_meter_style - - if progress_meter_relief != None: - DEFAULT_PROGRESS_BAR_RELIEF = progress_meter_relief - - if progress_meter_color != None: - DEFAULT_PROGRESS_BAR_COLOR = progress_meter_color - - if progress_meter_size != None: - DEFAULT_PROGRESS_BAR_SIZE = progress_meter_size - - if slider_border_width != None: - DEFAULT_SLIDER_BORDER_WIDTH = slider_border_width - - if slider_orientation != None: - DEFAULT_SLIDER_ORIENTATION = slider_orientation - - if slider_relief != None: - DEFAULT_SLIDER_RELIEF = slider_relief - - if text_justification != None: - DEFAULT_TEXT_JUSTIFICATION = text_justification - - if background_color != None: - DEFAULT_BACKGROUND_COLOR = background_color - - if text_element_background_color != None: - DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR = text_element_background_color - - if input_elements_background_color != None: - DEFAULT_INPUT_ELEMENTS_COLOR = input_elements_background_color - - if element_background_color != None: - DEFAULT_ELEMENT_BACKGROUND_COLOR = element_background_color - - if window_location != (None, None): - DEFAULT_WINDOW_LOCATION = window_location - - if debug_win_size != (None, None): - DEFAULT_DEBUG_WINDOW_SIZE = debug_win_size - - if text_color != None: - DEFAULT_TEXT_COLOR = text_color - - if scrollbar_color != None: - DEFAULT_SCROLLBAR_COLOR = scrollbar_color - - if element_text_color != None: - DEFAULT_ELEMENT_TEXT_COLOR = element_text_color - - if input_text_color is not None: - DEFAULT_INPUT_TEXT_COLOR = input_text_color - - if tooltip_time is not None: - DEFAULT_TOOLTIP_TIME = tooltip_time - - return True - - -#################### ChangeLookAndFeel ####################### -# Predefined settings that will change the colors and styles # -# of the elements. # -############################################################## -LOOK_AND_FEEL_TABLE = {'SystemDefault': - {'BACKGROUND': COLOR_SYSTEM_DEFAULT, - 'TEXT': COLOR_SYSTEM_DEFAULT, - 'INPUT': COLOR_SYSTEM_DEFAULT, 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, - 'SCROLL': COLOR_SYSTEM_DEFAULT, - 'BUTTON': OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR, - 'PROGRESS': COLOR_SYSTEM_DEFAULT, - 'BORDER': 1, 'SLIDER_DEPTH': 1, - 'PROGRESS_DEPTH': 0}, - - 'Reddit': {'BACKGROUND': '#ffffff', - 'TEXT': '#1a1a1b', - 'INPUT': '#dae0e6', - 'TEXT_INPUT': '#222222', - 'SCROLL': '#a5a4a4', - 'BUTTON': ('white', '#0079d3'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0, - 'ACCENT1': '#ff5414', - 'ACCENT2': '#33a8ff', - 'ACCENT3': '#dbf0ff'}, - - 'Topanga': {'BACKGROUND': '#282923', - 'TEXT': '#E7DB74', - 'INPUT': '#393a32', - 'TEXT_INPUT': '#E7C855', - 'SCROLL': '#E7C855', - 'BUTTON': ('#E7C855', '#284B5A'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0, - 'ACCENT1': '#c15226', - 'ACCENT2': '#7a4d5f', - 'ACCENT3': '#889743'}, - - 'GreenTan': {'BACKGROUND': '#9FB8AD', - 'TEXT': COLOR_SYSTEM_DEFAULT, - 'INPUT': '#F7F3EC', 'TEXT_INPUT': 'black', - 'SCROLL': '#F7F3EC', - 'BUTTON': ('white', '#475841'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Dark': {'BACKGROUND': 'gray25', - 'TEXT': 'white', - 'INPUT': 'gray30', - 'TEXT_INPUT': 'white', - 'SCROLL': 'gray44', - 'BUTTON': ('white', '#004F00'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'LightGreen': {'BACKGROUND': '#B7CECE', - 'TEXT': 'black', - 'INPUT': '#FDFFF7', - 'TEXT_INPUT': 'black', - 'SCROLL': '#FDFFF7', - 'BUTTON': ('white', '#658268'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'ACCENT1': '#76506d', - 'ACCENT2': '#5148f1', - 'ACCENT3': '#0a1c84', - 'PROGRESS_DEPTH': 0}, - - 'Dark2': {'BACKGROUND': 'gray25', - 'TEXT': 'white', - 'INPUT': 'white', - 'TEXT_INPUT': 'black', - 'SCROLL': 'gray44', - 'BUTTON': ('white', '#004F00'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Black': {'BACKGROUND': 'black', - 'TEXT': 'white', - 'INPUT': 'gray30', - 'TEXT_INPUT': 'white', - 'SCROLL': 'gray44', - 'BUTTON': ('black', 'white'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Tan': {'BACKGROUND': '#fdf6e3', - 'TEXT': '#268bd1', - 'INPUT': '#eee8d5', - 'TEXT_INPUT': '#6c71c3', - 'SCROLL': '#eee8d5', - 'BUTTON': ('white', '#063542'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'TanBlue': {'BACKGROUND': '#e5dece', - 'TEXT': '#063289', - 'INPUT': '#f9f8f4', - 'TEXT_INPUT': '#242834', - 'SCROLL': '#eee8d5', - 'BUTTON': ('white', '#063289'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'DarkTanBlue': {'BACKGROUND': '#242834', - 'TEXT': '#dfe6f8', - 'INPUT': '#97755c', - 'TEXT_INPUT': 'white', - 'SCROLL': '#a9afbb', - 'BUTTON': ('white', '#063289'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'DarkAmber': {'BACKGROUND': '#2c2825', - 'TEXT': '#fdcb52', - 'INPUT': '#705e52', - 'TEXT_INPUT': '#fdcb52', - 'SCROLL': '#705e52', - 'BUTTON': ('black', '#fdcb52'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'DarkBlue': {'BACKGROUND': '#1a2835', - 'TEXT': '#d1ecff', - 'INPUT': '#335267', - 'TEXT_INPUT': '#acc2d0', - 'SCROLL': '#1b6497', - 'BUTTON': ('black', '#fafaf8'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Reds': {'BACKGROUND': '#280001', - 'TEXT': 'white', - 'INPUT': '#d8d584', - 'TEXT_INPUT': 'black', - 'SCROLL': '#763e00', - 'BUTTON': ('black', '#daad28'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Green': {'BACKGROUND': '#82a459', - 'TEXT': 'black', - 'INPUT': '#d8d584', - 'TEXT_INPUT': 'black', - 'SCROLL': '#e3ecf3', - 'BUTTON': ('white', '#517239'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'BluePurple': {'BACKGROUND': '#A5CADD', - 'TEXT': '#6E266E', - 'INPUT': '#E0F5FF', - 'TEXT_INPUT': 'black', - 'SCROLL': '#E0F5FF', - 'BUTTON': ('white', '#303952'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Purple': {'BACKGROUND': '#B0AAC2', - 'TEXT': 'black', - 'INPUT': '#F2EFE8', - 'SCROLL': '#F2EFE8', - 'TEXT_INPUT': 'black', - 'BUTTON': ('black', '#C2D4D8'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'BlueMono': {'BACKGROUND': '#AAB6D3', - 'TEXT': 'black', - 'INPUT': '#F1F4FC', - 'SCROLL': '#F1F4FC', - 'TEXT_INPUT': 'black', - 'BUTTON': ('white', '#7186C7'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'GreenMono': {'BACKGROUND': '#A8C1B4', - 'TEXT': 'black', - 'INPUT': '#DDE0DE', - 'SCROLL': '#E3E3E3', - 'TEXT_INPUT': 'black', - 'BUTTON': ('white', '#6D9F85'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'BrownBlue': {'BACKGROUND': '#64778d', - 'TEXT': 'white', - 'INPUT': '#f0f3f7', - 'SCROLL': '#A6B2BE', - 'TEXT_INPUT': 'black', - 'BUTTON': ('white', '#283b5b'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'BrightColors': {'BACKGROUND': '#b4ffb4', - 'TEXT': 'black', - 'INPUT': '#ffff64', - 'SCROLL': '#ffb482', - 'TEXT_INPUT': 'black', - 'BUTTON': ('black', '#ffa0dc'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'NeutralBlue': {'BACKGROUND': '#92aa9d', - 'TEXT': 'black', - 'INPUT': '#fcfff6', - 'SCROLL': '#fcfff6', - 'TEXT_INPUT': 'black', - 'BUTTON': ('black', '#d0dbbd'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'Kayak': {'BACKGROUND': '#a7ad7f', - 'TEXT': 'black', - 'INPUT': '#e6d3a8', - 'SCROLL': '#e6d3a8', - 'TEXT_INPUT': 'black', - 'BUTTON': ('white', '#5d907d'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'SandyBeach': {'BACKGROUND': '#efeccb', - 'TEXT': '#012f2f', - 'INPUT': '#e6d3a8', - 'SCROLL': '#e6d3a8', - 'TEXT_INPUT': '#012f2f', - 'BUTTON': ('white', '#046380'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, - - 'TealMono': {'BACKGROUND': '#a8cfdd', - 'TEXT': 'black', - 'INPUT': '#dfedf2', 'SCROLL': '#dfedf2', - 'TEXT_INPUT': 'black', - 'BUTTON': ('white', '#183440'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0} - } - - -def ListOfLookAndFeelValues(): - return list(LOOK_AND_FEEL_TABLE.keys()) - - -def ChangeLookAndFeel(index): - # global LOOK_AND_FEEL_TABLE - - if sys.platform == 'darwin': - print('*** Changing look and feel is not supported on Mac platform ***') - return - - # look and feel table - - try: - colors = LOOK_AND_FEEL_TABLE[index] - - SetOptions(background_color=colors['BACKGROUND'], - text_element_background_color=colors['BACKGROUND'], - element_background_color=colors['BACKGROUND'], - text_color=colors['TEXT'], - input_elements_background_color=colors['INPUT'], - button_color=colors['BUTTON'], - progress_meter_color=colors['PROGRESS'], - border_width=colors['BORDER'], - slider_border_width=colors['SLIDER_DEPTH'], - progress_meter_border_depth=colors['PROGRESS_DEPTH'], - scrollbar_color=(colors['SCROLL']), - element_text_color=colors['TEXT'], - input_text_color=colors['TEXT_INPUT']) - except: # most likely an index out of range - print('** Warning - Look and Feel value not valid. Change your ChangeLookAndFeel call. **') - - -# ============================== sprint ======# -# Is identical to the Scrolled Text Box # -# Provides a crude 'print' mechanism but in a # -# GUI environment # -# ============================================# -sprint = ScrolledTextBox - - -# Converts an object's contents into a nice printable string. Great for dumping debug data -def ObjToStringSingleObj(obj): - if obj is None: - return 'None' - return str(obj.__class__) + '\n' + '\n'.join( - (repr(item) + ' = ' + repr(obj.__dict__[item]) for item in sorted(obj.__dict__))) - - -def ObjToString(obj, extra=' '): - if obj is None: - return 'None' - return str(obj.__class__) + '\n' + '\n'.join( - (extra + (str(item) + ' = ' + - (ObjToString(obj.__dict__[item], extra + ' ') if hasattr(obj.__dict__[item], '__dict__') else str( - obj.__dict__[item]))) - for item in sorted(obj.__dict__))) - - -# ------------------------------------------------------------------------------------------------------------------ # -# ===================================== Upper PySimpleGUI ======================================================== # -# Pre-built dialog boxes for all your needs These are the "high level API calls # -# ------------------------------------------------------------------------------------------------------------------ # - -# ----------------------------------- The mighty Popup! ------------------------------------------------------------ # - -def Popup(*args, button_color=None, background_color=None, text_color=None, button_type=POPUP_BUTTONS_OK, - auto_close=False, auto_close_duration=None, custom_text=(None, None), non_blocking=False, - icon=DEFAULT_WINDOW_ICON, line_width=None, - font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Popup - Display a popup box with as many parms as you wish to include - :param args: - :param button_color: - :param background_color: - :param text_color: - :param button_type: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - if not args: - args_to_print = [''] - else: - args_to_print = args - if line_width != None: - local_line_width = line_width - else: - local_line_width = MESSAGE_BOX_LINE_WIDTH - title = args_to_print[0] if args_to_print[0] is not None else 'None' - window = Window(title, auto_size_text=True, background_color=background_color, button_color=button_color, - auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, - no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - max_line_total, total_lines = 0, 0 - for message in args_to_print: - # fancy code to check if string and convert if not is not need. Just always convert to string :-) - # if not isinstance(message, str): message = str(message) - message = str(message) - if message.count('\n'): - message_wrapped = message - else: - message_wrapped = textwrap.fill(message, local_line_width) - message_wrapped_lines = message_wrapped.count('\n') + 1 - longest_line_len = max([len(l) for l in message.split('\n')]) - width_used = min(longest_line_len, local_line_width) - max_line_total = max(max_line_total, width_used) - # height = _GetNumLinesNeeded(message, width_used) - height = message_wrapped_lines - window.AddRow( - Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) - total_lines += height - - if non_blocking: - PopupButton = DummyButton # important to use or else button will close other windows too! - else: - PopupButton = CloseButton - # show either an OK or Yes/No depending on paramater - if custom_text != (None, None): - if type(custom_text) is not tuple: - window.AddRow(PopupButton(custom_text, size=(len(custom_text), 1), button_color=button_color, focus=True, - bind_return_key=True)) - elif custom_text[1] is None: - window.AddRow( - PopupButton(custom_text[0], size=(len(custom_text[0]), 1), button_color=button_color, focus=True, - bind_return_key=True)) - else: - window.AddRow(PopupButton(custom_text[0], button_color=button_color, focus=True, bind_return_key=True, - size=(len(custom_text[0]), 1)), - PopupButton(custom_text[1], button_color=button_color, size=(len(custom_text[0]), 1))) - elif button_type is POPUP_BUTTONS_YES_NO: - window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 5), 3), - size=(5, 1)), PopupButton('No', button_color=button_color, size=(5, 1))) - elif button_type is POPUP_BUTTONS_CANCELLED: - window.AddRow( - PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20, 0), 3))) - elif button_type is POPUP_BUTTONS_ERROR: - window.AddRow(PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True, - pad=((20, 0), 3))) - elif button_type is POPUP_BUTTONS_OK_CANCEL: - window.AddRow(PopupButton('OK', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True), - PopupButton('Cancel', size=(6, 1), button_color=button_color)) - elif button_type is POPUP_BUTTONS_NO_BUTTONS: - pass - else: - window.AddRow(PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True, - pad=((20, 0), 3))) - - if non_blocking: - button, values = window.Read(timeout=0) - else: - button, values = window.Read() - - return button - - -# ============================== MsgBox============# -# Lazy function. Same as calling Popup with parms # -# This function WILL Disappear perhaps today # -# ==================================================# -# MsgBox is the legacy call and should not be used any longer -def MsgBox(*args): - raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup') - - -# --------------------------- PopupNoButtons --------------------------- -def PopupNoButtons(*args, button_color=None, background_color=None, text_color=None, auto_close=False, - auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Show a Popup but without any buttons - :param args: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, - button_type=POPUP_BUTTONS_NO_BUTTONS, - auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, - line_width=line_width, - font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupNonBlocking --------------------------- -def PopupNonBlocking(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, - auto_close=False, auto_close_duration=None, non_blocking=True, icon=DEFAULT_WINDOW_ICON, - line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, - location=(None, None)): - """ - Show Popup box and immediately return (does not block) - :param args: - :param button_type: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, - button_type=button_type, - auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, - line_width=line_width, - font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -PopupNoWait = PopupNonBlocking - - -# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup --------------------------- -def PopupQuick(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, - auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, line_width=None, - font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Show Popup box that doesn't block and closes itself - :param args: - :param button_type: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, - button_type=button_type, - auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, - line_width=line_width, - font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupQuick - a NonBlocking, Self-closing Popup with no titlebar and no buttons --------------------------- -def PopupQuickMessage(*args, button_type=POPUP_BUTTONS_NO_BUTTONS, button_color=None, background_color=None, - text_color=None, - auto_close=True, auto_close_duration=2, non_blocking=True, icon=DEFAULT_WINDOW_ICON, - line_width=None, - font=None, no_titlebar=True, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Show Popup box that doesn't block and closes itself - :param args: - :param button_type: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, - button_type=button_type, - auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, - line_width=line_width, - font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupNoTitlebar --------------------------- -def PopupNoTitlebar(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, - auto_close=False, auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, - line_width=None, font=None, grab_anywhere=True, keep_on_top=False, location=(None, None)): - """ - Display a Popup without a titlebar. Enables grab anywhere so you can move it - :param args: - :param button_type: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, - button_type=button_type, - auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, - line_width=line_width, - font=font, no_titlebar=True, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -PopupNoFrame = PopupNoTitlebar -PopupNoBorder = PopupNoTitlebar -PopupAnnoying = PopupNoTitlebar - - -# --------------------------- PopupAutoClose --------------------------- -def PopupAutoClose(*args, button_type=POPUP_BUTTONS_OK, button_color=None, background_color=None, text_color=None, - auto_close=True, auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, - line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, - location=(None, None)): - """ - Popup that closes itself after some time period - :param args: - :param button_type: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_color=button_color, background_color=background_color, text_color=text_color, - button_type=button_type, - auto_close=auto_close, auto_close_duration=auto_close_duration, non_blocking=non_blocking, icon=icon, - line_width=line_width, - font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -PopupTimed = PopupAutoClose - - -# --------------------------- PopupError --------------------------- -def PopupError(*args, button_color=DEFAULT_ERROR_BUTTON_COLOR, background_color=None, text_color=None, auto_close=False, - auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Popup with colored button and 'Error' as button text - :param args: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_type=POPUP_BUTTONS_ERROR, background_color=background_color, text_color=text_color, - non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, - auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, - keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupCancel --------------------------- -def PopupCancel(*args, button_color=None, background_color=None, text_color=None, auto_close=False, - auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Display Popup with "cancelled" button text - :param args: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_type=POPUP_BUTTONS_CANCELLED, background_color=background_color, text_color=text_color, - non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, - auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, - keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupOK --------------------------- -def PopupOK(*args, button_color=None, background_color=None, text_color=None, auto_close=False, - auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Display Popup with OK button only - :param args: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: - """ - Popup(*args, button_type=POPUP_BUTTONS_OK, background_color=background_color, text_color=text_color, - non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, auto_close=auto_close, - auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, - keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupOKCancel --------------------------- -def PopupOKCancel(*args, button_color=None, background_color=None, text_color=None, auto_close=False, - auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Display popup with OK and Cancel buttons - :param args: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: OK, Cancel or None - """ - return Popup(*args, button_type=POPUP_BUTTONS_OK_CANCEL, background_color=background_color, text_color=text_color, - non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, - auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, - grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -# --------------------------- PopupYesNo --------------------------- -def PopupYesNo(*args, button_color=None, background_color=None, text_color=None, auto_close=False, - auto_close_duration=None, non_blocking=False, icon=DEFAULT_WINDOW_ICON, line_width=None, font=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Display Popup with Yes and No buttons - :param args: - :param button_color: - :param background_color: - :param text_color: - :param auto_close: - :param auto_close_duration: - :param non_blocking: - :param icon: - :param line_width: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: Yes, No or None - """ - return Popup(*args, button_type=POPUP_BUTTONS_YES_NO, background_color=background_color, text_color=text_color, - non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=button_color, - auto_close=auto_close, auto_close_duration=auto_close_duration, font=font, no_titlebar=no_titlebar, - grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - -############################################################################## -# The PopupGet_____ functions - Will return user input # -############################################################################## - -# --------------------------- PopupGetFolder --------------------------- - - -def PopupGetFolder(message, default_path='', no_window=False, size=(None, None), button_color=None, - background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, - grab_anywhere=False, keep_on_top=False, location=(None, None), initial_folder=None): - """ - Display popup with text entry field and browse button. Browse for folder - :param message: - :param default_path: - :param no_window: - :param size: - :param button_color: - :param background_color: - :param text_color: - :param icon: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: Contents of text field. None if closed using X or cancelled - """ - - global _my_windows - - if no_window: - if _my_windows.NumOpenWindows: - root = tk.Toplevel() - else: - root = tk.Tk() - try: - root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' - except: - pass - folder_name = tk.filedialog.askdirectory() # show the 'get folder' dialog box - root.destroy() - return folder_name - - layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], - [InputText(default_text=default_path, size=size), FolderBrowse(initial_folder=initial_folder)], - [CloseButton('Ok', size=(5, 1), bind_return_key=True), CloseButton('Cancel', size=(5, 1))]] - - window = Window(title=message, icon=icon, auto_size_text=True, button_color=button_color, - background_color=background_color, - font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, - location=location) - - (button, input_values) = window.LayoutAndRead(layout) - - if button != 'Ok': - return None - else: - path = input_values[0] - return path - - -# --------------------------- PopupGetFile --------------------------- - -def PopupGetFile(message, default_path='', default_extension='', save_as=False, file_types=(("ALL Files", "*.*"),), - no_window=False, size=(None, None), button_color=None, background_color=None, text_color=None, - icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, - location=(None, None), initial_folder=None): - """ - Display popup with text entry field and browse button. Browse for file - :param message: - :param default_path: - :param default_extension: - :param save_as: - :param file_types: - :param no_window: - :param size: - :param button_color: - :param background_color: - :param text_color: - :param icon: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: string representing the path chosen, None if cancelled or window closed with X - """ - - global _my_windows - - if no_window: - if _my_windows.NumOpenWindows: - root = tk.Toplevel() - else: - root = tk.Tk() - try: - root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' - except: - pass - if save_as: - filename = tk.filedialog.asksaveasfilename(filetypes=file_types, - defaultextension=default_extension) # show the 'get file' dialog box - else: - filename = tk.filedialog.askopenfilename(filetypes=file_types, - defaultextension=default_extension) # show the 'get file' dialog box - root.destroy() - return filename - - browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder) if save_as else FileBrowse( - file_types=file_types, initial_folder=initial_folder) - - layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], - [InputText(default_text=default_path, size=size), browse_button], - [CloseButton('Ok', size=(6, 1), bind_return_key=True), CloseButton('Cancel', size=(6, 1))]] - - window = Window(title=message, icon=icon, auto_size_text=True, button_color=button_color, font=font, - background_color=background_color, - no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - - (button, input_values) = window.Layout(layout).Read() - if button != 'Ok': - return None - else: - path = input_values[0] - return path - - -# --------------------------- PopupGetText --------------------------- - -def PopupGetText(message, default_text='', password_char='', size=(None, None), button_color=None, - background_color=None, text_color=None, icon=DEFAULT_WINDOW_ICON, font=None, no_titlebar=False, - grab_anywhere=False, keep_on_top=False, location=(None, None)): - """ - Display Popup with text entry field - :param message: - :param default_text: - :param password_char: - :param size: - :param button_color: - :param background_color: - :param text_color: - :param icon: - :param font: - :param no_titlebar: - :param grab_anywhere: - :param keep_on_top: - :param location: - :return: Text entered or None if window was closed - """ - - layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)], - [InputText(default_text=default_text, size=size, password_char=password_char)], - [CloseButton('Ok', size=(5, 1), bind_return_key=True), CloseButton('Cancel', size=(5, 1))]] - - window = Window(title=message, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, - background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, - location=location) - - (button, input_values) = window.Layout(layout).Read() - - if button != 'Ok': - return None - else: - return input_values[0] - - -def main(): - layout = [[Text('You are running the PySimpleGUI.py file itself')], - [Text('You should be importing it rather than running it', size=(50, 2))], - [Text('Here is your sample input window....')], - [Text('Source Folder', size=(15, 1), justification='right'), InputText('Source', focus=True), - FolderBrowse()], - [Text('Destination Folder', size=(15, 1), justification='right'), InputText('Dest'), FolderBrowse()], - [Ok(), Cancel()]] - - window = Window('Demo window..', size=(400,200)).Layout(layout) - event, values = window.Read() - window.Close() - - -if __name__ == '__main__': - main() - exit(69)