From 0d7473eedb8d5b8caac0409dff044340c5be501e Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Sat, 21 Dec 2019 13:23:38 -0500 Subject: [PATCH] Removed Macs being forced to system default. Checked in the latest readme components --- PySimpleGUI.py | 15 +- docs/index.md | 1664 +++++++------ readme.md | 1664 +++++++------ readme_creator/1_HEADER_top_part.md | 107 +- readme_creator/2_readme.md | 505 ++-- readme_creator/3_FOOTER.md | 73 +- readme_creator/4_Release_notes.md | 157 +- readme_creator/PySimpleGUIlib.py | 2903 +++++++++++++--------- readme_creator/make_real_readme.py | 17 +- readme_creator/readme.md | 3529 ++++++++++++++++++--------- readme_creator/run_me.py | 1 + readme_creator/show_all_tags.py | 1 + 12 files changed, 6485 insertions(+), 4151 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index f469f18f..ac6a48fa 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1,6 +1,6 @@ #!/usr/bin/python3 -version = __version__ = "4.13.1.2 Unreleased - Element.set_cursor, NEW theme(), Combo.update allows any value, table & tree header font defaults to window font, default theme now Dark Blue 3" +version = __version__ = "4.13.1.3 Unreleased - Element.set_cursor, NEW theme(), Combo.update allows any value, table & tree header font defaults to window font, default theme now Dark Blue 3, Macs no longer default to colorless windows and buttons" port = 'PySimpleGUI' @@ -215,13 +215,10 @@ NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), (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 = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default -OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long +COLOR_SYSTEM_DEFAULT = '1234567890' # A Magic Number kind of signal to PySimpleGUI that the color should not be set at all +DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) + CURRENT_LOOK_AND_FEEL = 'DarkBlue3' DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") @@ -12812,7 +12809,6 @@ def main(): # ------------------------ PEP8-ify The SDK ------------------------# change_look_and_feel = ChangeLookAndFeel -set_theme = ChangeLookAndFeel convert_args_to_single_string = ConvertArgsToSingleString convert_flex_to_tk = ConvertFlexToTK easy_print = EasyPrint @@ -12848,7 +12844,6 @@ popup_timed = PopupTimed popup_yes_no = PopupYesNo sgprint = Print sgprint_close = PrintClose -quit = Quit rgb = RGB set_global_icon = SetGlobalIcon set_options = SetOptions diff --git a/docs/index.md b/docs/index.md index d4a1dd13..e131764c 100644 --- a/docs/index.md +++ b/docs/index.md @@ -14,7 +14,7 @@ ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.13.0-red.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.13.1-red.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.1-blue.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.30.0-orange.svg?longCache=true&style=for-the-badge) @@ -233,10 +233,10 @@ PySimpleGUI runs on Windows, Linux and Mac, just like tkinter, Qt, WxPython and ### OS * Windows 7, 8, 10 -* Linux on PC - Tested on **many** distributions +* Linux on PC - Tested on several distributions * Linux on Raspbnerry Pi * Linux on Android - Can use either Termux or PyDroid3 -* Mac OS (Sorry don't know much about Macs other than Macs don't like tkinter) +* Mac OS #### Python versions @@ -484,13 +484,16 @@ Repl.it is not meant to serve up applications and web pages. Trying to use it t It's surprising that Python GUI code is completely cross platform from Windows to Mac to Linux. No source code changes. This is true for both PySimpleGUI and PySimpleGUIQt. -However, **Macs** suck. They suck on tkinter in particular. The "Look and feel" calls are disabled for Macs. Colored buttons in particular are broken. And, you are unable to specify filetypes when using the FileBrowse button. None of this is PySimpleGUI code issues, of course, they're all in tkinter. Consider using Qt instead of tkinter on the Mac. Or, if using tkinter, create your own button images. +Historicly, PySimpleGUI using tkinter have struggled on Macs. This was because of a problem setting button colors on the Mac. However, two events has turned this problem around entirely. -***Look through the open and closed issues if you're a Mac person with a problem. It's highly likely the problem has been at least seen previously and there may even be a fix or workaround*** +1. Use of ttk Buttons for Macs +2. Ability for Mac users to install Python from python.org rather than the Homebrew version with button problems -*Switching to "Light Mode" is known to fix some of the problems.* They honestly are tkinter/Mac problems. +It's been a long road for Mac users with many deciding to use PySimpleGUIQt so that multi-colored windows could be made. It's completely understandable to want to make attractive windows that utilitize colors. -Make sure you're running tkinter 8.6 and up. However, as I'm learning 8.6 can mean almost anything as the minor release numbers are not provided (8.6.1, etc). Turns out 8.6 has been in development for YEARS. The 8.6 that comes with Python 3.7.4 doesn't support table colors for example even though it's version 8.6. +PySimpleGUI now supports Macs, Linux, and Windows equally well. They all are able to use the "Themes" that automatically add color to your windows. + +Be aware that Macs default to using ttk buttons. You can override this setting at the Window and Button levels. If you installed Python from python.org, then it's likely you can use the non-ttk buttons should you wish. # Support @@ -3429,8 +3432,6 @@ You can call the method without setting the `time_between_frames` value and it w ## Button Element -**MAC USERS** - Macs suck when it comes to tkinter and button colors. It sucks so badly with colors that the `LookAndFeel` call is disabled. You cannot change button colors for Macs. You're stuck with the system default color if you are using the tkinter version of PySimpleGUI. The Qt version does not have this issue. - Buttons are the most important element of all! They cause the majority of the action to happen. After all, it's a button press that will get you out of a window, whether it be Submit or Cancel, one way or another a button is involved in all windows. The only exception is to this is when the user closes the window using the "X" in the upper corner which means no button was involved. The Types of buttons include: @@ -3494,6 +3495,12 @@ layout = [[sg.Ok(), sg.Cancel()]] In reality `Button` is in fact being called on your behalf. Behind the scenes, `sg.Ok` and `sg.Cancel` call `Button` with the text set to `Ok` and `Cancel` and returning the results that then go into the layout. If you were to print the layout it will look identical to the first layout shown that has `Button` shown specifically in the layout. +### TTK Buttons & Macs + +In 2019 support for ttk Buttons was added. This gets around the problem of not being able to change button colors on a Mac. There are a number of places you can control whether or not ttk buttons are used, be it on MAc or other platform. + +TTK Buttons and TK Buttons operate slightly differently. Button highlighting is one different. How images and text are displayed at the same time is another. You've got options now that weren't there previously. It's nice to see that Mac users can finally use the color themes. + ### Button Element Shortcuts These Pre-made buttons are some of the most important elements of all because they are used so much. They all basically do the same thing, **set the button text to match the function name and set the parameters to commonly used values**. If you find yourself needing to create a custom button often because it's not on this list, please post a request on GitHub. . They include: @@ -4523,7 +4530,7 @@ while True: print("Nothing happened") ``` -Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and yuou've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? +Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and you've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? Non-blocking (timeout=0) is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine. @@ -4570,7 +4577,7 @@ sg.ChangeLookAndFeel('Black') sg.SetOptions(element_padding=(0, 0)) layout = [[sg.Text('')], - [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], + [sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], [sg.ReadButton('Pause', key='button', button_color=('white', '#001480')), sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'), sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]] @@ -4753,7 +4760,7 @@ import PySimpleGUI as sg # Recipe for getting keys, one at a time as they are released # If want to use the space bar, then be sure and disable the "default focus" -text_elem = sg.Text("", size=(18, 1)) +text_elem = sg.Text(size=(18, 1)) layout = [[sg.Text("Press a key or scroll mouse")], [text_elem], @@ -4912,7 +4919,7 @@ import PySimpleGUI as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2'), sg.Button('Exit')]] win1 = sg.Window('Window 1', layout) @@ -4947,7 +4954,7 @@ import PySimpleGUIQt as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2')]] win1 = sg.Window('Window 1', layout) @@ -5364,7 +5371,7 @@ import PySimpleGUI as sg sg.change_look_and_feel('Dark Green 2') layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], + [sg.Input(key='-IN-'), sg.Text(size=(15,1), key='-OUT-')], [sg.Button('Go'), sg.Button('Exit')] ] @@ -14591,30 +14598,6 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| -Change the "color scheme" of all future PySimpleGUI Windows. -The scheme are string names that specify a group of colors. Background colors, text colors, button colors. -There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel -The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. -The original list was (prior to a major rework and renaming)... these names still work... -In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: -The "Formula" is: -["Dark" or "Light"] Color Number -Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black -The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. -Default = The default settings (only button color is different than system default) -Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - -``` -ChangeLookAndFeel(index, force=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| -|force|(bool) no longer used| - ``` CloseButton(button_text, image_filename=None, @@ -14779,41 +14762,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -``` -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, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -EasyPrintClose() -``` - ``` Exit(button_text="Exit", size=(None, None), @@ -15048,12 +14996,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -Get a list of the valid values to pass into your call to change_look_and_feel - -``` -ListOfLookAndFeelValues() -> List[str] - list of valid string values -``` - ``` No(button_text="No", size=(None, None), @@ -15208,6 +15150,601 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| +``` +Quit(button_text="Quit", + size=(None, None), + auto_size_button=None, + button_color=None, + disabled=False, + tooltip=None, + font=None, + bind_return_key=False, + focus=False, + pad=None, + key=None, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Quit')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +``` +RButton(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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button| +|image_filename|image filename if there is a button image| +|image_data|in-RAM image to be displayed on button| +|image_size|size of button image in pixels| +|image_subsample|amount to reduce the size of the image| +|border_width|width of border around element| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|disabled|set disable state for element (Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button| +|image_filename|image filename if there is a button image| +|image_data|in-RAM image to be displayed on button| +|image_size|size of button image in pixels| +|image_subsample|amount to reduce the size of the image| +|border_width|width of border around element| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|disabled|set disable state for element (Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button| +|image_filename|image filename if there is a button image| +|image_data|in-RAM image to be displayed on button| +|image_size|size of button image in pixels| +|image_subsample|amount to reduce the size of the image| +|border_width|width of border around element| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|font|specifies the font family, size, etc| +|disabled|set disable state for element (Default = False)| +|bind_return_key|(Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Save')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|bind_return_key|(Default = True)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +``` +SaveAs(button_text="Save As...", + target=(555666777, -1), + file_types=(('ALL Files', '*.*'),), + initial_folder=None, + disabled=False, + tooltip=None, + size=(None, None), + auto_size_button=None, + button_color=None, + change_submits=False, + enable_events=False, + font=None, + pad=None, + key=None, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Save As...')| +|target|key or (row,col) target for the button (Default value = (ThisRow, -1))| +|file_types|(Default value = (("ALL Files", "*.*")))| +|initial_folder|starting path for folders and files| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|change_submits|If True, pressing Enter key submits window (Default = False)| +|enable_events|Turns on the element specific events.(Default = False)| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you +want, just like a print statement. + +``` +ScrolledTextBox(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + yes_no=False, + auto_close=False, + auto_close_duration=None, + size=(None, None), + location=(None, None), + non_blocking=False, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + font=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|(Any) Variable number of items to display| +|title|(str) Title to display in the window.| +|button_color|Tuple[str, str] button color (foreground, background)| +|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| +|auto_close|(bool) if True window will close itself| +|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| +|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| +||| +| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | + +Sets the icon which will be used any time a window is created if an icon is not provided when the +window is created. + +``` +SetGlobalIcon(icon) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|icon|Union[bytes, str] Either a Base64 byte string or a filename| + +``` +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), + error_button_color=(None, None), + tooltip_time=None, + use_ttk_buttons=None, + ttk_theme=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|icon|filename of icon used for taskbar and title bar| +|button_color|button color (foreground, background)| +|element_size|Tuple[int, int] element size (width, height) in characters| +|button_element_size|Tuple[int, int]| +|margins|tkinter margins around outsize (Default = (None))| +|element_padding|(Default = (None))| +|auto_size_text|True if size should fit the text length| +|auto_size_buttons|| +|font|specifies the font family, size, etc| +|border_width|width of border around element| +|slider_border_width|| +|slider_relief|| +|slider_orientation|| +|autoclose_time|| +|message_box_line_width|| +|progress_meter_border_depth|| +|progress_meter_style|| +|progress_meter_relief|| +|progress_meter_color|| +|progress_meter_size|Tuple[int, int]| +|text_justification|| +|background_color|color of background| +|element_background_color|| +|text_element_background_color|| +|input_elements_background_color|| +|input_text_color|| +|scrollbar_color|| +|text_color|color of the text| +|element_text_color|| +|debug_win_size|Tuple[int, int] (Default = (None))| +|window_location|(Default = (None))| +|error_button_color|(Default = (None))| +|tooltip_time|time in milliseconds to wait before showing a tooltip. Default is 400ms| +|use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| +|ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Submit')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|bind_return_key|(Default = True)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Yes')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = True)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +## Debug Window Output + +``` +easy_print(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +easy_print_close() +``` + +``` +eprint(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +sgprint(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +sgprint_close() +``` + +``` +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, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +EasyPrintClose() +``` + +``` +Print(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +PrintClose() +``` + ## OneLineProgressMeter ``` @@ -15250,6 +15787,46 @@ Parameter Descriptions: |---|---| |key|Used with window.FindElement and with return values to uniquely identify this element| +``` +one_line_progress_meter(title, + current_value, + max_value, + key, + args, + orientation="v", + bar_color=(None, None), + button_color=None, + size=(20, 20), + border_width=None, + grab_anywhere=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|title|text to display| +|current_value|current progressbar value| +|max_value|max value of progressbar| +|key|Used with window.FindElement and with return values to uniquely identify this element| +|*args|stuff to output.| +|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| +|bar_color|| +|button_color|button color (foreground, background)| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| +|border_width|width of border around element| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| + +``` +one_line_progress_meter_cancel(key) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|Used with window.FindElement and with return values to uniquely identify this element| + ## Popup Functions Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the @@ -16144,659 +16721,7 @@ Parameter Descriptions: ||| | **return** | Union["Yes", "No", None] | -``` -Print(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -PrintClose() -``` - -``` -Quit(button_text="Quit", - size=(None, None), - auto_size_button=None, - button_color=None, - disabled=False, - tooltip=None, - font=None, - bind_return_key=False, - focus=False, - pad=None, - key=None, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Quit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -``` -RButton(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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button| -|image_filename|image filename if there is a button image| -|image_data|in-RAM image to be displayed on button| -|image_size|size of button image in pixels| -|image_subsample|amount to reduce the size of the image| -|border_width|width of border around element| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|disabled|set disable state for element (Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button| -|image_filename|image filename if there is a button image| -|image_data|in-RAM image to be displayed on button| -|image_size|size of button image in pixels| -|image_subsample|amount to reduce the size of the image| -|border_width|width of border around element| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|disabled|set disable state for element (Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button| -|image_filename|image filename if there is a button image| -|image_data|in-RAM image to be displayed on button| -|image_size|size of button image in pixels| -|image_subsample|amount to reduce the size of the image| -|border_width|width of border around element| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|font|specifies the font family, size, etc| -|disabled|set disable state for element (Default = False)| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Save')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|bind_return_key|(Default = True)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -``` -SaveAs(button_text="Save As...", - target=(555666777, -1), - file_types=(('ALL Files', '*.*'),), - initial_folder=None, - disabled=False, - tooltip=None, - size=(None, None), - auto_size_button=None, - button_color=None, - change_submits=False, - enable_events=False, - font=None, - pad=None, - key=None, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Save As...')| -|target|key or (row,col) target for the button (Default value = (ThisRow, -1))| -|file_types|(Default value = (("ALL Files", "*.*")))| -|initial_folder|starting path for folders and files| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|change_submits|If True, pressing Enter key submits window (Default = False)| -|enable_events|Turns on the element specific events.(Default = False)| -|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you -want, just like a print statement. - -``` -ScrolledTextBox(args, - title=None, - button_color=None, - background_color=None, - text_color=None, - yes_no=False, - auto_close=False, - auto_close_duration=None, - size=(None, None), - location=(None, None), - non_blocking=False, - no_titlebar=False, - grab_anywhere=False, - keep_on_top=False, - font=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|(Any) Variable number of items to display| -|title|(str) Title to display in the window.| -|button_color|Tuple[str, str] button color (foreground, background)| -|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| -|auto_close|(bool) if True window will close itself| -|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| -|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| -||| -| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | - -Sets the icon which will be used any time a window is created if an icon is not provided when the -window is created. - -``` -SetGlobalIcon(icon) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|icon|Union[bytes, str] Either a Base64 byte string or a filename| - -``` -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), - error_button_color=(None, None), - tooltip_time=None, - use_ttk_buttons=None, - ttk_theme=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|icon|filename of icon used for taskbar and title bar| -|button_color|button color (foreground, background)| -|element_size|Tuple[int, int] element size (width, height) in characters| -|button_element_size|Tuple[int, int]| -|margins|tkinter margins around outsize (Default = (None))| -|element_padding|(Default = (None))| -|auto_size_text|True if size should fit the text length| -|auto_size_buttons|| -|font|specifies the font family, size, etc| -|border_width|width of border around element| -|slider_border_width|| -|slider_relief|| -|slider_orientation|| -|autoclose_time|| -|message_box_line_width|| -|progress_meter_border_depth|| -|progress_meter_style|| -|progress_meter_relief|| -|progress_meter_color|| -|progress_meter_size|Tuple[int, int]| -|text_justification|| -|background_color|color of background| -|element_background_color|| -|text_element_background_color|| -|input_elements_background_color|| -|input_text_color|| -|scrollbar_color|| -|text_color|color of the text| -|element_text_color|| -|debug_win_size|Tuple[int, int] (Default = (None))| -|window_location|(Default = (None))| -|error_button_color|(Default = (None))| -|tooltip_time|time in milliseconds to wait before showing a tooltip. Default is 400ms| -|use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| -|ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Submit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|bind_return_key|(Default = True)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -Time your code easily.... start the timer. - -``` -TimerStart() -``` - -Time your code easily.... stop the timer and print the number of ms since the timer start - -``` -TimerStop() -``` - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Yes')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = True)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -## PEP8 Function Bindings - -Change the "color scheme" of all future PySimpleGUI Windows. -The scheme are string names that specify a group of colors. Background colors, text colors, button colors. -There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel -The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. -The original list was (prior to a major rework and renaming)... these names still work... -In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: -The "Formula" is: -["Dark" or "Light"] Color Number -Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black -The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. -Default = The default settings (only button color is different than system default) -Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - -``` -change_look_and_feel(index, force=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| -|force|(bool) no longer used| - -``` -easy_print(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -easy_print_close() -``` - -``` -eprint(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -Fills a window with values provided in a values dictionary { element_key : new_value } - -``` -fill_form_with_values(window, values_dict) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|window|(Window) The window object to fill| -|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| - -Get a list of the valid values to pass into your call to change_look_and_feel - -``` -list_of_look_and_feel_values() -> List[str] - list of valid string values -``` - -The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. - -``` -main() -``` - -Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form - -``` -obj_to_string(obj, extra=" ") -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|obj|(Any) The object to display| -|extra|(Default value = ' ') returns (str) Formatted output of the object's values| - -Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form -Returns only the top-most object's variables instead of drilling down to dispolay more - -``` -obj_to_string_single_obj(obj) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|obj|(Any) The object to display returns (str) Formatted output of the object's values| - -``` -one_line_progress_meter(title, - current_value, - max_value, - key, - args, - orientation="v", - bar_color=(None, None), - button_color=None, - size=(20, 20), - border_width=None, - grab_anywhere=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|title|text to display| -|current_value|current progressbar value| -|max_value|max value of progressbar| -|key|Used with window.FindElement and with return values to uniquely identify this element| -|*args|stuff to output.| -|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| -|bar_color|| -|button_color|button color (foreground, background)| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| -|border_width|width of border around element| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| - -``` -one_line_progress_meter_cancel(key) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -## Popups +## Popups PEP8 Versions Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the "print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. @@ -17690,51 +17615,52 @@ Parameter Descriptions: ||| | **return** | Union["Yes", "No", None] | -Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. -They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves +## PEP8 Function Bindings + +Fills a window with values provided in a values dictionary { element_key : new_value } ``` -preview_all_look_and_feel_themes(columns=12) +fill_form_with_values(window, values_dict) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|columns|(int) The number of themes to display per row| +|window|(Window) The window object to fill| +|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| + +The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. ``` -quit(button_text="Quit", - size=(None, None), - auto_size_button=None, - button_color=None, - disabled=False, - tooltip=None, - font=None, - bind_return_key=False, - focus=False, - pad=None, - key=None, - metadata=None) +main() +``` + +Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + +``` +obj_to_string(obj, extra=" ") ``` Parameter Descriptions: |Name|Meaning| |---|---| -|button_text|text in the button (Default value = 'Quit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | +|obj|(Any) The object to display| +|extra|(Default value = ' ') returns (str) Formatted output of the object's values| + +Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form +Returns only the top-most object's variables instead of drilling down to dispolay more + +``` +obj_to_string_single_obj(obj) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|obj|(Any) The object to display returns (str) Formatted output of the object's values| Sets the icon which will be used any time a window is created if an icon is not provided when the window is created. @@ -17827,41 +17753,6 @@ Parameter Descriptions: |use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| |ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| -``` -sgprint(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -sgprint_close() -``` - Shows the smaller "popout" window. Default location is the upper right corner of your screen ``` @@ -17931,6 +17822,146 @@ The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the E test() ``` +## Themes + +Sets / Gets the current Theme. If none is specified then returns the current theme. +This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + +``` +theme(new_theme=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|new_theme|(str) the new theme name to use| +||| +| **return** | (str) the currently selected theme | + +Returns the background color specified by the current color theme + +``` +theme_background_color() -> (str) - color string of the background color defined by current theme +``` + +Returns the button color specified by the current color theme + +``` +theme_button_color() -> Tuple[str, str] - TUPLE with color strings of the button color defined by current theme (button text color, button background color) +``` + +Returns the input element background color specified by the current color theme + +``` +theme_input_background_color() -> (str) - color string of the input element background color defined by current theme +``` + +Returns the input element text color specified by the current color theme + +``` +theme_input_text_color() -> (str) - color string of the input element text color defined by current theme +``` + +Returns a sorted list of the currently available color themes + +``` +theme_list() -> List[str] - A sorted list of the currently available color themes +``` + +Show a window with all of the color themes - takes a while so be patient + +``` +theme_previewer(columns=12) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|columns|(int) number of themes in a single row| + +Returns the text color specified by the current color theme + +``` +theme_text_color() -> (str) - color string of the text color defined by current theme +``` + +## Old Themes (Look and Feel) - Replaced by theme() + +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. +The original list was (prior to a major rework and renaming)... these names still work... +In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: +The "Formula" is: +["Dark" or "Light"] Color Number +Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black +The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. +Default = The default settings (only button color is different than system default) +Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + +``` +ChangeLookAndFeel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| +|force|(bool) no longer used| + +Get a list of the valid values to pass into your call to change_look_and_feel + +``` +ListOfLookAndFeelValues() -> List[str] - list of valid string values +``` + +Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. +They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + +``` +preview_all_look_and_feel_themes(columns=12) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|columns|(int) The number of themes to display per row| + +Get a list of the valid values to pass into your call to change_look_and_feel + +``` +list_of_look_and_feel_values() -> List[str] - list of valid string values +``` + +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. +The original list was (prior to a major rework and renaming)... these names still work... +In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: +The "Formula" is: +["Dark" or "Light"] Color Number +Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black +The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. +Default = The default settings (only button color is different than system default) +Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + +``` +change_look_and_feel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| +|force|(bool) no longer used| + --- # "Demo Programs" Applications @@ -18135,11 +18166,11 @@ Macs and PySimpleGUI did not play well together up until Nov 2019 and the releas The problems were the normal tk.Button was not working correctly on the Mac. You couldn't set the button color. If you tried it appeared as if the text was missing. -Users have recently reported the ability to install Python 3.7 from the Python.org website and NOT used (I think removed) the "Homebrew" version of Python. This resolved all of the button color problems. +Users have recently reported the ability to install Python 3.7 from the Python.org website and not use the Homebrew version. This resolved all of the button color problems. -Regardless, Macs can now enjoy using all of the look and feel color themes that Windows and Linux users are able to achieve. +Regardless of where you get your Python / tkinter, Macs can now enjoy using all of the look and feel color themes that Windows and Linux users are able to achieve. -Many PySimpleGUI users have switched from PySimpleGUI to PySimpleGUIQt due to the button problems. IF you're one of them, you should consider switching back. One reason to return is that features tend to get iumplemented on PySimpleGUI (tkinger version) and then later on the other ports. There are a number of other reasons to give tkinter another try. +Many PySimpleGUI users have switched from PySimpleGUI to PySimpleGUIQt due to the button problems. IF you're one of them, ***you should consider switching back***. One reason to return to PySimpleGUI is that features tend to get iumplemented on PySimpleGUI (tkinger version) and then later on the other ports. There are a number of other reasons to give tkinter another try. ## Multiple threads @@ -18153,6 +18184,37 @@ Other than that, feel free to use threads with PySimpleGUI on all of the ports. Be sure and **delete** your windows after you close them if you are running with multiple threads. There is a chance another thread's garbage collect will attempt to delete the window when not in the mainthread which will cause tkinter to crash. +### The dreaded "Tcl_AsyncDelete: async handler deleted by the wrong thread" error + +This crash has plagued and mystified tkinter users for some time now. It happens when the user is running multiple threads in their application. Even if the user doesn't make any calls that are into tkinter, this problem can still cause your program to crash. + +I'm thrilled to say there's a solution and it's easy to implement. If you're getting this error, then here is what is causing it. + +When you close a window and delete the layout, the tkinter widgets that were in use in the window are no longer needed. Python marks them to be handled by the "Garbage Collector". They're deleted but not quite gone from memory. Then, later, while your thread is running, the Python Garbage Collect algorithm decides it's time to run garbage collect. When it tells tkinter to free up the memory, the tkinter code looks to see what context it is running under. It sees that it's a thread, not the main thread, and generates this exception. + +The way around this is actually quite easy. + +When you are finished with a window, be sure to: + +* Close the Window +* Set the `layout` variable to None +* Set the `window` variable to None +* Trigger Python's Garbage Collect to run immediately + +The sequence looks like this in code: + +```python + import gc + + # Do all your windows stuff... make a layout... show your window... then when time to exit + window.close() + layout = None + window = None + gc.collect() +``` + +This will ensure that the tkinter widgets are all deleted in the context of the mainthread and another thread won't accidently run the Garbage Collect + # Contributing ## Write Applications @@ -18161,7 +18223,7 @@ The way for you to contribute to the PySimpleGUI is to create and share PySimple ## Pull Requests -***PySimpleGUI code changes/pull requests are not being accepted at this time.*** +***PySimpleGUI changes/pull requests are not being accepted at this time.*** ## GitHub Repos diff --git a/readme.md b/readme.md index d4a1dd13..e131764c 100644 --- a/readme.md +++ b/readme.md @@ -14,7 +14,7 @@ ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.13.0-red.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.13.1-red.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.1-blue.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.30.0-orange.svg?longCache=true&style=for-the-badge) @@ -233,10 +233,10 @@ PySimpleGUI runs on Windows, Linux and Mac, just like tkinter, Qt, WxPython and ### OS * Windows 7, 8, 10 -* Linux on PC - Tested on **many** distributions +* Linux on PC - Tested on several distributions * Linux on Raspbnerry Pi * Linux on Android - Can use either Termux or PyDroid3 -* Mac OS (Sorry don't know much about Macs other than Macs don't like tkinter) +* Mac OS #### Python versions @@ -484,13 +484,16 @@ Repl.it is not meant to serve up applications and web pages. Trying to use it t It's surprising that Python GUI code is completely cross platform from Windows to Mac to Linux. No source code changes. This is true for both PySimpleGUI and PySimpleGUIQt. -However, **Macs** suck. They suck on tkinter in particular. The "Look and feel" calls are disabled for Macs. Colored buttons in particular are broken. And, you are unable to specify filetypes when using the FileBrowse button. None of this is PySimpleGUI code issues, of course, they're all in tkinter. Consider using Qt instead of tkinter on the Mac. Or, if using tkinter, create your own button images. +Historicly, PySimpleGUI using tkinter have struggled on Macs. This was because of a problem setting button colors on the Mac. However, two events has turned this problem around entirely. -***Look through the open and closed issues if you're a Mac person with a problem. It's highly likely the problem has been at least seen previously and there may even be a fix or workaround*** +1. Use of ttk Buttons for Macs +2. Ability for Mac users to install Python from python.org rather than the Homebrew version with button problems -*Switching to "Light Mode" is known to fix some of the problems.* They honestly are tkinter/Mac problems. +It's been a long road for Mac users with many deciding to use PySimpleGUIQt so that multi-colored windows could be made. It's completely understandable to want to make attractive windows that utilitize colors. -Make sure you're running tkinter 8.6 and up. However, as I'm learning 8.6 can mean almost anything as the minor release numbers are not provided (8.6.1, etc). Turns out 8.6 has been in development for YEARS. The 8.6 that comes with Python 3.7.4 doesn't support table colors for example even though it's version 8.6. +PySimpleGUI now supports Macs, Linux, and Windows equally well. They all are able to use the "Themes" that automatically add color to your windows. + +Be aware that Macs default to using ttk buttons. You can override this setting at the Window and Button levels. If you installed Python from python.org, then it's likely you can use the non-ttk buttons should you wish. # Support @@ -3429,8 +3432,6 @@ You can call the method without setting the `time_between_frames` value and it w ## Button Element -**MAC USERS** - Macs suck when it comes to tkinter and button colors. It sucks so badly with colors that the `LookAndFeel` call is disabled. You cannot change button colors for Macs. You're stuck with the system default color if you are using the tkinter version of PySimpleGUI. The Qt version does not have this issue. - Buttons are the most important element of all! They cause the majority of the action to happen. After all, it's a button press that will get you out of a window, whether it be Submit or Cancel, one way or another a button is involved in all windows. The only exception is to this is when the user closes the window using the "X" in the upper corner which means no button was involved. The Types of buttons include: @@ -3494,6 +3495,12 @@ layout = [[sg.Ok(), sg.Cancel()]] In reality `Button` is in fact being called on your behalf. Behind the scenes, `sg.Ok` and `sg.Cancel` call `Button` with the text set to `Ok` and `Cancel` and returning the results that then go into the layout. If you were to print the layout it will look identical to the first layout shown that has `Button` shown specifically in the layout. +### TTK Buttons & Macs + +In 2019 support for ttk Buttons was added. This gets around the problem of not being able to change button colors on a Mac. There are a number of places you can control whether or not ttk buttons are used, be it on MAc or other platform. + +TTK Buttons and TK Buttons operate slightly differently. Button highlighting is one different. How images and text are displayed at the same time is another. You've got options now that weren't there previously. It's nice to see that Mac users can finally use the color themes. + ### Button Element Shortcuts These Pre-made buttons are some of the most important elements of all because they are used so much. They all basically do the same thing, **set the button text to match the function name and set the parameters to commonly used values**. If you find yourself needing to create a custom button often because it's not on this list, please post a request on GitHub. . They include: @@ -4523,7 +4530,7 @@ while True: print("Nothing happened") ``` -Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and yuou've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? +Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and you've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? Non-blocking (timeout=0) is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine. @@ -4570,7 +4577,7 @@ sg.ChangeLookAndFeel('Black') sg.SetOptions(element_padding=(0, 0)) layout = [[sg.Text('')], - [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], + [sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], [sg.ReadButton('Pause', key='button', button_color=('white', '#001480')), sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'), sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]] @@ -4753,7 +4760,7 @@ import PySimpleGUI as sg # Recipe for getting keys, one at a time as they are released # If want to use the space bar, then be sure and disable the "default focus" -text_elem = sg.Text("", size=(18, 1)) +text_elem = sg.Text(size=(18, 1)) layout = [[sg.Text("Press a key or scroll mouse")], [text_elem], @@ -4912,7 +4919,7 @@ import PySimpleGUI as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2'), sg.Button('Exit')]] win1 = sg.Window('Window 1', layout) @@ -4947,7 +4954,7 @@ import PySimpleGUIQt as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2')]] win1 = sg.Window('Window 1', layout) @@ -5364,7 +5371,7 @@ import PySimpleGUI as sg sg.change_look_and_feel('Dark Green 2') layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], + [sg.Input(key='-IN-'), sg.Text(size=(15,1), key='-OUT-')], [sg.Button('Go'), sg.Button('Exit')] ] @@ -14591,30 +14598,6 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| -Change the "color scheme" of all future PySimpleGUI Windows. -The scheme are string names that specify a group of colors. Background colors, text colors, button colors. -There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel -The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. -The original list was (prior to a major rework and renaming)... these names still work... -In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: -The "Formula" is: -["Dark" or "Light"] Color Number -Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black -The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. -Default = The default settings (only button color is different than system default) -Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - -``` -ChangeLookAndFeel(index, force=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| -|force|(bool) no longer used| - ``` CloseButton(button_text, image_filename=None, @@ -14779,41 +14762,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -``` -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, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -EasyPrintClose() -``` - ``` Exit(button_text="Exit", size=(None, None), @@ -15048,12 +14996,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -Get a list of the valid values to pass into your call to change_look_and_feel - -``` -ListOfLookAndFeelValues() -> List[str] - list of valid string values -``` - ``` No(button_text="No", size=(None, None), @@ -15208,6 +15150,601 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| +``` +Quit(button_text="Quit", + size=(None, None), + auto_size_button=None, + button_color=None, + disabled=False, + tooltip=None, + font=None, + bind_return_key=False, + focus=False, + pad=None, + key=None, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Quit')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +``` +RButton(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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button| +|image_filename|image filename if there is a button image| +|image_data|in-RAM image to be displayed on button| +|image_size|size of button image in pixels| +|image_subsample|amount to reduce the size of the image| +|border_width|width of border around element| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|disabled|set disable state for element (Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button| +|image_filename|image filename if there is a button image| +|image_data|in-RAM image to be displayed on button| +|image_size|size of button image in pixels| +|image_subsample|amount to reduce the size of the image| +|border_width|width of border around element| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = False)| +|disabled|set disable state for element (Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button| +|image_filename|image filename if there is a button image| +|image_data|in-RAM image to be displayed on button| +|image_size|size of button image in pixels| +|image_subsample|amount to reduce the size of the image| +|border_width|width of border around element| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|font|specifies the font family, size, etc| +|disabled|set disable state for element (Default = False)| +|bind_return_key|(Default = False)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Save')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|bind_return_key|(Default = True)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +``` +SaveAs(button_text="Save As...", + target=(555666777, -1), + file_types=(('ALL Files', '*.*'),), + initial_folder=None, + disabled=False, + tooltip=None, + size=(None, None), + auto_size_button=None, + button_color=None, + change_submits=False, + enable_events=False, + font=None, + pad=None, + key=None, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Save As...')| +|target|key or (row,col) target for the button (Default value = (ThisRow, -1))| +|file_types|(Default value = (("ALL Files", "*.*")))| +|initial_folder|starting path for folders and files| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|change_submits|If True, pressing Enter key submits window (Default = False)| +|enable_events|Turns on the element specific events.(Default = False)| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you +want, just like a print statement. + +``` +ScrolledTextBox(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + yes_no=False, + auto_close=False, + auto_close_duration=None, + size=(None, None), + location=(None, None), + non_blocking=False, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + font=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|(Any) Variable number of items to display| +|title|(str) Title to display in the window.| +|button_color|Tuple[str, str] button color (foreground, background)| +|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| +|auto_close|(bool) if True window will close itself| +|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| +|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| +||| +| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | + +Sets the icon which will be used any time a window is created if an icon is not provided when the +window is created. + +``` +SetGlobalIcon(icon) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|icon|Union[bytes, str] Either a Base64 byte string or a filename| + +``` +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), + error_button_color=(None, None), + tooltip_time=None, + use_ttk_buttons=None, + ttk_theme=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|icon|filename of icon used for taskbar and title bar| +|button_color|button color (foreground, background)| +|element_size|Tuple[int, int] element size (width, height) in characters| +|button_element_size|Tuple[int, int]| +|margins|tkinter margins around outsize (Default = (None))| +|element_padding|(Default = (None))| +|auto_size_text|True if size should fit the text length| +|auto_size_buttons|| +|font|specifies the font family, size, etc| +|border_width|width of border around element| +|slider_border_width|| +|slider_relief|| +|slider_orientation|| +|autoclose_time|| +|message_box_line_width|| +|progress_meter_border_depth|| +|progress_meter_style|| +|progress_meter_relief|| +|progress_meter_color|| +|progress_meter_size|Tuple[int, int]| +|text_justification|| +|background_color|color of background| +|element_background_color|| +|text_element_background_color|| +|input_elements_background_color|| +|input_text_color|| +|scrollbar_color|| +|text_color|color of the text| +|element_text_color|| +|debug_win_size|Tuple[int, int] (Default = (None))| +|window_location|(Default = (None))| +|error_button_color|(Default = (None))| +|tooltip_time|time in milliseconds to wait before showing a tooltip. Default is 400ms| +|use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| +|ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Submit')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|bind_return_key|(Default = True)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +``` +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, + metadata=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|button_text|text in the button (Default value = 'Yes')| +|size|(w,h) w=characters-wide, h=rows-high| +|auto_size_button|True if button size is determined by button text| +|button_color|button color (foreground, background)| +|disabled|set disable state for element (Default = False)| +|tooltip|(str) text, that will appear when mouse hovers over the element| +|font|specifies the font family, size, etc| +|bind_return_key|(Default = True)| +|focus|if focus should be set to this| +|pad|Amount of padding to put around element| +|key|Used with window.FindElement and with return values to uniquely identify this element| +||| +| **return** | (Button) | + +## Debug Window Output + +``` +easy_print(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +easy_print_close() +``` + +``` +eprint(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +sgprint(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +sgprint_close() +``` + +``` +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, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +EasyPrintClose() +``` + +``` +Print(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +PrintClose() +``` + ## OneLineProgressMeter ``` @@ -15250,6 +15787,46 @@ Parameter Descriptions: |---|---| |key|Used with window.FindElement and with return values to uniquely identify this element| +``` +one_line_progress_meter(title, + current_value, + max_value, + key, + args, + orientation="v", + bar_color=(None, None), + button_color=None, + size=(20, 20), + border_width=None, + grab_anywhere=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|title|text to display| +|current_value|current progressbar value| +|max_value|max value of progressbar| +|key|Used with window.FindElement and with return values to uniquely identify this element| +|*args|stuff to output.| +|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| +|bar_color|| +|button_color|button color (foreground, background)| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| +|border_width|width of border around element| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| + +``` +one_line_progress_meter_cancel(key) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|Used with window.FindElement and with return values to uniquely identify this element| + ## Popup Functions Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the @@ -16144,659 +16721,7 @@ Parameter Descriptions: ||| | **return** | Union["Yes", "No", None] | -``` -Print(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -PrintClose() -``` - -``` -Quit(button_text="Quit", - size=(None, None), - auto_size_button=None, - button_color=None, - disabled=False, - tooltip=None, - font=None, - bind_return_key=False, - focus=False, - pad=None, - key=None, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Quit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -``` -RButton(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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button| -|image_filename|image filename if there is a button image| -|image_data|in-RAM image to be displayed on button| -|image_size|size of button image in pixels| -|image_subsample|amount to reduce the size of the image| -|border_width|width of border around element| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|disabled|set disable state for element (Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button| -|image_filename|image filename if there is a button image| -|image_data|in-RAM image to be displayed on button| -|image_size|size of button image in pixels| -|image_subsample|amount to reduce the size of the image| -|border_width|width of border around element| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|disabled|set disable state for element (Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button| -|image_filename|image filename if there is a button image| -|image_data|in-RAM image to be displayed on button| -|image_size|size of button image in pixels| -|image_subsample|amount to reduce the size of the image| -|border_width|width of border around element| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high (Default = (None))| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|font|specifies the font family, size, etc| -|disabled|set disable state for element (Default = False)| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Save')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|bind_return_key|(Default = True)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -``` -SaveAs(button_text="Save As...", - target=(555666777, -1), - file_types=(('ALL Files', '*.*'),), - initial_folder=None, - disabled=False, - tooltip=None, - size=(None, None), - auto_size_button=None, - button_color=None, - change_submits=False, - enable_events=False, - font=None, - pad=None, - key=None, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Save As...')| -|target|key or (row,col) target for the button (Default value = (ThisRow, -1))| -|file_types|(Default value = (("ALL Files", "*.*")))| -|initial_folder|starting path for folders and files| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|change_submits|If True, pressing Enter key submits window (Default = False)| -|enable_events|Turns on the element specific events.(Default = False)| -|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you -want, just like a print statement. - -``` -ScrolledTextBox(args, - title=None, - button_color=None, - background_color=None, - text_color=None, - yes_no=False, - auto_close=False, - auto_close_duration=None, - size=(None, None), - location=(None, None), - non_blocking=False, - no_titlebar=False, - grab_anywhere=False, - keep_on_top=False, - font=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|(Any) Variable number of items to display| -|title|(str) Title to display in the window.| -|button_color|Tuple[str, str] button color (foreground, background)| -|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| -|auto_close|(bool) if True window will close itself| -|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| -|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| -||| -| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | - -Sets the icon which will be used any time a window is created if an icon is not provided when the -window is created. - -``` -SetGlobalIcon(icon) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|icon|Union[bytes, str] Either a Base64 byte string or a filename| - -``` -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), - error_button_color=(None, None), - tooltip_time=None, - use_ttk_buttons=None, - ttk_theme=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|icon|filename of icon used for taskbar and title bar| -|button_color|button color (foreground, background)| -|element_size|Tuple[int, int] element size (width, height) in characters| -|button_element_size|Tuple[int, int]| -|margins|tkinter margins around outsize (Default = (None))| -|element_padding|(Default = (None))| -|auto_size_text|True if size should fit the text length| -|auto_size_buttons|| -|font|specifies the font family, size, etc| -|border_width|width of border around element| -|slider_border_width|| -|slider_relief|| -|slider_orientation|| -|autoclose_time|| -|message_box_line_width|| -|progress_meter_border_depth|| -|progress_meter_style|| -|progress_meter_relief|| -|progress_meter_color|| -|progress_meter_size|Tuple[int, int]| -|text_justification|| -|background_color|color of background| -|element_background_color|| -|text_element_background_color|| -|input_elements_background_color|| -|input_text_color|| -|scrollbar_color|| -|text_color|color of the text| -|element_text_color|| -|debug_win_size|Tuple[int, int] (Default = (None))| -|window_location|(Default = (None))| -|error_button_color|(Default = (None))| -|tooltip_time|time in milliseconds to wait before showing a tooltip. Default is 400ms| -|use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| -|ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Submit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|bind_return_key|(Default = True)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -Time your code easily.... start the timer. - -``` -TimerStart() -``` - -Time your code easily.... stop the timer and print the number of ms since the timer start - -``` -TimerStop() -``` - -``` -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, - metadata=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|button_text|text in the button (Default value = 'Yes')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = True)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | - -## PEP8 Function Bindings - -Change the "color scheme" of all future PySimpleGUI Windows. -The scheme are string names that specify a group of colors. Background colors, text colors, button colors. -There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel -The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. -The original list was (prior to a major rework and renaming)... these names still work... -In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: -The "Formula" is: -["Dark" or "Light"] Color Number -Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black -The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. -Default = The default settings (only button color is different than system default) -Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - -``` -change_look_and_feel(index, force=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| -|force|(bool) no longer used| - -``` -easy_print(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -easy_print_close() -``` - -``` -eprint(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -Fills a window with values provided in a values dictionary { element_key : new_value } - -``` -fill_form_with_values(window, values_dict) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|window|(Window) The window object to fill| -|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| - -Get a list of the valid values to pass into your call to change_look_and_feel - -``` -list_of_look_and_feel_values() -> List[str] - list of valid string values -``` - -The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. - -``` -main() -``` - -Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form - -``` -obj_to_string(obj, extra=" ") -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|obj|(Any) The object to display| -|extra|(Default value = ' ') returns (str) Formatted output of the object's values| - -Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form -Returns only the top-most object's variables instead of drilling down to dispolay more - -``` -obj_to_string_single_obj(obj) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|obj|(Any) The object to display returns (str) Formatted output of the object's values| - -``` -one_line_progress_meter(title, - current_value, - max_value, - key, - args, - orientation="v", - bar_color=(None, None), - button_color=None, - size=(20, 20), - border_width=None, - grab_anywhere=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|title|text to display| -|current_value|current progressbar value| -|max_value|max value of progressbar| -|key|Used with window.FindElement and with return values to uniquely identify this element| -|*args|stuff to output.| -|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| -|bar_color|| -|button_color|button color (foreground, background)| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| -|border_width|width of border around element| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| - -``` -one_line_progress_meter_cancel(key) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|key|Used with window.FindElement and with return values to uniquely identify this element| - -## Popups +## Popups PEP8 Versions Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the "print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. @@ -17690,51 +17615,52 @@ Parameter Descriptions: ||| | **return** | Union["Yes", "No", None] | -Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. -They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves +## PEP8 Function Bindings + +Fills a window with values provided in a values dictionary { element_key : new_value } ``` -preview_all_look_and_feel_themes(columns=12) +fill_form_with_values(window, values_dict) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|columns|(int) The number of themes to display per row| +|window|(Window) The window object to fill| +|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| + +The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. ``` -quit(button_text="Quit", - size=(None, None), - auto_size_button=None, - button_color=None, - disabled=False, - tooltip=None, - font=None, - bind_return_key=False, - focus=False, - pad=None, - key=None, - metadata=None) +main() +``` + +Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + +``` +obj_to_string(obj, extra=" ") ``` Parameter Descriptions: |Name|Meaning| |---|---| -|button_text|text in the button (Default value = 'Quit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | +|obj|(Any) The object to display| +|extra|(Default value = ' ') returns (str) Formatted output of the object's values| + +Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form +Returns only the top-most object's variables instead of drilling down to dispolay more + +``` +obj_to_string_single_obj(obj) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|obj|(Any) The object to display returns (str) Formatted output of the object's values| Sets the icon which will be used any time a window is created if an icon is not provided when the window is created. @@ -17827,41 +17753,6 @@ Parameter Descriptions: |use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| |ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| -``` -sgprint(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True, - text_color=None, - background_color=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -sgprint_close() -``` - Shows the smaller "popout" window. Default location is the upper right corner of your screen ``` @@ -17931,6 +17822,146 @@ The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the E test() ``` +## Themes + +Sets / Gets the current Theme. If none is specified then returns the current theme. +This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + +``` +theme(new_theme=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|new_theme|(str) the new theme name to use| +||| +| **return** | (str) the currently selected theme | + +Returns the background color specified by the current color theme + +``` +theme_background_color() -> (str) - color string of the background color defined by current theme +``` + +Returns the button color specified by the current color theme + +``` +theme_button_color() -> Tuple[str, str] - TUPLE with color strings of the button color defined by current theme (button text color, button background color) +``` + +Returns the input element background color specified by the current color theme + +``` +theme_input_background_color() -> (str) - color string of the input element background color defined by current theme +``` + +Returns the input element text color specified by the current color theme + +``` +theme_input_text_color() -> (str) - color string of the input element text color defined by current theme +``` + +Returns a sorted list of the currently available color themes + +``` +theme_list() -> List[str] - A sorted list of the currently available color themes +``` + +Show a window with all of the color themes - takes a while so be patient + +``` +theme_previewer(columns=12) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|columns|(int) number of themes in a single row| + +Returns the text color specified by the current color theme + +``` +theme_text_color() -> (str) - color string of the text color defined by current theme +``` + +## Old Themes (Look and Feel) - Replaced by theme() + +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. +The original list was (prior to a major rework and renaming)... these names still work... +In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: +The "Formula" is: +["Dark" or "Light"] Color Number +Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black +The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. +Default = The default settings (only button color is different than system default) +Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + +``` +ChangeLookAndFeel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| +|force|(bool) no longer used| + +Get a list of the valid values to pass into your call to change_look_and_feel + +``` +ListOfLookAndFeelValues() -> List[str] - list of valid string values +``` + +Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. +They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + +``` +preview_all_look_and_feel_themes(columns=12) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|columns|(int) The number of themes to display per row| + +Get a list of the valid values to pass into your call to change_look_and_feel + +``` +list_of_look_and_feel_values() -> List[str] - list of valid string values +``` + +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. +The original list was (prior to a major rework and renaming)... these names still work... +In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: +The "Formula" is: +["Dark" or "Light"] Color Number +Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black +The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. +Default = The default settings (only button color is different than system default) +Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + +``` +change_look_and_feel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| +|force|(bool) no longer used| + --- # "Demo Programs" Applications @@ -18135,11 +18166,11 @@ Macs and PySimpleGUI did not play well together up until Nov 2019 and the releas The problems were the normal tk.Button was not working correctly on the Mac. You couldn't set the button color. If you tried it appeared as if the text was missing. -Users have recently reported the ability to install Python 3.7 from the Python.org website and NOT used (I think removed) the "Homebrew" version of Python. This resolved all of the button color problems. +Users have recently reported the ability to install Python 3.7 from the Python.org website and not use the Homebrew version. This resolved all of the button color problems. -Regardless, Macs can now enjoy using all of the look and feel color themes that Windows and Linux users are able to achieve. +Regardless of where you get your Python / tkinter, Macs can now enjoy using all of the look and feel color themes that Windows and Linux users are able to achieve. -Many PySimpleGUI users have switched from PySimpleGUI to PySimpleGUIQt due to the button problems. IF you're one of them, you should consider switching back. One reason to return is that features tend to get iumplemented on PySimpleGUI (tkinger version) and then later on the other ports. There are a number of other reasons to give tkinter another try. +Many PySimpleGUI users have switched from PySimpleGUI to PySimpleGUIQt due to the button problems. IF you're one of them, ***you should consider switching back***. One reason to return to PySimpleGUI is that features tend to get iumplemented on PySimpleGUI (tkinger version) and then later on the other ports. There are a number of other reasons to give tkinter another try. ## Multiple threads @@ -18153,6 +18184,37 @@ Other than that, feel free to use threads with PySimpleGUI on all of the ports. Be sure and **delete** your windows after you close them if you are running with multiple threads. There is a chance another thread's garbage collect will attempt to delete the window when not in the mainthread which will cause tkinter to crash. +### The dreaded "Tcl_AsyncDelete: async handler deleted by the wrong thread" error + +This crash has plagued and mystified tkinter users for some time now. It happens when the user is running multiple threads in their application. Even if the user doesn't make any calls that are into tkinter, this problem can still cause your program to crash. + +I'm thrilled to say there's a solution and it's easy to implement. If you're getting this error, then here is what is causing it. + +When you close a window and delete the layout, the tkinter widgets that were in use in the window are no longer needed. Python marks them to be handled by the "Garbage Collector". They're deleted but not quite gone from memory. Then, later, while your thread is running, the Python Garbage Collect algorithm decides it's time to run garbage collect. When it tells tkinter to free up the memory, the tkinter code looks to see what context it is running under. It sees that it's a thread, not the main thread, and generates this exception. + +The way around this is actually quite easy. + +When you are finished with a window, be sure to: + +* Close the Window +* Set the `layout` variable to None +* Set the `window` variable to None +* Trigger Python's Garbage Collect to run immediately + +The sequence looks like this in code: + +```python + import gc + + # Do all your windows stuff... make a layout... show your window... then when time to exit + window.close() + layout = None + window = None + gc.collect() +``` + +This will ensure that the tkinter widgets are all deleted in the context of the mainthread and another thread won't accidently run the Garbage Collect + # Contributing ## Write Applications @@ -18161,7 +18223,7 @@ The way for you to contribute to the PySimpleGUI is to create and share PySimple ## Pull Requests -***PySimpleGUI code changes/pull requests are not being accepted at this time.*** +***PySimpleGUI changes/pull requests are not being accepted at this time.*** ## GitHub Repos diff --git a/readme_creator/1_HEADER_top_part.md b/readme_creator/1_HEADER_top_part.md index d3ff72c2..ae80f29d 100644 --- a/readme_creator/1_HEADER_top_part.md +++ b/readme_creator/1_HEADER_top_part.md @@ -28,16 +28,21 @@ HOW DO I INSERT IMAGES ??? ![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) [![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) tkinter + [![Downloads ](https://pepy.tech/badge/pysimplegui27)](https://pepy.tech/project/pysimplegui27) tkinter 2.7 (WARNING - DISAPPEARING Entirely on 12/31/2019!!!) + [![Downloads](https://pepy.tech/badge/pysimpleguiqt)](https://pepy.tech/project/pysimpleguiqt) Qt + [![Downloads](https://pepy.tech/badge/pysimpleguiwx)](https://pepy.tech/project/pysimpleguiWx) WxPython + [![Downloads](https://pepy.tech/badge/pysimpleguiweb)](https://pepy.tech/project/pysimpleguiWeb) Web (Remi) + ![Documentation Status](https://readthedocs.org/projects/pysimplegui/badge/?version=latest) ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.7.0-red.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.13.1-red.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.1-blue.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.30.0-orange.svg?longCache=true&style=for-the-badge) @@ -191,12 +196,18 @@ and returns the value input as well as the button clicked. [How to submit an Issue](https://github.com/PySimpleGUI/PySimpleGUI/issues/1646) -The YouTube videos - If you like instructional videos, there are over 15 videos +The YouTube videos - If you like instructional videos, there are over 15 videos made by PySimpleGUI project - [5 part series of basics](https://www.youtube.com/playlist?list=PLl8dD0doyrvHMoJGTdMtgLuHymaqJVjzt) - [10 part series of more detail](https://www.youtube.com/playlist?list=PLl8dD0doyrvGyXjORNvirTIZxKopJr8s0) - [The Naked Truth (An updaate on the technology)](https://youtu.be/BFTxBmihsUY) - There are numerous short videos also on that channel that demonstrate PySimpleGUI being used +YouTube Videos made by others. These have much higher production values than the above videos. + +- A ***fantastic*** tutorial [PySimpleGUI Concepts - Video 1](https://youtu.be/cLcfLm_GgiM) +- Build a calculator [Python Calculator with GUI | PySimpleGUI | Texas Instruments DataMath II](https://youtu.be/x5LSTDdffFk) +- Notepad [Notepad in Python - PySimpleGUI](https://youtu.be/JQY641uynKo) +- File Search Engine [File Search Engine | Project for Python Portfolio with GUI | PySimpleGUI](https://youtu.be/IWDC9vcBIFQ) # About The PySimpleGUI Documentation System @@ -260,10 +271,10 @@ PySimpleGUI runs on Windows, Linux and Mac, just like tkinter, Qt, WxPython and ### OS * Windows 7, 8, 10 -* Linux on PC - Tested on **many** distributions +* Linux on PC - Tested on several distributions * Linux on Raspbnerry Pi * Linux on Android - Can use either Termux or PyDroid3 -* Mac OS (Sorry don't know much about Macs other than Macs don't like tkinter) +* Mac OS #### Python versions @@ -439,6 +450,35 @@ PySimpleGUIWeb is first and foremost a **GUI**, a program's front-end. It is des If more than 1 person connects at a time, then both users will see the exact same stuff and will be interacting with the program as if a single user was using it. +## Android Version + +PySimpleGUI runs on Android devices with the help of either the PyDroid3 app or the Termux app. Both are capable of running tkinter programs which means both are capable of running PySimpleGUI. + +To use with PyDroid3 you will need to add this import to the top of all of your PySimpleGUI program files: + +```python +import tkinter +``` + +This evidently triggers PyDroid3 that the application is going to need to use the GUI. + +You will also want to create your windows with the `location` parameter set to `(0,0)`. + +Here's a quick demo that uses OpenCV2 to display your webcam in a window that runs on PyDroid3: + +```python +import tkinter +import cv2, PySimpleGUI as sg +USE_CAMERA = 0 # change to 1 for front facing camera +window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(0, 0), grab_anywhere=True), cv2.VideoCapture(USE_CAMERA) +while window(timeout=20)[0] is not None: + window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) +``` + +You will need to pip install opencv-python as well as PySimpleGUI to run this program. + +Also, you must be using the Premium, yes paid, version of PyDroid3 in order to run OpenCV. The cost is CHEAP when compared to the rest of things in life. A movie ticket will cost you more. Which is more fun, seeing **your Python program** running on your phone and using your phone's camera, or some random movie currently playing? From experience, the Python choice is a winner. If you're cheap, well, then you won't get to use OpenCV. No, there is no secret commercial pact between the PySimpleGUI project and the PyDroid3 app team. + ## Source code compatibility @@ -493,13 +533,17 @@ Repl.it is not meant to serve up applications and web pages. Trying to use it t It's surprising that Python GUI code is completely cross platform from Windows to Mac to Linux. No source code changes. This is true for both PySimpleGUI and PySimpleGUIQt. -However, **Macs** suck. They suck on tkinter in particular. The "Look and feel" calls are disabled for Macs. Colored buttons in particular are broken. And, you are unable to specify filetypes when using the FileBrowse button. None of this is PySimpleGUI code issues, of course, they're all in tkinter. Consider using Qt instead of tkinter on the Mac. Or, if using tkinter, create your own button images. +Historicly, PySimpleGUI using tkinter have struggled on Macs. This was because of a problem setting button colors on the Mac. However, two events has turned this problem around entirely. -***Look through the open and closed issues if you're a Mac person with a problem. It's highly likely the problem has been at least seen previously and there may even be a fix or workaround*** +1. Use of ttk Buttons for Macs +2. Ability for Mac users to install Python from python.org rather than the Homebrew version with button problems -*Switching to "Light Mode" is known to fix some of the problems.* They honestly are tkinter/Mac problems. +It's been a long road for Mac users with many deciding to use PySimpleGUIQt so that multi-colored windows could be made. It's completely understandable to want to make attractive windows that utilitize colors. + +PySimpleGUI now supports Macs, Linux, and Windows equally well. They all are able to use the "Themes" that automatically add color to your windows. + +Be aware that Macs default to using ttk buttons. You can override this setting at the Window and Button levels. If you installed Python from python.org, then it's likely you can use the non-ttk buttons should you wish. -Make sure you're running tkinter 8.6 and up. However, as I'm learning 8.6 can mean almost anything as the minor release numbers are not provided (8.6.1, etc). Turns out 8.6 has been in development for YEARS. The 8.6 that comes with Python 3.7.4 doesn't support table colors for example even though it's version 8.6. # Support @@ -744,13 +788,16 @@ Creating and reading the user's inputs for the window occupy the last 2 lines of ```python import PySimpleGUI as sg -layout = [[sg.Text('Filename')], - [sg.Input(), sg.FileBrowse()], - [sg.OK(), sg.Cancel()]] +sg.change_look_and_feel('Dark Blue 3') # please make your creations colorful + +layout = [ [sg.Text('Filename')], + [sg.Input(), sg.FileBrowse()], + [sg.OK(), sg.Cancel()]] window = sg.Window('Get filename example', layout) event, values = window.Read() +window.close() ``` ![get filename](https://user-images.githubusercontent.com/13696193/44960039-f1018880-aec5-11e8-8a43-3d7f8ff93b67.jpg) @@ -850,8 +897,9 @@ Just because you can't match a pair of socks doesn't mean your windows have to a In PySimpleGUI release 4.6 the number of themes was dramatically increased from a couple dozen to over 100. To use the color schemes shown in the window below, add a call to `change_look_and_feel('Theme Name)` to your code, passing in the name of thd desired color theme. To see this window and the list of available themes on your releeae of softrware, call the function `preview_all_look_and_feel_themes()`. This will create a window with the frames like those below. It will shows you exactly what's available in your version of PySimpleGUI. -![Nov 2019 Look and Feel Themes](https://user-images.githubusercontent.com/46163555/68987669-91a54500-07f9-11ea-921e-8bf9320e3156.png) +In release 4.9 another 32 Color Themes were added... here are the current choices +![Dec 2019 Look And Feel Themes](https://user-images.githubusercontent.com/46163555/70382042-796da500-1923-11ea-8432-80d08cd5f503.jpg) Make beautiful looking, alpha-blended (partially transparent) Rainmeter-style Desktop Widgets that run in the background. @@ -983,6 +1031,7 @@ Features of PySimpleGUI include: - Calendar chooser - Color chooser - Button Menu +- TTK Buttons or "normal" TK Buttons - Checkboxes - Radio Buttons - Listbox @@ -1097,7 +1146,7 @@ Beginners certainly can add more `if event == 'my button':` statements to the ev The hope is that beginners that are interested in graphic design, and are taking a Python course, will have an easy way to express themselves, right from the start of their Python experience. Even if they're not the best programmers they will be able express themselves to show custom GUI layouts, colors and artwork with ease. -> Fill the GUI Gap +> Fill the GUI Gap (Democratize GUIs) There is a noticeable gap in the Python GUI solution. Fill that gap and who knows what will happen. At the moment, to make a tradiional GUI window using tkinter, Qt, WxPython and Remi, it takes much more than a week, or a month of Python education to use these GUI packages. @@ -1155,6 +1204,8 @@ More information about installing tkinter can be found here: https://www.techinf ### Installing for Python 2.7 +**IMPORTANT** PySimpleGUI27 will disappear from the GitHub on Dec 31, 2019. PLEASE migrate to 3.6 at least. It's not painful for most people. + `pip install --upgrade PySimpleGUI27` or `pip2 install --upgrade PySimpleGUI27` @@ -1165,7 +1216,6 @@ You may need to also install "future" for version 2.7 or `pip2 install future` -Python 2.7 support is relatively new and the bugs are still being worked out. I'm unsure what may need to be done to install tkinter for Python 2.7. Will update this readme when more info is available Like above, you may have to install either pip or tkinter. To do this on Python 2.7: @@ -1304,38 +1354,17 @@ Then use either "high level" API calls or build your own windows. Yes, it's just that easy to have a window appear on the screen using Python. With PySimpleGUI, making a custom window appear isn't much more difficult. The goal is to get you running on your GUI within ***minutes***, not hours nor days. -***WARNING*** Do NOT use PySimpleGUI with Python 3.7.3 and 3.7.4. tkiter is having issues with that release. Things like Table colors stopped working entirely. None of us want to debug tkinter code. It's difficult enough debugging your code and PySimpleGUI code. A lot of time has already been spent debugging this one so no need for you to suffer too. ### Python 3.7 -It puzzles me why a beginner would install 3.7. Or even a seasoned programmer. What specific feature of 3.7 are you using that is not in 3.6? If you are unable to answer this, then ***it's strongly suggested that you run 3.6***, an immensely solid release of Python with all those goodie inside like f-strings. If you must run 3.7, try 3.7.2 instead. It does work with PySimpleGUI with no known issues. +If you must run 3.7, try 3.7.2. It does work with PySimpleGUI with no known issues. +***PySimpleGUI with Python 3.7.3 and 3.7.4+.*** tkinter is having issues with all the newer releases. Things like Table colors stopped working entirely. It's unclear if there's been a change that makes the tkinter API no longer working which means they are not backwards compatible. That would be a real shame. If so, more work needs to be done in PySimpleGUI -## Using - Python 2.7 +## Python 2.7 -Those using Python 2.7 will import a different module name +On December 31, 2019 the Python 2.7 version of PySimpleGUI will be **deleted** from the GitHub. Sorry but Legacy Python has no permanent home here. The security experts claim that supporting 2.7 is doing a diservice to the Python community. I understand why. There are some very narrow cases where 2.7 is required. If you have one, make a copy of PySimpleGUI27.py quickly before it disappears for good. -```python -import PySimpleGUI27 as sg -``` - - - -## Code to Automatically Import Correct Version - -Many of the demo programs use this check to see which package to use: -```python -import sys -if sys.version_info[0] >= 3: - import PySimpleGUI as sg -else: - import PySimpleGUI27 as sg -``` - - -This will automatically import the correct library based on the Python version number reported by the Python interpreter. - -NOTE: It's 2019 and 2.7 support is being systematically removed. This construct will be removed from the demo programs shortly. 2.7 users can still run these demos, but they will need to change the import from PySimpleGUI to PySimpleGUI27. It save 4 lines of code and an import from sys in the process. --- diff --git a/readme_creator/2_readme.md b/readme_creator/2_readme.md index 7aece01c..e515d525 100644 --- a/readme_creator/2_readme.md +++ b/readme_creator/2_readme.md @@ -429,11 +429,13 @@ Writing the code for this one is just as straightforward. There is one tricky t ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ] -window sg.Window('Get filename example', layout) +window = sg.Window('Get filename example', layout) event, values = window.read() window.close() @@ -455,6 +457,9 @@ The input fields in your window will be returned to you as a dictionary (syntact ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + + layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], [sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]] @@ -476,6 +481,8 @@ This code will present a window and will print values until the user clicks the ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('Persistent window')], [sg.Input()], [sg.Button('Read'), sg.Exit()]] @@ -504,7 +511,9 @@ This example introduces the concept of "keys". Keys are super important in PySi ```python import PySimpleGUI as sg -layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', size=(12,1), key='_OUTPUT_')], +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + +layout = [[sg.Text('Your typed chars appear here:'), sg.Text(size=(12,1), key='_OUTPUT_')], [sg.Input(key='_IN_')], [sg.Button('Show'), sg.Button('Exit')]] @@ -541,6 +550,8 @@ Let's dissect this little program ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('Rename files or folders')], [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], @@ -554,8 +565,17 @@ folder_path, file_path = values[0], values[1] # get the data from the valu print(folder_path, file_path) ``` +#### Colors + +![image](https://user-images.githubusercontent.com/46163555/70470775-cd01ff00-1a99-11ea-8b9c-8b33c8880c99.png) + +The first line of code after the import is a call to `change_look_and_feel`. This single line of code make the window look like the window above instead of the window below. It will also stop PySimpleGUI from nagging you to put one of these calls into your program. + + ![snap0131](https://user-images.githubusercontent.com/13696193/43417007-df6d8408-9407-11e8-9986-30f0415f08a5.jpg) +#### Window contents + Let's agree the window has 4 rows. The first row only has **text** that reads `Rename files or folders` @@ -579,6 +599,8 @@ For return values the window is scanned from top to bottom, left to right. Each In our example window, there are 2 fields, so the return values from this window will be a dictionary with 2 values in it. Remember, if you do not specify a `key` when creating an element, one will be created for you. They are ints starting with 0. In this example, we have 2 input elements. They will be addressable as values[0] and values[1] +#### "Reading" the window's values (also displays the window) + ```python event, values = window.read() folder_path, file_path = values[0], values[1] @@ -647,7 +669,7 @@ while True: event, values = window.read() if event is None: break -window.Close() +window.close() ``` You will very often see the examples and demo programs write this check as: @@ -793,6 +815,8 @@ Let's take a look at your first dictionary-based window. ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [ [sg.Text('Please enter your Name, Address, Phone')], [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='_NAME_')], @@ -803,7 +827,7 @@ layout = [ window = sg.Window('Simple data entry window', layout) event, values = window.read() -window.Close() +window.close() sg.Popup(event, values, values['_NAME_'], values['_ADDRESS_'], values['_PHONE_']) ``` @@ -884,6 +908,7 @@ layout = [ window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False) event, values = window.read() +window.close() sg.Popup('Title', 'The results of the window.', @@ -1011,12 +1036,6 @@ You can get your window's size by access the `Size` property. The window has to To finalize your window: -```python -window = Window('My Title', layout).Finalize() -``` - -If using PySimpleGUI 4.2 and later: - ```python window = Window('My Title', layout, finalize=True) ``` @@ -1067,6 +1086,26 @@ To keep a window on top of all other windows on the screen, set keep_on_top = Tr PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call. +### TTK Buttons + +Beginning in release 4.7.0 PySimpleGUI supports both "normal" tk Buttons and ttk Buttons. This change was needed so that Mac users can use colors on their buttons. There is a bug that causes tk Buttons to not show text when you attempt to change the button color. Note that this problem goes away if you install Python from the official Python.org site rather than using Homebrew. A number of users have switched and are quite happy since even tk Buttons work on the Mac after the switch. + +By default Mac users will get ttk Buttons when a Button Element is used. All other platforms will get a normal tk Button. There are ways to override this behavior. One is by using the parameter `use_ttk_buttons` when you create your window. If set to True, all buttons will be ttk Buttons in the window. If set to False, all buttons will be normal tk Buttons. If not set then the platform or the Button Element determines which is used. + +If a system-wide setting is desired, then the default can be set using `set_options`. This will affect all windows such as popups and the debug window. + +### TTK Themes + +tkinter has a number of "Themes" that can be used with ttk widgets. In PySimpleGUI these widgets include - Table, Tree, Combobox, Button, ProgressBar, Tabs & TabGroups. Some elements have a 'theme' parameter but these are no longer used and should be ignored. The initial release of PySimpleGUI attempted to mix themes in a single window but since have learned this is not possible so instead it is set at the Window or the system level. + +If a system-wide setting is desired, then the default can be set using `set_options`. This will affect all windows such as popups and the debug window. + +The ttk theme choices depend on the platform. Linux has a shorter number of selections than Windows. These are the Windows choices: +'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + +There are constants defined to help you with code completion to determine what your choices are. Theme constants start with `THEME_`. For example, the "clam" theme is `THEME_CLAM` + +You're urged to experiment with this setting to determine which you like the most. They change the ttk-based elements in subtle but still significant ways. ## Closing Windows @@ -1098,8 +1137,8 @@ This is the "long form" as each method is called individually. ```python window = sg.Window('My Title') -window.Layout(layout) -window.Finalize() +window.layout(layout) +window.finalize() ``` ### Chaining The Calls (the old method) @@ -1107,7 +1146,7 @@ window.Finalize() The next level of compression that was done was to chain the calls together into a single line of code. ```python -window = sg.Window('My Title').Layout(layout).Finalize() +window = sg.Window('My Title').Layout(layout).finalize() ``` ### Using Parameters Instead of Calls (New Preferred Method) @@ -1128,14 +1167,14 @@ Call to set the window layout. Must be called prior to `Read`. Most likely "ch window = sg.Window('My window title', layout) ``` -#### `Finalize()` or `Window` parameter `finalize=True` +#### `finalize()` or `Window` parameter `finalize=True` Call to force a window to go through the final stages of initialization. This will cause the tkinter resources to be allocated so that they can then be modified. This also causes your window to appear. If you do not want your window to appear when Finalize is called, then set the Alpha to 0 in your window's creation parameters. If you want to call an element's `Update` method or call a `Graph` element's drawing primitives, you ***must*** either call `Read` or `Finalize` prior to making those calls. -#### Read(timeout=None, timeout_key=TIMEOUT_KEY) +#### read(timeout=None, timeout_key=TIMEOUT_KEY) Read the Window's input values and button clicks in a blocking-fashion @@ -1366,11 +1405,13 @@ The first part should look familiar since it was just discussed as being what bu ### Putting it all together -Here is our final program that uses simple addition to add the headers onto the top of the input matrix. +Here is our final program that uses simple addition to add the headers onto the top of the input matrix. To make it more attractive, the color theme is set to 'Dark Brown 1'. ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Brown 1') + headings = ['HEADER 1', 'HEADER 2', 'HEADER 3','HEADER 4'] header = [[sg.Text(' ')] + [sg.Text(h, size=(14,1)) for h in headings]] @@ -1382,6 +1423,8 @@ window = sg.Window('Table Simulation', layout, font='Courier 12') event, values = window.read() ``` +![image](https://user-images.githubusercontent.com/46163555/70472374-f7a18700-1a9c-11ea-9cd1-27d386cd9066.png) + ## User Defined Elements / Compound Elements @@ -1946,8 +1989,6 @@ You can call the method without setting the `time_between_frames` value and it w ## Button Element -**MAC USERS** - Macs suck when it comes to tkinter and button colors. It sucks so badly with colors that the `LookAndFeel` call is disabled. You cannot change button colors for Macs. You're stuck with the system default color if you are using the tkinter version of PySimpleGUI. The Qt version does not have this issue. - Buttons are the most important element of all! They cause the majority of the action to happen. After all, it's a button press that will get you out of a window, whether it be Submit or Cancel, one way or another a button is involved in all windows. The only exception is to this is when the user closes the window using the "X" in the upper corner which means no button was involved. The Types of buttons include: @@ -2013,7 +2054,11 @@ layout = [[sg.Ok(), sg.Cancel()]] In reality `Button` is in fact being called on your behalf. Behind the scenes, `sg.Ok` and `sg.Cancel` call `Button` with the text set to `Ok` and `Cancel` and returning the results that then go into the layout. If you were to print the layout it will look identical to the first layout shown that has `Button` shown specifically in the layout. +### TTK Buttons & Macs +In 2019 support for ttk Buttons was added. This gets around the problem of not being able to change button colors on a Mac. There are a number of places you can control whether or not ttk buttons are used, be it on MAc or other platform. + +TTK Buttons and TK Buttons operate slightly differently. Button highlighting is one different. How images and text are displayed at the same time is another. You've got options now that weren't there previously. It's nice to see that Mac users can finally use the color themes. ### Button Element Shortcuts These Pre-made buttons are some of the most important elements of all because they are used so much. They all basically do the same thing, **set the button text to match the function name and set the parameters to commonly used values**. If you find yourself needing to create a custom button often because it's not on this list, please post a request on GitHub. . They include: @@ -2266,12 +2311,12 @@ This element has limited usefulness and is being included more for completeness It works best when placed between columns or elements that span multiple rows. If on a "normal" row with elements that are only 1 row high, then it will only span that one row. - ```python VerticalSeparator(pad=None) ``` + ![snag-0129](https://user-images.githubusercontent.com/13696193/47376041-a92a0100-d6bf-11e8-8f5b-0c0df56cf0f3.jpg) @@ -2343,15 +2388,12 @@ If you are looking for a way to quickly add the ability to show scrolling text w ***IMPORTANT*** You will NOT see what you `print` until you call either `window.Read` or `window.Refresh`. If you want to immediately see what was printed, call `window.Refresh()` immediately after your print statement. - - ```python Output(size=(80,20)) ``` ![output](https://user-images.githubusercontent.com/13696193/44959863-b72f8280-aec3-11e8-8caa-7bc743149953.jpg) - ---- @@ -3129,7 +3171,7 @@ while True: ``` -Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and yuou've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? +Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and you've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? Non-blocking (timeout=0) is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine. @@ -3179,7 +3221,7 @@ sg.ChangeLookAndFeel('Black') sg.SetOptions(element_padding=(0, 0)) layout = [[sg.Text('')], - [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], + [sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], [sg.ReadButton('Pause', key='button', button_color=('white', '#001480')), sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'), sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]] @@ -3374,7 +3416,7 @@ import PySimpleGUI as sg # Recipe for getting keys, one at a time as they are released # If want to use the space bar, then be sure and disable the "default focus" -text_elem = sg.Text("", size=(18, 1)) +text_elem = sg.Text(size=(18, 1)) layout = [[sg.Text("Press a key or scroll mouse")], [text_elem], @@ -3539,7 +3581,7 @@ import PySimpleGUI as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2'), sg.Button('Exit')]] win1 = sg.Window('Window 1', layout) @@ -3575,7 +3617,7 @@ import PySimpleGUIQt as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2')]] win1 = sg.Window('Window 1', layout) @@ -3978,56 +4020,58 @@ Watch this space in the future for the more standardized variable name for this ## Binding tkiner "events" -If you wish to receive events directly from tkinter, but do it in a PySimpleGUI way, then there's a particular way at the moment to make this happen. +If you wish to receive events directly from tkinter, but do it in a PySimpleGUI way, then you can do that and get those events returned to you via your standard `Window.read()` call. -tkinter performs a callback into user code when an event happens, but that's not how PySimpleGUI works. Instead of callbacks, a PySimpleGUI user's program simply returns an event via the `window.read()` call. In order for your "event" to generate an event that will be returned to you via your read call, follow these instructions: +Both the Elements and Window objects have a method called `bind`. You specify 2 parameters to this function. One is the string that is used to tell tkinter what events to bind. The other is a "key modifier" for Elements and a "key" for Windows. -1. Create a Button for each event you wish to receive -2. Set visible=False when creating the buttons -3. Make the Button text be the event you want to see returned to you or set the button's Key to that value -4. After creating / finalizing the window, make the tkinter bind call, passing `element.ButtonReboundCallback` as the function to call. +The `key_modifier` in the `Element.bind` call is something that is added to your key. If your key is a string, then this modifier will be appended to your key and the event will be a single string. + +If your element's key is not a string, then a tuple will be returned as the event +(your_key, key_modifier) + +This will enable you to continue to use your weird, non-string keys. Just be aware that you'll be getting back a tuple instead of your key in these situations. + +The best example of when this can happen is in a Minesweeper game where each button is already a tuple of the (x,y) position of the button. Normal left clicks will return (x,y). A right click that was generated as a result of bind call will be ((x,y), key_modifier). + +It'll be tricky for the user to parse these events, but it's assumed you're an advanced user if you're using this capability and are also using non-string keys. + +There are 2 member variables that have also been added as shown in the documentation for the bind methods. This added variable contains the tkinter specific event information. In other words, the 'event' that tkinter normally sends back when a callback happens. + +Here is sample code that shows how to make these calls. + +Three events are being bound. + +1. Any button clicks in the window will return an event "Window Click" from window.read() +2. Right clicking the "Go" buttons will return an event "Go+RIGHT CLICK+" from window.read() +3. When the Input Element receives focus, an event "-IN-+FOCUS+" will be returned from window.read() -This sample code binds not an element events but events from the window itself. In this case, Focus events. ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Green 2') + layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], - [sg.Button('Do Something'), sg.Button('Exit'), - sg.Button('-FOCUS-IN-', visible=False), sg.Button('-FOCUS-OUT-', visible=False)] ] + [sg.Input(key='-IN-'), sg.Text(size=(15,1), key='-OUT-')], + [sg.Button('Go'), sg.Button('Exit')] + ] window = sg.Window('Window Title', layout, finalize=True) -window.TKroot.bind("", window['-FOCUS-IN-'].ButtonReboundCallback) -window.TKroot.bind("", window['-FOCUS-OUT-'].ButtonReboundCallback) -``` +window['-IN-'].bind("", '+FOCUS+') +window.bind("", 'Window Click') +window['Go'].bind("", '+RIGHT CLICK+') -This code binds the right mouse button to a button so that you can right click a button and get a different event than if you left clicked it. - -```python -import PySimpleGUI as sg - -layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], - [sg.Button('Do Something'), sg.Button('Right Click Me')], - [sg.Button('-RIGHT-', visible=False)] - ] - -window = sg.Window('Window Title', layout, finalize=True) - -window['Right Click Me'].Widget.bind("", window['-RIGHT-'].ButtonReboundCallback) - -has_focus = True while True: # Event Loop event, values = window.read() print(event, values) if event in (None, 'Exit'): break -window.close() + +window.close(); del window ``` - +There is no way to "unbind" and event at this time. (sorry, didn't think of it before releasing) --- @@ -4047,27 +4091,11 @@ This section of the documentation is generated directly from the source code. A Without further delay... here are all of the Elements and the Window class - ## Button Element -### ButtonCallBack - - - -### ButtonPressCallBack - - - -### ButtonReboundCallback - - - -### ButtonReleaseCallBack - - ### Click @@ -4089,6 +4117,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4158,6 +4190,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4215,6 +4251,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4276,6 +4316,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4321,18 +4365,11 @@ Without further delay... here are all of the Elements and the Window class -### AddRow - - ### ButtonReboundCallback -### Layout - - - ### SetFocus @@ -4349,6 +4386,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4414,6 +4455,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4459,17 +4504,11 @@ Without further delay... here are all of the Elements and the Window class -### AddRow - - ### ButtonReboundCallback -### Layout - - ### SetFocus @@ -4483,9 +4522,10 @@ Without further delay... here are all of the Elements and the Window class -### add_row - +### bind + + ### button_rebound_callback @@ -4503,9 +4543,6 @@ Without further delay... here are all of the Elements and the Window class -### layout - - ### set_focus @@ -4544,10 +4581,6 @@ Without further delay... here are all of the Elements and the Window class -### ButtonReleaseCallBack - - - ### DeleteFigure @@ -4588,9 +4621,14 @@ Without further delay... here are all of the Elements and the Window class -### MotionCallBack - +### GetBoundingBox + + + +### GetFiguresAtLocation + + ### Move @@ -4624,6 +4662,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### bring_figure_to_front @@ -4636,9 +4678,6 @@ Without further delay... here are all of the Elements and the Window class -### button_release_call_back - - ### delete_figure @@ -4684,6 +4723,17 @@ Without further delay... here are all of the Elements and the Window class + + +### get_bounding_box + + + +### get_figures_at_location + + + + ### get_size @@ -4692,10 +4742,6 @@ Without further delay... here are all of the Elements and the Window class -### motion_call_back - - - ### move @@ -4761,6 +4807,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4826,6 +4876,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4899,6 +4953,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -4968,6 +5026,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5029,6 +5091,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5090,6 +5156,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5155,6 +5225,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5216,6 +5290,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5277,6 +5355,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5317,6 +5399,7 @@ Without further delay... here are all of the Elements and the Window class + ## Radio Element @@ -5346,6 +5429,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5411,6 +5498,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5472,6 +5563,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5533,6 +5628,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5574,17 +5673,11 @@ Without further delay... here are all of the Elements and the Window class -### AddRow - - - ### ButtonReboundCallback -### Layout - ### Select @@ -5602,9 +5695,10 @@ Without further delay... here are all of the Elements and the Window class -### add_row - +### bind + + ### button_rebound_callback @@ -5622,9 +5716,6 @@ Without further delay... here are all of the Elements and the Window class -### layout - - ### select @@ -5655,9 +5746,6 @@ Without further delay... here are all of the Elements and the Window class -### AddRow - - ### ButtonReboundCallback @@ -5671,9 +5759,6 @@ Without further delay... here are all of the Elements and the Window class -### Layout - - ### SetFocus @@ -5683,9 +5768,10 @@ Without further delay... here are all of the Elements and the Window class -### add_row - +### bind + + ### button_rebound_callback @@ -5756,6 +5842,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5788,13 +5878,6 @@ Without further delay... here are all of the Elements and the Window class -### treeview_double_click - - - -### treeview_selected - - ### unhide_row @@ -5825,6 +5908,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5861,6 +5948,34 @@ Without further delay... here are all of the Elements and the Window class +## ToolTip Element + + + + +### enter + + + +### hidetip + + + +### leave + + + +### schedule + + + +### showtip + + + +### unschedule + + ## Tree Element @@ -5887,6 +6002,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5961,6 +6080,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### button_rebound_callback @@ -5993,7 +6116,7 @@ Without further delay... here are all of the Elements and the Window class -## Window +## Window Element @@ -6018,10 +6141,12 @@ Without further delay... here are all of the Elements and the Window class + ### CurrentLocation + ### Disable @@ -6070,6 +6195,7 @@ Without further delay... here are all of the Elements and the Window class + ### GetScreenDimensions @@ -6090,6 +6216,7 @@ Without further delay... here are all of the Elements and the Window class + ### LoadFromDisk @@ -6110,6 +6237,7 @@ Without further delay... here are all of the Elements and the Window class + ### Read @@ -6166,6 +6294,10 @@ Without further delay... here are all of the Elements and the Window class +### bind + + + ### bring_to_front @@ -6242,6 +6374,7 @@ Without further delay... here are all of the Elements and the Window class + ### hide @@ -6274,6 +6407,7 @@ Without further delay... here are all of the Elements and the Window class + ### reappear @@ -6310,21 +6444,21 @@ Without further delay... here are all of the Elements and the Window class + ### visibility_changed +## Function Reference + - - - @@ -6332,22 +6466,12 @@ Without further delay... here are all of the Elements and the Window class - - - - - - - - - - @@ -6358,20 +6482,58 @@ Without further delay... here are all of the Elements and the Window class - - - + + +## Debug Window Output + - - - - - + + + + + + + + +## OneLineProgressMeter + + + + + +## Popup Functions + + + + + + + + + + + + + + + + + + + + + + + + + +## Popups PEP8 Versions + @@ -6388,18 +6550,47 @@ Without further delay... here are all of the Elements and the Window class + - + + +## PEP8 Function Bindings + + + + + + - - - + + + + +## Themes + + + + + + + + + + +## Old Themes (Look and Feel) - Replaced by theme() + + + + + + + diff --git a/readme_creator/3_FOOTER.md b/readme_creator/3_FOOTER.md index 7ff2f541..69428353 100644 --- a/readme_creator/3_FOOTER.md +++ b/readme_creator/3_FOOTER.md @@ -30,6 +30,11 @@ https://github.com/PySimpleGUI/PySimpleGUI/tree/master/PySimpleGUIWeb/Demo%20Pro There are not many programs under each of the port's folders because the main Demo Programs should run on all of the other platforms with minimal changes (often only the import statement changes). +You will also find a lot of demos running on Trinket +http://Trinket.PySimpleGUI.org + + + ## Packages Used In Demos @@ -213,36 +218,80 @@ You'll quickly wonder how you ever coded without it. Well, there are a few quirks, and problems of course. Check the [GitHub Issues database](https://github.com/PySimpleGUI/PySimpleGUI/issues) for a list of them. -As previously mentioned this is also where you should post all problems and enhancements. +As previously mentioned **this is where you should post all problems and enhancements.** + +Random crashes have been rared. The code is stable and hasn't been "quirky" nor have there been many "emergency" releases. -## MACS + tkinter = SUCKS +## MACS & tkinter -Not sure why, but for over a year and a half, setting the color of buttons does not work on Macs. There have been numerous other problems. Checking the Issues database is the best place to see what they are. If there was a magic wand it would have been used long ago to fix these problems, but there does not appear to be a magic fix. +Macs and PySimpleGUI did not play well together up until Nov 2019 and the release of ttk buttons. Prior to that buttons had to be white. Now the Mac can use any color for buttons and they work great. Images on buttons work as well. + +The problems were the normal tk.Button was not working correctly on the Mac. You couldn't set the button color. If you tried it appeared as if the text was missing. + +Users have recently reported the ability to install Python 3.7 from the Python.org website and not use the Homebrew version. This resolved all of the button color problems. + +Regardless of where you get your Python / tkinter, Macs can now enjoy using all of the look and feel color themes that Windows and Linux users are able to achieve. + +Many PySimpleGUI users have switched from PySimpleGUI to PySimpleGUIQt due to the button problems. IF you're one of them, ***you should consider switching back***. One reason to return to PySimpleGUI is that features tend to get iumplemented on PySimpleGUI (tkinger version) and then later on the other ports. There are a number of other reasons to give tkinter another try. -This was already mentioned at the top of this document but want to make sure it's covered as a "known issue" ## Multiple threads -While not an "issue" this is a ***stern warning*** +Consider this is a ***stern warning*** -## **Do not attempt** to call `PySimpleGUI` from multiple threads! It's `tkinter` based and `tkinter` has issues with multiple threads +### **Do not attempt** to call `PySimpleGUI` from multiple threads! At least the `tkinter` based port because tkinter is not threadsafe and has known issues with multiple threads Tkinter also wants to be the MAIN thread in your code. So, if you have to run multiple threads, make sure the GUI is the main thread. -Other than that, feel free to use threads with PySimpleGUI on all of the ports. You'll find a good example for how to run "long running tasks" in your event loop by looking at the demo program: `Demo_Multithreaded_Long_Tasks.py` +Other than that, feel free to use threads with PySimpleGUI on all of the ports. You'll find a good example for how to run "long running tasks" in your event loop by looking at the demo program: `Demo_Multithreaded_Long_Tasks.py`. There are several examples of using threads with PySimpleGUI. + +Be sure and **delete** your windows after you close them if you are running with multiple threads. There is a chance another thread's garbage collect will attempt to delete the window when not in the mainthread which will cause tkinter to crash. + +### The dreaded "Tcl_AsyncDelete: async handler deleted by the wrong thread" error + +This crash has plagued and mystified tkinter users for some time now. It happens when the user is running multiple threads in their application. Even if the user doesn't make any calls that are into tkinter, this problem can still cause your program to crash. + +I'm thrilled to say there's a solution and it's easy to implement. If you're getting this error, then here is what is causing it. + +When you close a window and delete the layout, the tkinter widgets that were in use in the window are no longer needed. Python marks them to be handled by the "Garbage Collector". They're deleted but not quite gone from memory. Then, later, while your thread is running, the Python Garbage Collect algorithm decides it's time to run garbage collect. When it tells tkinter to free up the memory, the tkinter code looks to see what context it is running under. It sees that it's a thread, not the main thread, and generates this exception. + +The way around this is actually quite easy. + +When you are finished with a window, be sure to: + +* Close the Window +* Set the `layout` variable to None +* Set the `window` variable to None +* Trigger Python's Garbage Collect to run immediately + +The sequence looks like this in code: + +```python + import gc + + # Do all your windows stuff... make a layout... show your window... then when time to exit + window.close() + layout = None + window = None + gc.collect() +``` + +This will ensure that the tkinter widgets are all deleted in the context of the mainthread and another thread won't accidently run the Garbage Collect + # Contributing -## Core Code +## Write Applications -***Core code changes/pull requests are not being accepted at this time.*** +The way for you to contribute to the PySimpleGUI is to create and share PySimpleGUI GUIs. **Everyone** learns from seeing other peoples' implementations. It's through user's creating applications that new problems and needs are discovered. These have had a profound and positive impact on the project and helped to create thw you see today. -## Demos +## Pull Requests + +***PySimpleGUI changes/pull requests are not being accepted at this time.*** -You're welcome to share a PySimpleGUI program you've written that you think fits the model of a PySimpleGUI Demo Program. ## GitHub Repos -If you've created a GitHub for your project that uses PySimpleGUI then please submit it to be included in this document or on the PySimpleGUI GitHub site. Also, you'll find a lot more people will look at your code, explore your repo if you have posted **screen shots in your readme**. People *love* success stories and showing your GUI's screen shows you've been successful. Everyone wins! +If you've created a GitHub for your project that uses PySimpleGUI then please post screenshots in in the "User's Screenshots" Issue on the PySimpleGUI GitHub. Say a little something about it and I'll also add it to the annoucements. People *love* success stories and showing your GUI's screen visually communicates your success. diff --git a/readme_creator/4_Release_notes.md b/readme_creator/4_Release_notes.md index add6c41a..ab329792 100644 --- a/readme_creator/4_Release_notes.md +++ b/readme_creator/4_Release_notes.md @@ -896,9 +896,158 @@ TTK WIDGETS! Welcome back Mac Users! * Test harness changes to help test new ttk stuff (want to shrink this window in the future so will fit on Trinket, Pi, etc +## 4.8.0 PySimpleGUI 4-Dec-2019 + +Multicolored multiline text! Often asked for feature going way back +ttk Buttons can have images +Print in color! + +* Multiline Element got 2 new parameters to the update method + * text_color_for_value - color for the newly added text + * background_color_for_value - background color of the newly added text +* New Print/EasyPrint parameters and capability + * text_color, background_color - control the text's color and background color when printing to "Debug Window" + * Must be done only when used in mode where stdout is not re-routed (the default) + * Wouldn't it be really nice if normal print calls had this parameter? + * Print(event, text_color='green', background_color='white', end='') +* ttk Buttons + * can have images. No longer forces Buttons with images to be the old tk Butons. Now you can choose either + * can update the button color + * can update the button image +* Set warning filter so that warnings are repeated +* New global variables: + * CURRENT_LOOK_AND_FEEL - The current look and feel setting in use. Starts out as "Default" + * BROWSE_FILES_DELIMITER - Defaults to ";" It is the string placed between entries returned from a FilesBrowse button + * TRANSPARENT_BUTTON - Depricated - was being used incorrectly as it was a relic from the early days. It's value was a color of gray +* Window - gentle reminder if you don't choose a look and feel for your window. It's easy to stop them. Add a change_look_and_feel line +* Test harness uses a debug window so don't be shocked when 2 windows appear when running PySimpleGUI by itself + * Prints the "Event" in Green on White text + * Prints the "values" normally + +## 4.9.0 PySimpleGUI 7-Dec-2019 + +The "Finally Nailed Tabs" release + +* Colors for Tabs! + * When creating TabGroup can now specify + * Text & Background color of all tabs + * Text & Background color of selected tab + * If nothing is specified then the Look and Feel theme will be used (which turned out GREAT) +* Tab visibility - Can finally control individual tab's visibility using update and when creating +* More "Look and Feel" Themes! There's no excuse to be grey again. There are now 126 themes to choose from. Here are the 32 new themes" + DefaultNoMoreNagging + DarkBlack1 + DarkBlue12 + DarkBlue13 + DarkBlue14 + DarkBlue15 + DarkBlue16 + DarkBlue17 + DarkBrown5 + DarkBrown6 + DarkGreen2 + DarkGreen3 + DarkGreen4 + DarkGreen5 + DarkGreen6 + DarkGrey4 + DarkGrey5 + DarkGrey6 + DarkGrey7 + DarkPurple6 + DarkRed2 + DarkTeal10 + DarkTeal11 + DarkTeal12 + DarkTeal9 + LightBlue6 + LightBlue7 + LightBrown12 + LightBrown13 + LightGray1 + LightGreen10 + LightGreen9 + LightGrey6 +* preview_all_look_and_feel_themes now has a columns parameter to control number of entries per rows + * also made each theme display smaller due to large number of themes + + +## 4.10.0 PySimpleGUI 9-Dec-2019 + +"Oh crap the debugger is broken!" + "Pretty Progress Bars" release + +* Fix for built-in debugger not working + * Important due to upcoming educational usage + * Has been broken since 4.5.0 when a change to Finalize was made +* ProgessBar element colors set using Look and Feel colors + * Combination of button color, input element, and input element text are used + + +## 4.11.0 PySimpleGUI 10-Dec-2019 + +The Element & Window bindings release + +* Element.bind - New method of all Elements + * Enables tkinter bindings to be added to any element + * Will get an event returned from window.read() if the tkinter event happens +* Window.bind - New method for Windows, just like Elements + * Enables tkinter bindings to be added to Windows + * Will get an event returned from window.read() if the tkinter event happens +* TabGroup fonts - can now set the font and font size for Tab text + + + +## 4.12.0 PySimpleGUI 14-Dec-2019 + +Finally no more outlines around TK Elements on Linux + +* Fixed a long-term problem of the mysterious white border around (almost) all TK Elements on Linux +* Ability to set the disabled button colors + * New Button and Button.update parameter - disabled_button_color + * Specified as (Text Color, Background Color) just like button colors + * For Normal / TK Buttons - can set button text color only + * For TTK Buttons - can set both a disabled button and text color + * Either parameter can be None to use current setting +* Removed use of CloseButton from Popups (still have a bug in the CloseButton code but not in popups now) +* Combobox - removed requirement of setting disabled if want to set to readonly using update method +* Fix for cancelling out of file/folder browse on Linux caused target to be cleared instead of just cancelling +* Removed try block around setting button colors - if user sets a bad color, well don't do that +* Now deleting windows after closing them for popup + + +## 4.13.0 PySimpleGUI 18-Dec-2019 + +Table and Tree header colors, expanded Graph methods + +* Element.expand new parameter - expand_row. If true then row will expand along with the widgets. Provides better resizing control +* Using math.floor now instead of an int cast in Graph Element's unit conversions +* Graph.draw_point - now using caller's graph units for specifying point size +* Graph.draw_circle - converted radius size from user's graph units. +* Graph.draw_circle - added line_width parameter +* Graph.draw_oval - added line_width parameter +* Graph.get_figures_at_location - new method for getting a list of figures at a particular point +* Graph.get_bounding_box - returns bounding box for a previously drawn figure +* Table and Tree Elements + * 3 new element creation parameters + * header_text_color - color of the text for the column headings + * header_background_color - color of the background of column headings + * header_font - font family, style , size for the column headings + * Defaults to using the current look and feel setting + * Uses similar algorithm as Tabs - Input Text background and text colors are used +* Spin element - fixed bug that showed "None" if default value is "None" +* Test Harness sets incorrect look and feel on purpose so a random one is chosen + + ### Upcoming -Make suggestions people! Future release features +There will always be overlapping work as the ports will never actually be "complete" as there's always something new that can be built. However there's a definition for the base functionality for PySimpleGUI. This is what is being strived for with the currnt ports that are underway. + +The current road ahead is to complete these ports - Qt (very close), Web (pretty close), Wx (not all that close). + +PySimpleGUIDroid is in the works.... + +In addition to the ports there is ongoing work with educators that want to bring PySimpleGUI into their classrooms. Some projects have already started with teachers. One effort is to examine a number of books that teach Python to kids and convert the exercises to use PySimpleGUI instead of tkinter or command line. Another educational effort is in integrating with Circuit Python. It's unclear exactly how PySimpleGUI will fit into the picture. A board from Adafruit is arriving soon which should help solidify what's possible. + ## Code Condition @@ -907,11 +1056,11 @@ Make suggestions people! Future release features Make it right Make it fast -It's a recipe for success if done right. PySimpleGUI has completed the "Make it run" phase. It's far from "right" in many ways. These are being worked on. The module is particularly poor for PEP 8 compliance. It was a learning exercise that turned into a somewhat complete GUI solution for lightweight problems. +It's a recipe for success if done right. PySimpleGUI has completed the "Make it run" phase. It's far from "right" in many ways. These are being worked on. The module has historically been particularly poor for PEP8 compliance. It was a learning exercise that turned into a somewhat complete GUI solution for lightweight problems. -While the internals to PySimpleGUI are a tad sketchy, the public interfaces into the SDK are more strictly defined and comply with PEP 8 for the most part. +While the internals to PySimpleGUI are a tad sketchy, the public interfaces into the SDK are more strictly defined and comply with PEP8 naming conventions. A set of "PEP8 Bindings" was released in summar 2019 to ensure the enternally facing interfaces all adhere to PEP8 names. -Please log bugs and suggestions in the GitHub! It will only make the code stronger and better in the end, a good thing for us all, right? +Please log bugs and suggestions **only on the PySimpleGUI GitHub**! It will only make the code stronger and better in the end, a good thing for us all, right? Logging them elsewhere doesn't enable the core developer and other PySimpleGUI users to help. To make matters worse, you may get bad advice from other sites because there are simply not many PySimpleGUI experts, yet. ## Design diff --git a/readme_creator/PySimpleGUIlib.py b/readme_creator/PySimpleGUIlib.py index 81c6a862..0e273781 100644 --- a/readme_creator/PySimpleGUIlib.py +++ b/readme_creator/PySimpleGUIlib.py @@ -1,6 +1,7 @@ #!/usr/bin/python3 -version = __version__ = "4.7.0 Released 26-Nov-2019 Welcome back Macs!" +version = __version__ = "4.13.1.3 Unreleased - Element.set_cursor, NEW theme(), Combo.update allows any value, table & tree header font defaults to window font, default theme now Dark Blue 3, Macs no longer default to colorless windows and buttons" + port = 'PySimpleGUI' # 888888ba .d88888b oo dP .88888. dP dP dP @@ -14,9 +15,6 @@ port = 'PySimpleGUI' # d8888P dP - - - # __ __ # / | / | # $$ | ______ ______ ______ $$ | @@ -32,7 +30,7 @@ port = 'PySimpleGUI' """ -Copyright 2018, 2019 PySimpleGUI.org +Copyright 2018, 2019, 2020 PySimpleGUI.org OK, let's get the bullshit out of the way @@ -47,7 +45,7 @@ This notice, these first 100 lines of code shall remain unchanged # # # # # # # # # # # # # # # # # # # # # # # # # # #### ##### # # # ###### ##### - + 888 .d8888b. 8888888b. 888 .d8888b. 888 d88P Y88b 888 Y88b 888 d88P Y88b @@ -57,7 +55,7 @@ This notice, these first 100 lines of code shall remain unchanged 888 888 888 888 888 888 888 888 888 Y88b d88P 888 888 Y88b d88P 88888888 "Y8888P88 888 88888888 "Y8888P" - + And just what is that? Well, it's LPGL3+ and these FOUR simple stipulations. 1. These and all comments are to remain in this document @@ -71,7 +69,7 @@ And just what is that? Well, it's LPGL3+ and these FOUR simple stipulations. 1. GitHub - (http://www.PySimpleGUI.com) currently pointing at: https://github.com/PySimpleGUI/PySimpleGUI 2. PyPI - pip install PySimpleGUI is the customary way of obtaining the latest release - + THE official documentation location is: Read the Docs (via http://www.PySimpleGUI.org). Currently is pointed at: https://pysimplegui.readthedocs.io/en/latest/ @@ -98,9 +96,9 @@ The User Manual and the Cookbook are both designed to paint some nice looking GU """ - # do the Python 2 or 3 check so the right tkinter stuff can get pulled in import sys + if sys.version_info[0] >= 3: import tkinter as tk from tkinter import filedialog @@ -108,7 +106,7 @@ if sys.version_info[0] >= 3: from tkinter import ttk import tkinter.scrolledtext as tkst import tkinter.font -else: # Do NOT remove any of these regardless of what your IDE or lint says. They are transformed in the 3 to 2 process +else: # Do NOT remove any of these regardless of what your IDE or lint says. They are transformed in the 3 to 2 process import Tkinter as tk import tkFileDialog import ttk @@ -116,7 +114,6 @@ else: # Do NOT remove any of these regardless of what your IDE or lint says. The import tkFont import ScrolledText - import datetime import time import pickle @@ -126,11 +123,15 @@ import inspect # from typing import List, Any, Union, Tuple, Dict # because this code has to run on 2.7 can't use real type hints. Must do typing only in comments from random import randint import warnings +from math import floor + +warnings.simplefilter('always', UserWarning) g_time_start = 0 g_time_end = 0 g_time_delta = 0 + # These timer routines are to help you quickly time portions of code. Please this TimerStart call at the point # you want to start timing and the TimerStop at the end point. As you can see, TimerStop prints the time delta in ms. def TimerStart(): @@ -214,13 +215,11 @@ NICE_BUTTON_COLORS = ((GREENS[3], TANS[0]), (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 = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default -OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) # Colors should never be this long +COLOR_SYSTEM_DEFAULT = '1234567890' # A Magic Number kind of signal to PySimpleGUI that the color should not be set at all +DEFAULT_BUTTON_COLOR = ('white', BLUES[0]) # Foreground, Background (None, None) == System Default +OFFICIAL_PYSIMPLEGUI_BUTTON_COLOR = ('white', BLUES[0]) + +CURRENT_LOOK_AND_FEEL = 'DarkBlue3' DEFAULT_ERROR_BUTTON_COLOR = ("#FFFFFF", "#FF0000") DEFAULT_BACKGROUND_COLOR = None @@ -242,7 +241,7 @@ DEFAULT_SCROLLBAR_COLOR = None # 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') +TRANSPARENT_BUTTON = 'This constant has been depricated. You must set your button background = background it is on for it to be transparent appearing' # -------------------------------------------------------------------------------- # Progress Bar Relief Choices RELIEF_RAISED = 'raised' @@ -266,8 +265,8 @@ THEME_LIST = ('default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnati DEFAULT_TTK_THEME = THEME_DEFAULT USE_TTK_BUTTONS = None - DEFAULT_PROGRESS_BAR_COLOR = (GREENS[0], '#D0D0D0') # a nice green progress bar +DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL = (GREENS[0], '#D0D0D0') # a nice green progress bar DEFAULT_PROGRESS_BAR_SIZE = (20, 20) # Size of Progress Bar (characters for length, pixels for width) DEFAULT_PROGRESS_BAR_BORDER_WIDTH = 1 DEFAULT_PROGRESS_BAR_RELIEF = RELIEF_GROOVE @@ -313,7 +312,6 @@ TEXT_LOCATION_BOTTOM_LEFT = tk.SW TEXT_LOCATION_BOTTOM_RIGHT = tk.SE TEXT_LOCATION_CENTER = tk.CENTER - # ----====----====----==== Constants the user should NOT f-with ====----====----====----# ThisRow = 555666777 # magic number @@ -331,6 +329,7 @@ MENU_KEY_SEPARATOR = '::' ENABLE_TK_WINDOWS = False + # ====================================================================== # # One-liner functions that are handy as f_ck # # ====================================================================== # @@ -363,6 +362,8 @@ BUTTON_TYPE_CALENDAR_CHOOSER = 30 BUTTON_TYPE_COLOR_CHOOSER = 40 BUTTON_TYPE_SHOW_DEBUGGER = 50 +BROWSE_FILES_DELIMITER = ';' # the delimeter to be used between each file in the returned string + # ------------------------- Element types ------------------------- # ELEM_TYPE_TEXT = 'text' @@ -416,6 +417,7 @@ class ToolTip: (inspired by https://stackoverflow.com/a/36221216) This is an INTERNALLY USED only class. Users should not refer to this class at all. """ + def __init__(self, widget, text, timeout=DEFAULT_TOOLTIP_TIME): """ @@ -483,7 +485,7 @@ class ToolTip: self.tipwindow.wm_attributes("-topmost", 1) label = ttk.Label(self.tipwindow, text=self.text, justify=tk.LEFT, - background=TOOLTIP_BACKGROUND_COLOR, relief=tk.SOLID, borderwidth=1) + background=TOOLTIP_BACKGROUND_COLOR, relief=tk.SOLID, borderwidth=1) label.pack() def hidetip(self): @@ -510,7 +512,9 @@ class Element(): The base class for all Elements. Holds the basic description of an Element like size and colors """ - def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None): + + def __init__(self, type, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, + visible=True, metadata=None): """ Element base class. Only used internally. User will not create an Element object by itself @@ -551,8 +555,10 @@ class Element(): self.TKRightClickMenu = None self.Widget = None # Set when creating window. Has the main tkinter widget for element self.Tearoff = False - self.ParentRowFrame = None # type tk.Frame - self.metadata = metadata # type: Any + self.ParentRowFrame = None # type tk.Frame + self.metadata = metadata # type: Any + self.user_bind_dict = {} # Used when user defines a tkinter binding using bind method - convert bind string to key modifier + self.user_bind_event = None # Used when user defines a tkinter binding using bind method - event data from tkinter def _RightClickMenuCallback(self, event): """ @@ -740,21 +746,49 @@ class Element(): if self.ParentForm.CurrentlyRunningMainloop: self.ParentForm.TKroot.quit() + def _user_bind_callback(self, bind_string, event): + """ + Used when user binds a tkinter event directly to an element + + :param bind_string: The event that was bound so can lookup the key modifier + :param event: Event data passed in by tkinter (not used) + """ + key_suffix = self.user_bind_dict.get(bind_string, '') + self.user_bind_event = event + if self.Key is not None: + if isinstance(self.Key, str): + self.ParentForm.LastButtonClicked = self.Key + str(key_suffix) + else: + self.ParentForm.LastButtonClicked = (self.Key, key_suffix) + else: + self.ParentForm.LastButtonClicked = bind_string + self.ParentForm.FormRemainedOpen = True + if self.ParentForm.CurrentlyRunningMainloop: + self.ParentForm.TKroot.quit() + + def bind(self, bind_string, key_modifier): + """ + Used to add tkinter events to an Element. + The tkinter specific data is in the Element's member variable user_bind_event + :param bind_string: The string tkinter expected in its bind function + :param key_modifier: Additional data to be added to the element's key when event is returned + """ + self.Widget.bind(bind_string, lambda evt: self._user_bind_callback(bind_string, evt)) + self.user_bind_dict[bind_string] = key_modifier + def ButtonReboundCallback(self, event): """ - Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal - callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button - callback function that is normally called. + *** DEPRICATED *** + Use Element.bind instead :param event: (unknown) Not used in this function. """ - # print(f'Button callback event = {obj_to_string_single_obj(event)}') + # print(f'Button callback event = {event}, {other}') try: self.ButtonCallBack() except: print('** ButtonReboundCallback - warning your element does not have a ButtonCallBack method **') - def SetTooltip(self, tooltip_text): """ Called by application to change the tooltip text for an Element. Normally invoked using the Element Object such as: window.Element('key').SetToolTip('New tip'). @@ -778,7 +812,6 @@ class Element(): except: print('Was unable to set focus. The Widget passed in was perhaps not present in this element? Check your elements .Widget property') - def set_size(self, size=(None, None)): """ Changes the size of an element to a specific size. @@ -797,7 +830,6 @@ class Element(): except: print('Warning, error setting height on element with key=', self.Key) - def get_size(self): """ Return the size of an element in Pixels. Care must be taken as some elements use characters to specify their size but will return pixels when calling this get_size method. @@ -809,8 +841,7 @@ class Element(): except: print('Warning, error getting size of element', self.Key) w = h = None - return w,h - + return w, h def hide_row(self): """ @@ -822,7 +853,6 @@ class Element(): except: print('Warning, error hiding element row for key =', self.Key) - def unhide_row(self): """ Unhides (makes visible again) the row container that the Element is located on. @@ -833,14 +863,14 @@ class Element(): except: print('Warning, error hiding element row for key =', self.Key) - def expand(self, expand_x=False, expand_y=False): + def expand(self, expand_x=False, expand_y=False, expand_row=True): """ Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions :param expand_x: (Bool) If True Element will expand in the Horizontal directions :param expand_y: (Bool) If True Element will expand in the Vertical directions + :param expand_row: (Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row """ - if expand_x and expand_y: fill = tk.BOTH elif expand_x: @@ -851,7 +881,19 @@ class Element(): return self.Widget.pack(expand=True, fill=fill) - self.ParentRowFrame.pack(expand=True, fill=fill) + self.ParentRowFrame.pack(expand=expand_row, fill=fill) + + + def set_cursor(self,cursor): + """ + Sets the cursor for the current Element. + :param cursor: (str) The tkinter cursor name + """ + try: + self.Widget.config(cursor=cursor) + except Exception as e: + print('Warning bad cursor specified ', cursor) + print(e) def __call__(self, *args, **kwargs): @@ -881,8 +923,9 @@ class InputText(Element): """ Display a single text input field. Based on the tkinter Widget `Entry` """ + def __init__(self, default_text='', size=(None, None), disabled=False, password_char='', - justification=None, background_color=None, text_color=None, font=None, tooltip=None, + justification=None, background_color=None, text_color=None, font=None, tooltip=None, change_submits=False, enable_events=False, do_not_clear=True, key=None, focus=False, pad=None, use_readonly_for_disable=True, right_click_menu=None, visible=True, metadata=None): @@ -919,11 +962,11 @@ class InputText(Element): self.ChangeSubmits = change_submits or enable_events self.RightClickMenu = right_click_menu self.UseReadonlyForDisable = use_readonly_for_disable - self.TKEntry = self.Widget = None # type: tk.Entry + self.TKEntry = self.Widget = None # type: tk.Entry super().__init__(ELEM_TYPE_INPUT_TEXT, size=size, background_color=bg, text_color=fg, key=key, pad=pad, font=font, tooltip=tooltip, visible=visible, metadata=metadata) - def Update(self, value=None, disabled=None, select=None, visible=None,text_color=None, background_color=None, move_cursor_to='end'): + def Update(self, value=None, disabled=None, select=None, visible=None, text_color=None, background_color=None, move_cursor_to='end'): """ Changes some of the settings for the Input Element. Must call `Window.Read` or `Window.Finalize` prior @@ -975,7 +1018,6 @@ class InputText(Element): text = '' return text - get = Get set_focus = Element.SetFocus set_tooltip = Element.SetTooltip @@ -995,6 +1037,7 @@ class Combo(Element): """ ComboBox Element - A combination of a single-line input and a drop-down menu. User can type in their own value or choose from list. """ + def __init__(self, values, default_value=None, size=(None, None), auto_size_text=None, background_color=None, text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, tooltip=None, readonly=False, font=None, visible=True, metadata=None): @@ -1019,7 +1062,7 @@ class Combo(Element): self.Values = values self.DefaultValue = default_value self.ChangeSubmits = change_submits or enable_events - self.Widget = self.TKCombo = None # type: ttk.Combobox + self.Widget = self.TKCombo = None # type: ttk.Combobox self.Disabled = disabled self.Readonly = readonly bg = background_color if background_color else DEFAULT_INPUT_ELEMENTS_COLOR @@ -1052,28 +1095,33 @@ class Combo(Element): 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 value not in self.Values: + self.TKCombo.set(value) + else: + 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 readonly: + self.Readonly = True + self.TKCombo['state'] = 'readonly' + elif readonly is False: + self.Readonly = False + self.TKCombo['state'] = 'enable' 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.TKCombo.configure(font=font) if visible is False: @@ -1090,11 +1138,11 @@ class Combo(Element): """ try: if self.TKCombo.current() == -1: # if the current value was not in the original list - value = self.TKCombo.get() # then get the value typed in by user + value = self.TKCombo.get() # then get the value typed in by user else: value = self.Values[self.TKCombo.current()] # get value from original list given index except: - value = None # only would happen if user closes window + value = None # only would happen if user closes window return value get = Get @@ -1102,12 +1150,14 @@ class Combo(Element): set_tooltip = Element.SetTooltip update = Update + # ------------------------- INPUT COMBO Element lazy functions ------------------------- # InputCombo = Combo DropDown = InputCombo Drop = InputCombo DD = Combo + # ---------------------------------------------------------------------- # # Option Menu # # ---------------------------------------------------------------------- # @@ -1118,6 +1168,7 @@ class OptionMenu(Element): choices, another little graphic is shown on the widget to indicate where you click. After clicking to activate, it looks like a Combo Box that you scroll to select a choice. """ + def __init__(self, values, default_value=None, size=(None, None), disabled=False, auto_size_text=None, background_color=None, text_color=None, key=None, pad=None, tooltip=None, visible=True, metadata=None): """ @@ -1192,6 +1243,7 @@ class OptionMenu(Element): # ------------------------- OPTION MENU Element lazy functions ------------------------- # InputOptionMenu = OptionMenu + # ---------------------------------------------------------------------- # # Listbox # # ---------------------------------------------------------------------- # @@ -1200,6 +1252,7 @@ class Listbox(Element): A List Box. Provide a list of values for the user to choose one or more of. Returns a list of selected rows when a window.Read() is executed. """ + def __init__(self, values, default_values=None, select_mode=None, change_submits=False, enable_events=False, bind_return_key=False, size=(None, None), disabled=False, auto_size_text=None, font=None, no_scrollbar=False, background_color=None, text_color=None, key=None, pad=None, tooltip=None, right_click_menu=None, @@ -1248,12 +1301,11 @@ class Listbox(Element): fg = text_color if text_color is not None else DEFAULT_INPUT_TEXT_COLOR self.RightClickMenu = right_click_menu self.vsb = None # type: tk.Scrollbar - self.TKListbox = self.Widget = None # type: tk.Listbox + self.TKListbox = self.Widget = None # type: tk.Listbox self.NoScrollbar = no_scrollbar super().__init__(ELEM_TYPE_INPUT_LISTBOX, size=size, auto_size_text=auto_size_text, font=font, background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, visible=visible, metadata=metadata) - def Update(self, values=None, disabled=None, set_to_index=None, scroll_to_index=None, visible=None): """ Changes some of the settings for the Listbox Element. Must call `Window.Read` or `Window.Finalize` prior @@ -1279,7 +1331,7 @@ class Listbox(Element): self.TKListbox.selection_set(0, 0) self.Values = values if set_to_index is not None: - self.TKListbox.selection_clear(0, len(self.Values)) # clear all listbox selections + self.TKListbox.selection_clear(0, len(self.Values)) # clear all listbox selections if type(set_to_index) in (tuple, list): for i in set_to_index: try: @@ -1300,8 +1352,7 @@ class Listbox(Element): if not self.NoScrollbar: self.vsb.pack() if scroll_to_index is not None and len(self.Values): - self.TKListbox.yview_moveto(scroll_to_index/len(self.Values)) - + self.TKListbox.yview_moveto(scroll_to_index / len(self.Values)) def SetValue(self, values): """ @@ -1320,7 +1371,6 @@ class Listbox(Element): pass self.DefaultValues = values - def GetListValues(self): # type: (Listbox) -> List[Any] """ @@ -1330,7 +1380,6 @@ class Listbox(Element): """ return self.Values - def GetIndexes(self): """ Returns the items currently selected as a list of indexes @@ -1339,7 +1388,6 @@ class Listbox(Element): """ return self.TKListbox.curselection() - get_indexes = GetIndexes get_list_values = GetListValues set_focus = Element.SetFocus @@ -1351,6 +1399,7 @@ class Listbox(Element): LBox = Listbox LB = Listbox + # ---------------------------------------------------------------------- # # Radio # # ---------------------------------------------------------------------- # @@ -1359,6 +1408,7 @@ class Radio(Element): Radio Button Element - Used in a group of other Radio Elements to provide user with ability to select only 1 choice in a list of choices. """ + def __init__(self, text, group_id, default=False, disabled=False, size=(None, None), auto_size_text=None, background_color=None, text_color=None, font=None, key=None, pad=None, tooltip=None, change_submits=False, enable_events=False, visible=True, metadata=None): @@ -1444,11 +1494,11 @@ class Radio(Element): set_tooltip = Element.SetTooltip update = Update + R = Radio Rad = Radio - # ---------------------------------------------------------------------- # # Checkbox # # ---------------------------------------------------------------------- # @@ -1456,6 +1506,7 @@ class Checkbox(Element): """ Checkbox Element - Displays a checkbox and text next to it """ + def __init__(self, text, default=False, size=(None, None), auto_size_text=None, font=None, background_color=None, text_color=None, change_submits=False, enable_events=False, disabled=False, key=None, pad=None, tooltip=None, visible=True, metadata=None): @@ -1480,7 +1531,7 @@ class Checkbox(Element): self.Text = text self.InitialState = default self.Value = None - self.TKCheckbutton = self.Widget = None # type: tk.Checkbutton + self.TKCheckbutton = self.Widget = None # type: tk.Checkbutton self.Disabled = disabled self.TextColor = text_color if text_color else DEFAULT_TEXT_COLOR self.ChangeSubmits = change_submits or enable_events @@ -1572,7 +1623,7 @@ class Spin(Element): self.Values = values self.DefaultValue = initial_value self.ChangeSubmits = change_submits or enable_events - self.TKSpinBox = self.Widget = None # type: tk.Spinbox + self.TKSpinBox = self.Widget = None # type: tk.Spinbox 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 @@ -1616,7 +1667,6 @@ class Spin(Element): elif visible is True: self.TKSpinBox.pack() - def _SpinChangedHandler(self, event): """ Callback function. Used internally only. Called by tkinter when Spinbox Widget changes. Results in Window.Read() call returning @@ -1648,7 +1698,6 @@ class Spin(Element): update = Update - # ---------------------------------------------------------------------- # # Multiline # # ---------------------------------------------------------------------- # @@ -1698,13 +1747,14 @@ class Multiline(Element): self.ChangeSubmits = change_submits or enable_events self.RightClickMenu = right_click_menu self.BorderWidth = border_width if border_width is not None else DEFAULT_BORDER_WIDTH - self.TKText = self.Widget = None # type: tkst.ScrolledText + self.TagCounter = 0 + self.TKText = self.Widget = None # type: tkst.ScrolledText super().__init__(ELEM_TYPE_INPUT_MULTILINE, size=size, auto_size_text=auto_size_text, background_color=bg, text_color=fg, key=key, pad=pad, tooltip=tooltip, font=font or DEFAULT_FONT, visible=visible, metadata=metadata) return - def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None, - visible=None, autoscroll=None): + def Update(self, value=None, disabled=None, append=False, font=None, text_color=None, background_color=None, text_color_for_value=None, + background_color_for_value=None, visible=None, autoscroll=None): """ Changes some of the settings for the Multiline Element. Must call `Window.Read` or `Window.Finalize` prior @@ -1717,19 +1767,28 @@ class Multiline(Element): :param visible: (bool) set visibility state of the element :param autoscroll: (bool) if True then contents of element are scrolled down when new text is added to the end """ - + value = str(value) if self.Widget is None: warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning) return if autoscroll is not None: self.Autoscroll = autoscroll + # Multicolored text + if text_color_for_value is not None: + self.TKText.tag_configure(str(self.TagCounter), foreground=text_color_for_value) + if background_color_for_value is not None: + self.TKText.tag_configure(str(self.TagCounter), background=background_color_for_value) + if value is not None: if self.Disabled: self.TKText.configure(state='normal') try: if not append: self.TKText.delete('1.0', tk.END) - self.TKText.insert(tk.END, value) + if text_color_for_value is not None or background_color_for_value is not None: + self.TKText.insert(tk.END, value, str(self.TagCounter)) + else: + self.TKText.insert(tk.END, value) except: pass if self.Disabled: @@ -1751,6 +1810,7 @@ class Multiline(Element): self.TKText.pack_forget() elif visible is True: self.TKText.pack() + self.TagCounter += 1 # doesn't matter if the counter is bumped every call def Get(self): """ @@ -1761,7 +1821,6 @@ class Multiline(Element): return self.TKText.get(1.0, tk.END) - get = Get set_focus = Element.SetFocus set_tooltip = Element.SetTooltip @@ -1779,8 +1838,10 @@ class Text(Element): """ Text - Display some text in the window. Usually this means a single line of text. However, the text can also be multiple lines. If multi-lined there are no scroll bars. """ + def __init__(self, text='', size=(None, None), auto_size_text=None, click_submits=False, enable_events=False, - relief=None, font=None, text_color=None, background_color=None, border_width=None, justification=None, pad=None, key=None, right_click_menu=None, tooltip=None, visible=True, metadata=None): + relief=None, font=None, text_color=None, background_color=None, border_width=None, justification=None, pad=None, key=None, + right_click_menu=None, tooltip=None, visible=True, metadata=None): """ :param text: (str) The text to display. Can include /n to achieve multiple lines :param size: Tuple[int, int] (width, height) width = characters-wide, height = rows-high @@ -1817,7 +1878,6 @@ class Text(Element): super().__init__(ELEM_TYPE_TEXT, size, auto_size_text, background_color=bg, font=font if font else DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) - def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): """ Changes some of the settings for the Text Element. Must call `Window.Read` or `Window.Finalize` prior @@ -1852,11 +1912,10 @@ class Text(Element): update = Update - # ------------------------- Text Element lazy functions ------------------------- # Txt = Text # type: Text -T = Text # type: Text +T = Text # type: Text # ---------------------------------------------------------------------- # @@ -1866,6 +1925,7 @@ class StatusBar(Element): """ A StatusBar Element creates the sunken text-filled strip at the bottom. Many Windows programs have this line """ + def __init__(self, text, size=(None, None), auto_size_text=None, click_submits=None, enable_events=False, relief=RELIEF_SUNKEN, font=None, text_color=None, background_color=None, justification=None, pad=None, key=None, tooltip=None, visible=True, metadata=None): @@ -1897,13 +1957,12 @@ class StatusBar(Element): bg = DEFAULT_TEXT_ELEMENT_BACKGROUND_COLOR else: bg = background_color - self.TKText = self.Widget = None # type: tk.Label + self.TKText = self.Widget = None # type: tk.Label super().__init__(ELEM_TYPE_STATUSBAR, size=size, auto_size_text=auto_size_text, background_color=bg, font=font or DEFAULT_FONT, text_color=self.TextColor, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return - def Update(self, value=None, background_color=None, text_color=None, font=None, visible=None): """ Changes some of the settings for the Status Bar Element. Must call `Window.Read` or `Window.Finalize` prior @@ -1937,7 +1996,6 @@ class StatusBar(Element): update = Update - # ---------------------------------------------------------------------- # # TKProgressBar # # Emulate the TK ProgressBar using canvas and rectangles @@ -1945,6 +2003,7 @@ class StatusBar(Element): class TKProgressBar(): """ """ + def __init__(self, root, max, length=400, width=DEFAULT_PROGRESS_BAR_SIZE[1], style=DEFAULT_TTK_THEME, relief=DEFAULT_PROGRESS_BAR_RELIEF, border_width=DEFAULT_PROGRESS_BAR_BORDER_WIDTH, orientation='horizontal', BarColor=(None, None), key=None): @@ -2029,6 +2088,7 @@ class TKOutput(tk.Frame): Note - This is NOT a user controlled class. Users should NOT be directly using it unless making an extention to PySimpleGUI by directly manipulating tkinter. """ + def __init__(self, parent, width, height, bd, background_color=None, text_color=None, font=None, pad=None): """ :param parent: Union[tk.Tk, tk.Toplevel] The "Root" that the Widget will be in @@ -2102,6 +2162,7 @@ class Output(Element): """ Output Element - a multi-lined text area where stdout and stderr are re-routed to. """ + def __init__(self, size=(None, None), background_color=None, text_color=None, pad=None, font=None, tooltip=None, key=None, right_click_menu=None, visible=True, metadata=None): """ @@ -2117,7 +2178,7 @@ class Output(Element): :param metadata: (Any) User metadata that can be set to ANYTHING """ - self._TKOut = self.Widget = None # type: TKOutput + self._TKOut = self.Widget = None # type: TKOutput 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 self.RightClickMenu = right_click_menu @@ -2158,7 +2219,6 @@ class Output(Element): """ return self._TKOut.output.get(1.0, tk.END) - def expand(self, expand_x=False, expand_y=False): """ Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions @@ -2180,8 +2240,6 @@ class Output(Element): self._TKOut.frame.pack(expand=True, fill=fill) self.ParentRowFrame.pack(expand=True, fill=fill) - - set_focus = Element.SetFocus set_tooltip = Element.SetTooltip tk_out = TKOut @@ -2195,10 +2253,12 @@ class Button(Element): """ Button Element - Defines all possible buttons. The shortcuts such as Submit, FileBrowse, ... each create a Button """ + 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, enable_events=False, image_filename=None, image_data=None, image_size=(None, None), - image_subsample=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, use_ttk_buttons=None, + image_subsample=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, disabled_button_color=None, + use_ttk_buttons=None, font=None, bind_return_key=False, focus=False, pad=None, key=None, visible=True, metadata=None): """ :param button_text: (str) Text to be displayed on the button @@ -2218,6 +2278,7 @@ class Button(Element): :param size: Tuple[int, int] (width, height) of the button in characters wide, rows high :param auto_size_button: (bool) if True the button size is sized to fit the text :param button_color: Tuple[str, str] (text color, background color) of button. Easy to remember which is which if you say "ON" between colors. "red" on "green". + :param disabled_button_color: Tuple[str, str] colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color :param use_ttk_buttons: (bool) True = use ttk buttons. False = do not use ttk buttons. None (Default) = use ttk buttons only if on a Mac and not with button images :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc :param bind_return_key: (bool) If True the return key will cause this button to be pressed @@ -2235,6 +2296,7 @@ class Button(Element): self.Target = target self.ButtonText = str(button_text) self.ButtonColor = button_color if button_color != None else DEFAULT_BUTTON_COLOR + self.DisabledButtonColor = disabled_button_color if disabled_button_color is not None else (None, None) self.ImageFilename = image_filename self.ImageData = image_data self.ImageSize = image_size @@ -2252,8 +2314,8 @@ class Button(Element): self.UseTtkButtons = use_ttk_buttons if sys.platform.startswith('darwin'): self.UseTtkButtons = True - if image_filename or image_data: - self.UseTtkButtons = False # if an image is to be displayed, then force the button to not be a TTK Button + # if image_filename or image_data: + # self.UseTtkButtons = False # if an image is to be displayed, then force the button to not be a TTK Button super().__init__(ELEM_TYPE_BUTTON, size=size, font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return @@ -2293,7 +2355,7 @@ class Button(Element): # print('Button callback') - # print(f'Parent = {self.ParentForm} Position = {self.Position}') + # print(f'Button Callback - 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 @@ -2325,7 +2387,7 @@ class Button(Element): 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, parent=self.ParentForm.TKroot) # show the 'get folder' dialog box - if folder_name != '': + if folder_name: try: strvar.set(folder_name) self.TKStringVar.set(folder_name) @@ -2338,7 +2400,7 @@ class Button(Element): else: file_name = tk.filedialog.askopenfilename(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get file' dialog box - if file_name != '': + if file_name: strvar.set(file_name) self.TKStringVar.set(file_name) elif self.BType == BUTTON_TYPE_COLOR_CHOOSER: @@ -2351,8 +2413,8 @@ class Button(Element): file_name = tk.filedialog.askopenfilenames(initialdir=self.InitialFolder) else: file_name = tk.filedialog.askopenfilenames(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) - if file_name != '': - file_name = ';'.join(file_name) + if file_name: + file_name = BROWSE_FILES_DELIMITER.join(file_name) # normally a ';' strvar.set(file_name) self.TKStringVar.set(file_name) elif self.BType == BUTTON_TYPE_SAVEAS_FILE: @@ -2362,7 +2424,7 @@ class Button(Element): else: file_name = tk.filedialog.asksaveasfilename(filetypes=filetypes, initialdir=self.InitialFolder, parent=self.ParentForm.TKroot) # show the 'get file' dialog box - if file_name != '': + 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 @@ -2427,7 +2489,7 @@ class Button(Element): return def Update(self, text=None, button_color=(None, None), disabled=None, image_data=None, image_filename=None, - visible=None, image_subsample=None, image_size=None): + visible=None, image_subsample=None, disabled_button_color=(None, None), image_size=None): """ Changes some of the settings for the Button Element. Must call `Window.Read` or `Window.Finalize` prior @@ -2436,6 +2498,7 @@ class Button(Element): :param disabled: (bool) disable or enable state of the element :param image_data: Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data :param image_filename: (str) image filename if there is a button image. GIFs and PNGs only. + :param disabled_button_color: Tuple[str, str] colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color :param visible: (bool) control visibility of element :param image_subsample: (int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc :param image_size: Tuple[int, int] Size of the image in pixels (width, height) @@ -2444,17 +2507,25 @@ class Button(Element): if self.Widget is None: warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning) return - try: - if text is not None: - self.TKButton.configure(text=text) - self.ButtonText = text - if sys.platform == 'darwin' and button_color != (None, None): - print('Button.Update *** WARNING - Button colors are not supported on the Mac***') - if button_color != (None, None): - self.TKButton.config(foreground=button_color[0], background=button_color[1], activebackground=button_color[1]) - self.ButtonColor = button_color - except: - return + if self.UseTtkButtons: + style_name = str(self.Key) + 'custombutton.TButton' + button_style = ttk.Style() + if text is not None: + self.TKButton.configure(text=text) + self.ButtonText = text + if button_color != (None, None): + if self.UseTtkButtons: + if button_color[0] is not None: + button_style.configure(style_name, foreground=button_color[0]) + if button_color[1]: + button_style.configure(style_name, background=button_color[1]) + else: + if button_color[0]: + self.TKButton.config(foreground=button_color[0]) + if button_color[1]: + self.TKButton.config(background=button_color[1], activebackground=button_color[1]) + self.ButtonColor = (button_color[0] if button_color[0] is not None else self.ButtonColor[0], + button_color[1] if button_color[1] is not None else self.ButtonColor[1]) if disabled == True: self.TKButton['state'] = 'disabled' elif disabled == False: @@ -2467,10 +2538,12 @@ class Button(Element): width, height = image.width(), image.height() if image_subsample: image = image.subsample(image_subsample) - self.TKButton.config(image=image, width=width, height=height) + if self.UseTtkButtons: + button_style.configure(style_name, image=image, width=width, height=height) + else: + self.TKButton.config(image=image, width=width, height=height) self.TKButton.image = image if image_filename is not None: - self.TKButton.config(highlightthickness=0) image = tk.PhotoImage(file=image_filename) if image_size is not None: width, height = image_size @@ -2478,12 +2551,25 @@ class Button(Element): width, height = image.width(), image.height() if image_subsample: image = image.subsample(image_subsample) - self.TKButton.config(image=image, width=width, height=height) + if self.UseTtkButtons: + button_style.configure(style_name, image=image, width=width, height=height) + else: + self.TKButton.config(highlightthickness=0, image=image, width=width, height=height) self.TKButton.image = image if visible is False: self.TKButton.pack_forget() elif visible is True: self.TKButton.pack() + if disabled_button_color != (None, None): + if not self.UseTtkButtons: + self.TKButton['disabledforeground'] = disabled_button_color[0] + else: + if disabled_button_color[0] is not None: + button_style.map(style_name, foreground=[('disabled', disabled_button_color[0])]) + if disabled_button_color[1] is not None: + button_style.map(style_name, background=[('disabled', disabled_button_color[1])]) + self.DisabledButtonColor = (disabled_button_color[0] if disabled_button_color[0] is not None else self.DisabledButtonColor[0], + disabled_button_color[1] if disabled_button_color[1] is not None else self.DisabledButtonColor[1]) def GetText(self): """ @@ -2493,7 +2579,6 @@ class Button(Element): """ return self.ButtonText - def Click(self): """ Generates a click of the button as if the user clicked the button @@ -2504,7 +2589,6 @@ class Button(Element): except: print('Exception clicking button') - click = Click get_text = GetText set_focus = Element.SetFocus @@ -2565,8 +2649,8 @@ class ButtonMenu(Element): self.IsButtonMenu = True self.MenuItemChosen = None self.Tearoff = tearoff - self.TKButtonMenu = None # type: tk.Menubutton - self.TKMenu = None # type: tk.Menu + self.TKButtonMenu = None # type: tk.Menubutton + self.TKMenu = None # type: tk.Menu # self.temp_size = size if size != (NONE, NONE) else super().__init__(ELEM_TYPE_BUTTONMENU, size=size, font=font, pad=pad, key=key, tooltip=tooltip, @@ -2586,7 +2670,6 @@ class ButtonMenu(Element): if self.ParentForm.CurrentlyRunningMainloop: self.ParentForm.TKroot.quit() # kick the users out of the mainloop - def Update(self, menu_definition, visible=None): """ Changes some of the settings for the ButtonMenu Element. Must call `Window.Read` or `Window.Finalize` prior @@ -2618,11 +2701,11 @@ class ButtonMenu(Element): except: print('Exception clicking button') - set_focus = Element.SetFocus set_tooltip = Element.SetTooltip update = Update + BMenu = ButtonMenu @@ -2633,7 +2716,9 @@ class ProgressBar(Element): """ Progress Bar Element - Displays a colored bar that is shaded as progress of some operation is made """ - def __init__(self, max_value, orientation=None, size=(None, None), auto_size_text=None, bar_color=(None, None), style=None, border_width=None, relief=None, key=None, pad=None, visible=True, metadata=None): + + def __init__(self, max_value, orientation=None, size=(None, None), auto_size_text=None, bar_color=(None, None), style=None, border_width=None, relief=None, + key=None, pad=None, visible=True, metadata=None): """ :param max_value: (int) max value of progressbar :param orientation: (str) 'horizontal' or 'vertical' @@ -2650,7 +2735,7 @@ class ProgressBar(Element): """ self.MaxValue = max_value - self.TKProgressBar = None # type: TKProgressBar + self.TKProgressBar = None # type: TKProgressBar self.Cancelled = False self.NotRunning = True self.Orientation = orientation if orientation else DEFAULT_METER_ORIENTATION @@ -2682,7 +2767,6 @@ class ProgressBar(Element): return False return True - def Update(self, visible=None): """ Changes some of the settings for the ProgressBar Element. Must call `Window.Read` or `Window.Finalize` prior @@ -2702,11 +2786,11 @@ class ProgressBar(Element): update = Update update_bar = UpdateBar + PBar = ProgressBar Prog = ProgressBar - # ---------------------------------------------------------------------- # # Image # # ---------------------------------------------------------------------- # @@ -2969,7 +3053,7 @@ class Graph(Element): if self.FloatValues: return new_x, new_y else: - return int(new_x), int(new_y) + return floor(new_x), floor(new_y) def DrawLine(self, point_from, point_to, color='black', width=1): """ @@ -3008,6 +3092,8 @@ class Graph(Element): if point == (None, None): return converted_point = self._convert_xy_to_canvas_xy(point[0], point[1]) + size_converted = self._convert_xy_to_canvas_xy(point[0]+size, point[1]) + size = size_converted[0]-converted_point[0] 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') @@ -3020,7 +3106,7 @@ class Graph(Element): id = None return id - def DrawCircle(self, center_location, radius, fill_color=None, line_color='black'): + def DrawCircle(self, center_location, radius, fill_color=None, line_color='black', line_width=1): """ Draws a circle, cenetered at the location provided. Can set the fill and outline colors @@ -3028,24 +3114,31 @@ class Graph(Element): :param radius: Union[int, float] Radius in user's coordinate values. :param fill_color: (str) color of the point to draw :param line_color: (str) color of the outer line that goes around the circle (sorry, can't set thickness) + :param line_width: (int) width of the line around the circle, the outline, in pixels :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the circle """ if center_location == (None, None): return converted_point = self._convert_xy_to_canvas_xy(center_location[0], center_location[1]) + radius_converted = self._convert_xy_to_canvas_xy(center_location[0]+radius, center_location[1]) + radius = radius_converted[0]-converted_point[0] + # radius = radius_converted[1]-5 + # print(f'center = {converted_point} radius converted = {radius_converted}') 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 + # print('Oval parms', int(converted_point[0]) - int(radius), int(converted_point[1]) - int(radius), + # int(converted_point[0]) + int(radius), int(converted_point[1]) + int(radius)) try: # needed in case the window was closed with an X - id = 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) + id = self._TKCanvas2.create_oval(int(converted_point[0]) - int(radius), int(converted_point[1]) - int(radius), + int(converted_point[0]) + int(radius), int(converted_point[1]) + int(radius), fill=fill_color, + outline=line_color, width=line_width) except: id = None return id - def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None): + def DrawOval(self, top_left, bottom_right, fill_color=None, line_color=None, line_width=1): """ Draws an oval based on coordinates in user coordinate system. Provide the location of a "bounding rectangle" @@ -3053,6 +3146,7 @@ class Graph(Element): :param bottom_right: Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle :param fill_color: (str) color of the interrior :param line_color: (str) color of outline of oval + :param line_width: (int) width of the line around the oval, the outline, in pixels :return: Union[int, None] id returned from tkinter that you'll need if you want to manipulate the oval """ converted_top_left = self._convert_xy_to_canvas_xy(top_left[0], top_left[1]) @@ -3063,7 +3157,7 @@ class Graph(Element): return None try: # in case windows close with X id = 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) + converted_bottom_right[1], fill=fill_color, outline=line_color, width=line_width ) except: id = None @@ -3183,7 +3277,6 @@ class Graph(Element): id = None return id - def Erase(self): """ Erase the Graph - Removes all figures previously "drawn" using the Graph methods (e.g. DrawText) @@ -3198,7 +3291,6 @@ class Graph(Element): except: pass - def DeleteFigure(self, id): """ Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive @@ -3210,9 +3302,9 @@ class Graph(Element): except: print('DeleteFigure - bad ID {}'.format(id)) try: - del self.Images[id] # in case was an image. If wasn't an image, then will get exception - except: pass - + del self.Images[id] # in case was an image. If wasn't an image, then will get exception + except: + pass def Update(self, background_color=None, visible=None): """ @@ -3232,7 +3324,6 @@ class Graph(Element): elif visible is True: self._TKCanvas2.pack() - def Move(self, x_direction, y_direction): """ Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system @@ -3249,7 +3340,6 @@ class Graph(Element): return None self._TKCanvas2.move('all', shift_amount[0], shift_amount[1]) - def MoveFigure(self, figure, x_direction, y_direction): """ Moves a previously drawn figure using a "delta" from current position @@ -3287,15 +3377,13 @@ class Graph(Element): xy = self._TKCanvas2.coords(figure) self._TKCanvas2.move(figure, shift_converted[0] - xy[0], shift_converted[1] - xy[1]) - def SendFigureToBack(self, figure): """ Changes Z-order of figures on the Graph. Sends the indicated figure to the back of all other drawn figures :param figure: (int) value returned by tkinter when creating the figure / drawing """ - self.TKCanvas.tag_lower(figure) # move figure to the "bottom" of all other figure - + self.TKCanvas.tag_lower(figure) # move figure to the "bottom" of all other figure def BringFigureToFront(self, figure): """ @@ -3303,9 +3391,31 @@ class Graph(Element): :param figure: (int) value returned by tkinter when creating the figure / drawing """ - self.TKCanvas.tag_raise(figure) # move figure to the "top" of all other figures + self.TKCanvas.tag_raise(figure) # move figure to the "top" of all other figures + def GetFiguresAtLocation(self, location): + """ + Returns a list of figures located at a particular x,y location within the Graph + + :param location: Union[Tuple[int, int], Tuple[float, float]] point to check + :return: List[int] a list of previously drawn "Figures" (returned from the drawing primitives) + """ + x, y = self._convert_xy_to_canvas_xy(location[0], location[1]) + ids = self.TKCanvas.find_overlapping(x,y,x,y) + return ids + + def GetBoundingBox(self, figure): + """ + Given a figure, returns the upper left and lower right bounding box coordinates + + :param figure: a previously drawing figure + :return: Union[Tuple[int, int, int, int], Tuple[float, float, float, float]] (upper left x, upper left y, lower right x, lower right y + """ + box = self.TKCanvas.bbox(figure) + top_left = self._convert_canvas_xy_to_xy(box[0], box[1]) + bottom_right = self._convert_canvas_xy_to_xy(box[2], box[3]) + return top_left,bottom_right @property def TKCanvas(self): @@ -3322,7 +3432,7 @@ class Graph(Element): :param event: (event) event info from tkinter. Note not used in this method """ - if not self.DragSubmits: # only report mouse up for drag operations + if not self.DragSubmits: # only report mouse up for drag operations return self.ClickPosition = self._convert_canvas_xy_to_xy(event.x, event.y) self.LastButtonClickedWasRealtime = not self.DragSubmits @@ -3385,6 +3495,8 @@ class Graph(Element): draw_point = DrawPoint draw_rectangle = DrawRectangle draw_text = DrawText + get_figures_at_location = GetFiguresAtLocation + get_bounding_box = GetBoundingBox erase = Erase motion_call_back = MotionCallBack move = Move @@ -3397,7 +3509,6 @@ class Graph(Element): update = Update - # ---------------------------------------------------------------------- # # Frame # # ---------------------------------------------------------------------- # @@ -3513,7 +3624,6 @@ class Frame(Element): if value is not None: self.TKFrame.config(text=str(value)) - add_row = AddRow layout = Layout set_focus = Element.SetFocus @@ -3542,9 +3652,11 @@ class VerticalSeparator(Element): set_focus = Element.SetFocus set_tooltip = Element.SetTooltip + VSeperator = VerticalSeparator VSep = VerticalSeparator + # ---------------------------------------------------------------------- # # Tab # # ---------------------------------------------------------------------- # @@ -3638,15 +3750,18 @@ class Tab(Element): if self.Widget is None: warnings.warn('You cannot Update element with key = {} until the window has been Read or Finalized'.format(self.Key), UserWarning) return - if disabled is None: - return - self.Disabled = disabled - state = 'disabled' if disabled is True else 'normal' - self.ParentNotebook.tab(self.TabID, state=state) + state = 'normal' + if disabled is not None: + self.Disabled = disabled + if disabled: + state = 'disabled' if visible is False: - self.ParentNotebook.pack_forget() - elif visible is True: - self.ParentNotebook.pack() + state = 'hidden' + self.ParentNotebook.tab(self.TabID, state=state) + # if visible is False: + # self.ParentNotebook.pack_forget() + # elif visible is True: + # self.ParentNotebook.pack() return self def _GetElementAtLocation(self, location): @@ -3662,7 +3777,6 @@ class Tab(Element): element = row[col_num] return element - def Select(self): """ Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first! @@ -3681,6 +3795,7 @@ class Tab(Element): set_tooltip = Element.SetTooltip update = Update + # ---------------------------------------------------------------------- # # TabGroup # # ---------------------------------------------------------------------- # @@ -3689,15 +3804,18 @@ class TabGroup(Element): TabGroup Element groups together your tabs into the group of tabs you see displayed in your window """ - def __init__(self, layout, tab_location=None, title_color=None, selected_title_color=None, background_color=None, + def __init__(self, layout, tab_location=None, title_color=None, tab_background_color=None, selected_title_color=None, selected_background_color=None, + background_color=None, font=None, change_submits=False, enable_events=False, pad=None, border_width=None, theme=None, key=None, tooltip=None, visible=True, metadata=None): """ :param layout: List[List[Tab]] Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row :param tab_location: (str) location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright :param title_color: (str) color of text on tabs - :param selected_title_color: (str) color of tab when it is selected - :param background_color: (str) color of background of tabs + :param tab_background_color: (str) color of all tabs that are not selected + :param selected_title_color: (str) color of tab text when it is selected + :param selected_background_color: (str) color of tab when it is selected + :param background_color: (str) color of background area that tabs are located on :param font: Union[str, Tuple[str, int]] specifies the font family, size, etc :param change_submits: (bool) * DEPRICATED DO NOT USE! Same as enable_events :param enable_events: (bool) If True then switching tabs will generate an Event @@ -3716,10 +3834,14 @@ class TabGroup(Element): self.ReturnValuesDictionary = {} self.DictionaryKeyCounter = 0 self.ParentWindow = None - self.SelectedTitleColor = selected_title_color + self.SelectedTitleColor = selected_title_color if selected_title_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT'] + self.SelectedBackgroundColor = selected_background_color if selected_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL][ + 'BACKGROUND'] + title_color = title_color if title_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT'] + self.TabBackgroundColor = tab_background_color if tab_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT'] self.Rows = [] - self.TKNotebook = None # type: ttk.Notebook - self.Widget = None # type: ttk.Notebook + self.TKNotebook = None # type: ttk.Notebook + self.Widget = None # type: ttk.Notebook self.TabCount = 0 self.BorderWidth = border_width self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR @@ -3790,7 +3912,6 @@ class TabGroup(Element): return element.Key return None - def Get(self): """ Returns the current value for the Tab Group, which will be the currently selected tab's KEY or the text on @@ -3818,7 +3939,6 @@ class TabGroup(Element): set_tooltip = Element.SetTooltip - # ---------------------------------------------------------------------- # # Slider # # ---------------------------------------------------------------------- # @@ -3911,8 +4031,6 @@ class Slider(Element): if range != (None, None): self.TKScale.config(from_=range[0], to_=range[1]) - - def _SliderChangedHandler(self, event): """ Not user callable. Callback function for when slider is moved. @@ -3940,6 +4058,7 @@ class TkFixedFrame(tk.Frame): """ A tkinter frame that is used with Column Elements that do not have a scrollbar """ + def __init__(self, master, **kwargs): """ :param master: (tk.Widget) The parent widget @@ -3970,6 +4089,7 @@ class TkScrollableFrame(tk.Frame): """ A frame with one or two scrollbars. Used to make Columns with scrollbars """ + def __init__(self, master, vertical_only, **kwargs): """ @@ -4014,16 +4134,13 @@ class TkScrollableFrame(tk.Frame): self.bind('', self.set_scrollregion) - self.canvas.bind("", self.yscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! - self.canvas.bind("", self.xscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! - - + self.canvas.bind("", self.yscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! + self.canvas.bind("", self.xscroll) # THIS IS IT! The line of code that enables the column to be scrolled with the mouse! # def _on_mousewheel(self, event): # self.canv.yview_scroll(int(-1 * (event.delta / 120)), "units") - - # self.bind_mouse_scroll(self.canvas, self.yscroll) + # self.bind_mouse_scroll(self.canvas, self.yscroll) # if not vertical_only: # self.bind_mouse_scroll(self.hscrollbar, self.xscroll) # self.bind_mouse_scroll(self.vscrollbar, self.yscroll) @@ -4162,7 +4279,6 @@ class Column(Element): self.AddRow(*row) return self - def _GetElementAtLocation(self, location): """ Not user callable. Used to find the Element at a row, col position within the layout @@ -4176,7 +4292,6 @@ class Column(Element): element = row[col_num] return element - def Update(self, visible=None): """ Changes some of the settings for the Column Element. Must call `Window.Read` or `Window.Finalize` prior @@ -4203,8 +4318,10 @@ class Column(Element): set_tooltip = Element.SetTooltip update = Update + Col = Column + # ---------------------------------------------------------------------- # # Pane # # ---------------------------------------------------------------------- # @@ -4584,7 +4701,7 @@ class Menu(Element): self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.MenuDefinition = menu_definition - self.Widget = self.TKMenu = None # type: tk.Menu + self.Widget = self.TKMenu = None # type: tk.Menu self.Tearoff = tearoff self.MenuItemChosen = None @@ -4637,7 +4754,7 @@ class Menu(Element): AddMenuItem(baritem, menu_entry[1], self) if visible == False: - self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear + self.ParentForm.TKroot.configure(menu=[]) # this will cause the menubar to disappear elif self.TKMenu is not None: self.ParentForm.TKroot.configure(menu=self.TKMenu) @@ -4658,7 +4775,7 @@ 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, row_height=None, font=None, justification='right', text_color=None, background_color=None, - alternating_row_color=None, row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, + alternating_row_color=None, header_text_color=None, header_background_color=None, header_font=None, row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, size=(None, None), change_submits=False, enable_events=False, bind_return_key=False, pad=None, key=None, tooltip=None, right_click_menu=None, visible=True, metadata=None): """ @@ -4681,7 +4798,10 @@ class Table(Element): :param text_color: (str) color of the text :param background_color: (str) color of background :param alternating_row_color: (str) if set then every other row will have this color in the background. - :param row_colors: + :param header_text_color: (str) sets the text color for the header + :param header_background_color: (str) sets the background color for the header + :param header_font: Union[str, Tuple[str, int]] specifies the font family, size, etc + :param row_colors: List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Sets the colors of listed rows to the color(s) provided (note the optional foreground color) :param vertical_scroll_only: (bool) if True only the vertical scrollbar will be visible :param hide_vertical_scroll: (bool) if True vertical scrollbar will be hidden :param size: Tuple[int, int] DO NOT USE! Use num_rows instead @@ -4705,13 +4825,16 @@ class Table(Element): self.AutoSizeColumns = auto_size_columns self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.TextColor = text_color + self.HeaderTextColor = header_text_color if header_text_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT'] + self.HeaderBackgroundColor = header_background_color if header_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT'] + self.HeaderFont = header_font 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.RowHeight = row_height - self.Widget = self.TKTreeview = None # type: ttk.Treeview + self.Widget = self.TKTreeview = None # type: ttk.Treeview self.AlternatingRowColor = alternating_row_color self.VerticalScrollOnly = vertical_scroll_only self.HideVerticalScroll = hide_vertical_scroll @@ -4722,7 +4845,7 @@ class Table(Element): self.RowHeaderText = 'Row' self.RightClickMenu = right_click_menu self.RowColors = row_colors - self.tree_ids = [] # ids returned when inserting items into table - will use to delete colors + self.tree_ids = [] # ids returned when inserting items into table - will use to delete colors super().__init__(ELEM_TYPE_TABLE, text_color=text_color, background_color=background_color, font=font, size=size, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) return @@ -4759,7 +4882,7 @@ class Table(Element): self.TKTreeview.delete(i) children = self.TKTreeview.get_children() - self.tree_ids =[] + self.tree_ids = [] for i, value in enumerate(values): if self.DisplayRowNumbers: value = [i + self.StartingRowNumber] + value @@ -4778,7 +4901,7 @@ class Table(Element): if num_rows is not None: self.TKTreeview.config(height=num_rows) if select_rows is not None: - rows_to_select = [i+1 for i in select_rows] + rows_to_select = [i + 1 for i in select_rows] self.TKTreeview.selection_set(rows_to_select) if alternating_row_color is not None: # alternating colors @@ -4822,7 +4945,7 @@ class Table(Element): """ selections = self.TKTreeview.selection() self.SelectedRows = [int(x) - 1 for x in selections] - if self.BindReturnKey: # Signifies BOTH a return key AND a double click + if self.BindReturnKey: # Signifies BOTH a return key AND a double click if self.Key is not None: self.ParentForm.LastButtonClicked = self.Key else: @@ -4841,13 +4964,12 @@ class Table(Element): """ return self.Values - - set_focus = Element.SetFocus set_tooltip = Element.SetTooltip update = Update get = Get + # ---------------------------------------------------------------------- # # Tree # # ---------------------------------------------------------------------- # @@ -4860,7 +4982,7 @@ 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, enable_events=False, font=None, justification='right', text_color=None, - background_color=None, num_rows=None, row_height=None, pad=None, key=None, tooltip=None, + background_color=None, header_text_color=None, header_background_color=None, header_font=None, num_rows=None, row_height=None, pad=None, key=None, tooltip=None, right_click_menu=None, visible=True, metadata=None): """ @@ -4883,6 +5005,9 @@ class Tree(Element): :param justification: (str) 'left', 'right', 'center' are valid choices :param text_color: (str) color of the text :param background_color: (str) color of background + :param header_text_color: (str) sets the text color for the header + :param header_background_color: (str) sets the background color for the header + :param header_font: Union[str, Tuple[str, int]] specifies the font family, size, etc :param num_rows: (int) The number of rows of the table to display at a time :param row_height: (int) height of a single row in pixels :param pad: (int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom)) @@ -4902,6 +5027,9 @@ class Tree(Element): self.AutoSizeColumns = auto_size_columns self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.TextColor = text_color + self.HeaderTextColor = header_text_color if header_text_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['TEXT_INPUT'] + self.HeaderBackgroundColor = header_background_color if header_background_color is not None else LOOK_AND_FEEL_TABLE[CURRENT_LOOK_AND_FEEL]['INPUT'] + self.HeaderFont = header_font self.Justification = justification self.InitialState = None self.SelectMode = select_mode @@ -4914,8 +5042,8 @@ class Tree(Element): self.RightClickMenu = right_click_menu self.RowHeight = row_height self.IconList = {} - self.IdToKey = {'':''} - self.KeyToID = {'':''} + self.IdToKey = {'': ''} + self.KeyToID = {'': ''} super().__init__(ELEM_TYPE_TREE, text_color=text_color, background_color=background_color, font=font, pad=pad, key=key, tooltip=tooltip, visible=visible, metadata=metadata) @@ -4942,7 +5070,6 @@ class Tree(Element): if self.ParentForm.CurrentlyRunningMainloop: self.ParentForm.TKroot.quit() - def add_treeview_data(self, node): """ Not a user function. Recursive method that inserts tree data into the tkinter treeview widget. @@ -4958,7 +5085,7 @@ class Tree(Element): photo = tk.PhotoImage(file=node.icon) node.photo = photo id = self.TKTreeview.insert(self.KeyToID[node.parent], 'end', iid=None, text=node.text, - values=node.values, open=self.ShowExpanded, image=node.photo) + values=node.values, open=self.ShowExpanded, image=node.photo) self.IdToKey[id] = node.key self.KeyToID[node.key] = id except: @@ -4972,7 +5099,6 @@ class Tree(Element): for node in node.children: self.add_treeview_data(node) - def Update(self, values=None, key=None, value=None, text=None, icon=None, visible=None): """ Changes some of the settings for the Tree Element. Must call `Window.Read` or `Window.Finalize` prior @@ -5030,21 +5156,23 @@ class Tree(Element): self.TKTreeview.pack() return self - set_focus = Element.SetFocus set_tooltip = Element.SetTooltip update = Update + class TreeData(object): """ Class that user fills in to represent their tree data. It's a very simple tree representation with a root "Node" with possibly one or more children "Nodes". Each Node contains a key, text to display, list of values to display and an icon. The entire tree is built using a single method, Insert. Nothing else is required to make the tree. """ + class Node(object): """ Contains information about the individual node in the tree """ + def __init__(self, parent, key, text, values, icon=None): """ :param parent: (TreeData.Node) The parent Node @@ -5054,12 +5182,12 @@ class TreeData(object): :param icon: Union[str, bytes] """ - self.parent = parent # type: TreeData.Node - self.children = [] # type: List[TreeData.Node] - self.key = key # type: str - self.text = text # type: str - self.values = values # type: List[Any] - self.icon = icon # type: Union[str, bytes] + self.parent = parent # type: TreeData.Node + self.children = [] # type: List[TreeData.Node] + self.key = key # type: str + self.text = text # type: str + self.values = values # type: List[Any] + self.icon = icon # type: Union[str, bytes] def _Add(self, node): """ @@ -5073,9 +5201,9 @@ class TreeData(object): """ Instantiate the object, initializes the Tree Data, creates a root node for you """ - self.tree_dict = {} # type: Dict[str : TreeData.Node] - self.root_node = self.Node("", "", 'root', [], None) # The root node - self.tree_dict[""] = self.root_node # Start the tree out with the root node + self.tree_dict = {} # type: Dict[str : TreeData.Node] + self.root_node = self.Node("", "", 'root', [], None) # The root node + self.tree_dict[""] = self.root_node # Start the tree out with the root node def _AddNode(self, key, node): """ @@ -5132,6 +5260,7 @@ class ErrorElement(Element): """ A "dummy Element" that is returned when there are error conditions, like trying to find an element that's invalid """ + def __init__(self, key=None, metadata=None): """ :param key: Used with window.FindElement and with return values to uniquely identify this element @@ -5140,7 +5269,6 @@ class ErrorElement(Element): super().__init__(ELEM_TYPE_ERROR, key=key, metadata=metadata) - def Update(self, silent_on_error=True, *args, **kwargs): """ Update method for the Error Element, an element that should not be directly used by developer @@ -5265,7 +5393,7 @@ class Window: self.WindowIcon = DEFAULT_WINDOW_ICON self.AutoClose = auto_close self.NonBlocking = False - self.TKroot = None + self.TKroot = None # type: tk.Tk self.TKrootDestroyed = False self.CurrentlyRunningMainloop = False self.FormRemainedOpen = False @@ -5313,7 +5441,10 @@ class Window: self.metadata = metadata self.TtkTheme = ttk_theme or DEFAULT_TTK_THEME self.UseTtkButtons = use_ttk_buttons if use_ttk_buttons is not None else USE_TTK_BUTTONS - if layout is not None and type(layout) not in (list, tuple): + self.user_bind_dict = {} # Used when user defines a tkinter binding using bind method - convert bind string to key modifier + self.user_bind_event = None # Used when user defines a tkinter binding using bind method - event data from tkinter + + if layout is not None and type(layout) not in (list, tuple): warnings.warn('Your layout is not a list or tuple... this is not good!') if layout is not None: @@ -5321,6 +5452,9 @@ class Window: if finalize: self.Finalize() + if CURRENT_LOOK_AND_FEEL == 'Default': + print("Window will be a boring gray. Try adding call to change_look_and_feel('Dark Blue 3') before your layout definition\n", + "If you seriously want this gray window and no more nagging, add change_look_and_feel('DefaultNoMoreNagging') ") @classmethod def GetAContainerNumber(cls): @@ -5377,30 +5511,30 @@ class Window: for i, element in enumerate(args): # Loop through list of elements and add them to the row if type(element) == list: PopupError('Error creating layout', - 'Layout has a LIST instead of an ELEMENT', - 'This means you have a badly placed ]', - 'The offensive list is:', - element, - 'This list will be stripped from your layout' - ) + 'Layout has a LIST instead of an ELEMENT', + 'This means you have a badly placed ]', + 'The offensive list is:', + element, + 'This list will be stripped from your layout' + ) continue elif callable(element) and not isinstance(element, Element): PopupError('Error creating layout', - 'Layout has a FUNCTION instead of an ELEMENT', - 'This means you are missing () from your layout', - 'The offensive list is:', - element, - 'This item will be stripped from your layout') + 'Layout has a FUNCTION instead of an ELEMENT', + 'This means you are missing () from your layout', + 'The offensive list is:', + element, + 'This item will be stripped from your layout') continue if element.ParentContainer is not None: warnings.warn('*** YOU ARE ATTEMPTING TO RESUSE A LAYOUT! You must not attempt this kind of re-use ***', UserWarning) PopupError('Error creating layout', - 'The layout specified has already been used', - 'You MUST start witha "clean", unused layout every time you create a window', - 'The offensive Element = ', - element, - 'and has a key = ', element.Key, - 'This item will be stripped from your layout') + 'The layout specified has already been used', + 'You MUST start witha "clean", unused layout every time you create a window', + 'The offensive Element = ', + element, + 'and has a key = ', element.Key, + 'This item will be stripped from your layout') continue element.Position = (CurrentRowNumber, i) element.ParentContainer = self @@ -5423,11 +5557,11 @@ class Window: iter(row) except TypeError: PopupError('Error creating layout', - 'Your row is not an iterable (e.g. a list)', - f'Instead of a list, the type found was {type(row)}', - 'The offensive row = ', - row, - 'This item will be stripped from your layout') + 'Your row is not an iterable (e.g. a list)', + 'Instead of a list, the type found was {}'.format(type(row)), + 'The offensive row = ', + row, + 'This item will be stripped from your layout') continue self.AddRow(*row) @@ -5445,7 +5579,6 @@ class Window: self._BuildKeyDict() return self - def LayoutAndRead(self, rows, non_blocking=False): """ Deprecated!! Now your layout your window's rows (layout) and then separately call Read. @@ -5466,7 +5599,6 @@ class Window: """ raise DeprecationWarning('LayoutAndShow is no longer supported... ') - def _Show(self, non_blocking=False): """ NOT TO BE CALLED BY USERS. INTERNAL ONLY! @@ -5550,7 +5682,6 @@ class Window: pass self.WindowIcon = wicon - def _GetElementAtLocation(self, location): """ Given a (row, col) location in a layout, return the element located at that position @@ -5604,7 +5735,6 @@ class Window: self.FormRemainedOpen = True self.TKroot.quit() # kick the users out of the mainloop - def Read(self, timeout=None, timeout_key=TIMEOUT_KEY): # type: (int, Any) -> Tuple[Any, Union[Dict, List]] """ @@ -5725,7 +5855,6 @@ class Window: self.ReturnValues = self.TimeoutKey, self.ReturnValues[1] # fake a timeout return self.ReturnValues - def _ReadNonBlocking(self): """ Should be NEVER called directly by the user. The user can call Window.Read(timeout=0) to get same effect @@ -5761,7 +5890,6 @@ class Window: return None, None return _BuildResults(self, False, self) - def Finalize(self): """ Use this method to cause your layout to built into a real tkinter window. In reality this method is like @@ -5788,7 +5916,6 @@ class Window: # return None, None return self - def Refresh(self): """ Refreshes the window by calling tkroot.update(). Can sometimes get away with a refresh instead of a Read. @@ -5806,7 +5933,6 @@ class Window: pass return self - def Fill(self, values_dict): """ Fill in elements that are input fields with data based on a 'values dictionary' @@ -5818,7 +5944,6 @@ class Window: FillFormWithValues(self, values_dict) return self - def FindElement(self, key, silent_on_error=False): """ Find element object associated with the provided key. @@ -5862,9 +5987,9 @@ class Window: element = ErrorElement(key=key) return element - Element = FindElement # Shortcut function - Find = FindElement # Shortcut function, most likely not used by many people. - Elem = FindElement # NEW for 2019! More laziness... Another shortcut + Element = FindElement # Shortcut function + Find = FindElement # Shortcut function, most likely not used by many people. + Elem = FindElement # NEW for 2019! More laziness... Another shortcut def FindElementWithFocus(self): """ @@ -5960,7 +6085,6 @@ class Window: except: print('*** Error loading form to disk ***') - def GetScreenDimensions(self): """ Get the screen dimensions. NOTE - you must have a window already open for this to work (blame tkinter not me) @@ -6027,7 +6151,6 @@ class Window: pass # print('Start move {},{}'.format(event.x,event.y)) - def _StopMove(self, event): """ Used by "Grab Anywhere" style windows. This function is bound to mouse-up. It marks the ending of a drag. @@ -6051,12 +6174,11 @@ class Window: 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)) # this is what really moves the window + self.TKroot.geometry("+%s+%s" % (x, y)) # this is what really moves the window # print('{},{}'.format(x,y)) except: pass - def _KeyboardCallback(self, event): """ Window keyboard callback. Called by tkinter. Will kick user out of the tkinter event loop. Should only be @@ -6130,7 +6252,6 @@ class Window: del self.TKroot del self.Rows - # IT FINALLY WORKED! 29-Oct-2018 was the first time this damned thing got called def _OnClosingCallback(self): """ @@ -6151,7 +6272,6 @@ class Window: self.RootNeedsDestroying = True self.RootNeedsDestroying = True - def Disable(self): """ Disables window from taking any input from the user @@ -6166,7 +6286,6 @@ class Window: self.TKroot.attributes('-disabled', 0) # self.TKroot.grab_release() - def Hide(self): """ Hides the window from the screen and the task bar @@ -6182,7 +6301,6 @@ class Window: self.TKroot.deiconify() self._Hidden = False - def Disappear(self): """ Causes a window to "disappear" from the screen, but remain on the taskbar. It does this by turning the alpha @@ -6226,7 +6344,6 @@ class Window: self._AlphaChannel = alpha self.TKroot.attributes('-alpha', alpha) - def BringToFront(self): """ Brings this window to the top of all other windows (perhaps may not be brought before a window made to "stay @@ -6254,7 +6371,6 @@ class Window: """ return int(self.TKroot.winfo_x()), int(self.TKroot.winfo_y()) - @property def Size(self): """ @@ -6288,7 +6404,6 @@ class Window: # A dummy function. Needed in Qt but not tkinter return - def SetTransparentColor(self, color): """ Set the color that will be transparent in your window. Areas with this color will be SEE THROUGH. @@ -6318,6 +6433,33 @@ class Window: self.TKroot.unbind("") self.TKroot.unbind("") + def _user_bind_callback(self, bind_string, event): + """ + Used when user binds a tkinter event directly to an element + + :param bind_string: The event that was bound so can lookup the key modifier + :param event: Event data passed in by tkinter (not used) + """ + + key = self.user_bind_dict.get(bind_string, '') + self.user_bind_event = event + if key is not None: + self.LastButtonClicked = key + else: + self.LastButtonClicked = bind_string + self.FormRemainedOpen = True + if self.CurrentlyRunningMainloop: + self.TKroot.quit() + + def bind(self, bind_string, key): + """ + Used to add tkinter events to a Window. + The tkinter specific data is in the Window's member variable user_bind_event + :param bind_string: The string tkinter expected in its bind function + :param key: The event that will be generated when the tkinter event occurs + """ + self.TKroot.bind(bind_string, lambda evt: self._user_bind_callback(bind_string, evt)) + self.user_bind_dict[bind_string] = key def _callback_main_debugger_window_create_keystroke(self, event): """ @@ -6343,7 +6485,6 @@ class Window: self.TKroot.bind('', self._callback_popout_window_create_keystroke) self.DebuggerEnabled = True - def DisableDebugger(self): """ Disable the internal debugger. By default the debugger is ENABLED @@ -6352,7 +6493,6 @@ class Window: self.TKroot.unbind("") self.DebuggerEnabled = False - def VisibilityChanged(self): """ This is a completely dummy method that does nothing. It is here so that PySimpleGUIQt programs can make this @@ -6361,8 +6501,6 @@ class Window: """ return - - # def __enter__(self): # """ # WAS used with context managers which are no longer needed nor advised. It is here for legacy support and @@ -6386,7 +6524,6 @@ class Window: warnings.warn('The key you passed in is no good. Key = {}*'.format(key)) return None - def __call__(self, *args, **kwargs): """ Call window.Read but without having to type it out. @@ -6399,7 +6536,6 @@ class Window: """ return self.Read(*args, **kwargs) - add_row = AddRow add_rows = AddRows alpha_channel = AlphaChannel @@ -6457,6 +6593,8 @@ class Window: # for row in self.Rows: # for element in row: # element.__del__() + + # -------------------------------- PEP8-ify the Window Class USER Interfaces -------------------------------- # @@ -6464,6 +6602,7 @@ FlexForm = Window Window.CloseNonBlockingForm = Window.Close Window.CloseNonBlocking = Window.Close + # ################################################################################ # ################################################################################ # END OF ELEMENT DEFINITIONS @@ -6485,7 +6624,8 @@ def Sizer(h_pixels=0, v_pixels=0): :return: (Column) A column element that has a pad setting set according to parameters """ - return Column([[]], pad=((h_pixels,0),(v_pixels,0))) + return Column([[]], pad=((h_pixels, 0), (v_pixels, 0))) + # ------------------------- FOLDER BROWSE Element lazy function ------------------------- # def FolderBrowse(button_text='Browse', target=(ThisRow, -1), initial_folder=None, tooltip=None, size=(None, None), @@ -6549,6 +6689,8 @@ def FilesBrowse(button_text='Browse', target=(ThisRow, -1), file_types=(("ALL Fi change_submits=False, enable_events=False, font=None, pad=None, key=None, metadata=None): """ + Allows browsing of multiple files. File list is returned as a single list with the delimeter defined using the variable + BROWSE_FILES_DELIMETER. This defaults to ';' but is changable by the user :param button_text: text in the button (Default value = 'Browse') :param target: key or (row,col) target for the button (Default value = (ThisRow, -1)) @@ -7214,7 +7356,6 @@ def EncodeRadioRowCol(container, row, col): return RadValue - # ------- FUNCTION BuildResults. Form exiting so build the results to pass back ------- # # format of return values is # (Button Pressed, input_values) @@ -7347,13 +7488,13 @@ def _BuildResultsForSubform(form, initialize_only, top_level_form): except: value = None elif element.Type == ELEM_TYPE_INPUT_COMBO: - element = element # type: Combo + element = element # type: Combo # value = element.TKStringVar.get() try: - if element.TKCombo.current() == -1: # if the current value was not in the original list + if element.TKCombo.current() == -1: # if the current value was not in the original list value = element.TKCombo.get() else: - value = element.Values[element.TKCombo.current()] # get value from original list given index + value = element.Values[element.TKCombo.current()] # get value from original list given index except: value = '*Exception occurred*' elif element.Type == ELEM_TYPE_INPUT_OPTION_MENU: @@ -7512,7 +7653,7 @@ def _FindElementWithFocusInSubForm(form): if element.TKButton is not None: if element.TKButton is element.TKButton.focus_get(): return element - else: # The "Catch All" - if type isn't one of the above, try generic element.Widget + else: # The "Catch All" - if type isn't one of the above, try generic element.Widget try: if element.Widget is not None: if element.Widget is element.Widget.focus_get(): @@ -7522,6 +7663,7 @@ def _FindElementWithFocusInSubForm(form): return None + if sys.version_info[0] >= 3: def AddMenuItem(top_menu, sub_menu_info, element, is_sub_menu=False, skip=False): """ @@ -7647,7 +7789,7 @@ else: # Y88b. 888 "88b 888 888 888 Y88b. Y8b. 888 # "Y888 888 888 888 888 888 "Y888 "Y8888 888 -# My crappy tkinter code starts here +# My crappy tkinter code starts here. (search for "crappy" to get here quickly... that's the purpose if you hadn't caught on """ ) @@ -7660,6 +7802,9 @@ else: """ +# Also, to get to the point in the code where each element's widget is created, look for element + "p lacement" (without the space) + + # ======================== TK CODE STARTS HERE ========================================= # def PackFormIntoFrame(form, containing_frame, toplevel_form): @@ -7670,11 +7815,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): :param toplevel_form: (Window) """ + 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 ********** ----- # @@ -7718,9 +7863,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element_size = toplevel_form.DefaultButtonElementSize else: auto_size_text = False # if user has specified a size then it shouldn't autosize - # ------------------------- COLUMN element ------------------------- # + # ------------------------- COLUMN placement element ------------------------- # if element_type == ELEM_TYPE_COLUMN: - element = element # type: Column + element = element # type: Column if element.Scrollable: element.TKColFrame = TkScrollableFrame(tk_row_frame, element.VerticalScrollOnly) # do not use yet! not working PackFormIntoFrame(element, element.TKColFrame.TKFrame, toplevel_form) @@ -7756,21 +7901,21 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): element.TKColFrame.canvas.config(background=element.BackgroundColor) element.TKColFrame.TKFrame.config(background=element.BackgroundColor, borderwidth=0, - highlightthickness=0) + highlightthickness=0) else: element.TKColFrame = tk.Frame(tk_row_frame) PackFormIntoFrame(element, element.TKColFrame, toplevel_form) if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): element.TKColFrame.config(background=element.BackgroundColor, borderwidth=0, - highlightthickness=0) + highlightthickness=0) if element.Justification.lower().startswith('c'): - anchor=tk.N - side=tk.TOP + anchor = tk.N + side = tk.TOP elif element.Justification.lower().startswith('r'): - anchor=tk.NE + anchor = tk.NE side = tk.RIGHT else: - anchor=tk.NW + anchor = tk.NW side = tk.LEFT # anchor=tk.NW # side = tk.LEFT @@ -7792,7 +7937,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKRightClickMenu = top_menu element.TKColFrame.bind('', element._RightClickMenuCallback) # row_should_expand = True - # ------------------------- Pane element ------------------------- # + # ------------------------- Pane placement element ------------------------- # if element_type == ELEM_TYPE_PANE: bd = element.BorderDepth if element.BorderDepth is not None else border_depth element.PanedWindow = element.Widget = tk.PanedWindow(tk_row_frame, @@ -7824,7 +7969,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.PanedWindow.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=True, fill='both') if element.Visible is False: element.PanedWindow.pack_forget() - # ------------------------- TEXT element ------------------------- # + # ------------------------- TEXT placement element ------------------------- # elif element_type == ELEM_TYPE_TEXT: # auto_size_text = element.AutoSizeText element = element # type: Text @@ -7841,7 +7986,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): width = max_line_len height = num_lines # ---===--- LABEL widget create and place --- # - element = element # type: Text + element = element # type: Text bd = element.BorderWidth if element.BorderWidth is not None else border_depth stringvar = tk.StringVar() element.TKStringVar = stringvar @@ -7861,7 +8006,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): height=height, justify=justify, bd=bd, font=font) # Set wrap-length for text (in PIXELS) == PAIN IN THE ASS wraplen = tktext_label.winfo_reqwidth() # width of widget in Pixels - if not auto_size_text and height == 1: # if just 1 line high, ensure no wrap happens + if not auto_size_text and height == 1: # if just 1 line high, ensure no wrap happens wraplen = 0 # print(f'Text wraplen = {wraplen} wxh = {width} x {height}') # print(f'Len = {len(display_text)} Text = {str(display_text)}') @@ -7886,10 +8031,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu tktext_label.bind('', element._RightClickMenuCallback) - # ------------------------- BUTTON element non-ttk version ------------------------- # + # ------------------------- BUTTON placement element non-ttk version ------------------------- # elif (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is False) or \ - (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is not True and toplevel_form.UseTtkButtons is not True): + (element_type == ELEM_TYPE_BUTTON and element.UseTtkButtons is not True and toplevel_form.UseTtkButtons is not True): element = element # type: Button + element.UseTtkButtons = False # indicate that ttk button was not used stringvar = tk.StringVar() element.TKStringVar = stringvar element.Location = (row_num, col_num) @@ -7925,7 +8071,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): tkbutton.config(foreground=bc[0]) if bd == 0 and not sys.platform.startswith('darwin'): tkbutton.config(relief=tk.FLAT) - tkbutton.config(highlightthickness=0) + tkbutton.config(highlightthickness=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 @@ -7964,12 +8110,16 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): toplevel_form.TKroot.focus_force() if element.Disabled == True: element.TKButton['state'] = 'disabled' + if element.DisabledButtonColor != (None, None): + if element.DisabledButtonColor[0] is not None: + element.TKButton['disabledforeground'] = element.DisabledButtonColor[0] if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- BUTTON element ttk version ------------------------- # + # ------------------------- BUTTON placement element ttk version ------------------------- # elif element_type == ELEM_TYPE_BUTTON: element = element # type: Button + element.UseTtkButtons = True # indicate that ttk button was used stringvar = tk.StringVar() element.TKStringVar = stringvar element.Location = (row_num, col_num) @@ -8001,10 +8151,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): style_name = str(element.Key) + 'custombutton.TButton' button_style = ttk.Style() button_style.theme_use(toplevel_form.TtkTheme) - # if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: - # button_style.configure(style_name, background=element.BackgroundColor) - # if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: - # button_style.configure(style_name, foreground=element.TextColor) button_style.configure(style_name, font=font) if bc != (None, None) and bc != COLOR_SYSTEM_DEFAULT and bc[1] != COLOR_SYSTEM_DEFAULT: @@ -8017,12 +8163,44 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): else: button_style.configure(style_name, borderwidth=bd) button_style.configure(style_name, justify=tk.CENTER) + if element.DisabledButtonColor != (None, None): + if element.DisabledButtonColor[0] is not None: + button_style.map(style_name, foreground=[('disabled', element.DisabledButtonColor[0])]) + if element.DisabledButtonColor[1] is not None: + button_style.map(style_name, background=[('disabled', element.DisabledButtonColor[1])]) if height > 1: - button_style.configure(style_name, padding=height*CharWidthInPixels()) + button_style.configure(style_name, padding=height * CharWidthInPixels()) wraplen = tkbutton.winfo_reqwidth() # width of widget in Pixels if width != 0: button_style.configure(style_name, wraplength=wraplen) # set wrap to width of widget + if element.ImageFilename: # if button has an image on it + button_style.configure(style_name, borderwidth=0) + # tkbutton.configure(highlightthickness=0) + photo = tk.PhotoImage(file=element.ImageFilename) + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + if element.ImageSize != (None, None): + width, height = element.ImageSize + else: + width, height = photo.width(), photo.height() + button_style.configure(style_name, image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + if element.ImageData: # if button has an image on it + # tkbutton.configure(highlightthickness=0) + button_style.configure(style_name, borderwidth=0) + + photo = tk.PhotoImage(data=element.ImageData) + if element.ImageSubsample: + photo = photo.subsample(element.ImageSubsample) + if element.ImageSize != (None, None): + width, height = element.ImageSize + else: + width, height = photo.width(), photo.height() + button_style.configure(style_name, image=photo, compound=tk.CENTER, width=width, height=height) + # tkbutton.configure(image=photo, compound=tk.CENTER, width=width, height=height) + tkbutton.image = photo + element.TKButton = tkbutton # not used yet but save the TK button in case tkbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1]) if element.Visible is False: @@ -8037,14 +8215,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if element.Disabled == True: element.TKButton['state'] = 'disabled' - tkbutton.configure(style=style_name) # IMPORTANT! Apply the style to the button! + tkbutton.configure(style=style_name) # IMPORTANT! Apply the style to the button! if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKButton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- BUTTONMENU element ------------------------- # + # ------------------------- BUTTONMENU placement element ------------------------- # elif element_type == ELEM_TYPE_BUTTONMENU: - element = element # type: ButtonMenu + element = element # type: ButtonMenu element.Location = (row_num, col_num) btext = element.ButtonText if element.AutoSizeButton is not None: @@ -8072,11 +8250,10 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): tkbutton.config(foreground=bc[0]) if bd == 0: tkbutton.config(relief=tk.FLAT) - tkbutton.config(highlightthickness=0) + tkbutton.config(highlightthickness=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 @@ -8087,7 +8264,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): 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 @@ -8117,7 +8293,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- INPUT element ------------------------- # + # ------------------------- INPUT placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_TEXT: element = element # type: InputText default_text = element.DefaultText @@ -8142,6 +8318,8 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): 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.Widget.config(highlightthickness=0) + element.TKEntry.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], expand=False, fill=tk.NONE) if element.Visible is False: element.TKEntry.pack_forget() @@ -8160,9 +8338,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKEntry.bind('', element._RightClickMenuCallback) # row_should_expand = True - # ------------------------- COMBOBOX element ------------------------- # + # ------------------------- COMBO placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_COMBO: - element = element # type: InputCombo + element = element # type: InputCombo max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0 if auto_size_text is False: width = element_size[0] @@ -8175,7 +8353,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # s.theme_use('default') if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: # Creates 1 style per Text Color/ Background Color combination - style_name = str(element.Key) +'.TCombobox' + style_name = str(element.Key) + '.TCombobox' combostyle = ttk.Style() combostyle.theme_use(toplevel_form.TtkTheme) @@ -8225,10 +8403,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if element.Visible is False: element.TKCombo.pack_forget() if element.DefaultValue is not None: - for i, v in enumerate(element.Values): - if v == element.DefaultValue: - element.TKCombo.current(i) - break + element.TKCombo.set(element.DefaultValue) + # for i, v in enumerate(element.Values): + # if v == element.DefaultValue: + # element.TKCombo.current(i) + # break # elif element.Values: # element.TKCombo.current(0) if element.ChangeSubmits: @@ -8239,7 +8418,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKCombo['state'] = 'disabled' if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKCombo, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- OPTION MENU Element (Like ComboBox but different) element ------------------------- # + # ------------------------- OPTION MENU placement Element (Like ComboBox but different) element ------------------------- # elif element_type == ELEM_TYPE_INPUT_OPTION_MENU: max_line_len = max([len(str(l)) for l in element.Values]) if auto_size_text is False: @@ -8265,7 +8444,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKOptionMenu, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- LISTBOX element ------------------------- # + # ------------------------- LISTBOX placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_LISTBOX: element = element # type: Listbox max_line_len = max([len(str(l)) for l in element.Values]) if len(element.Values) else 0 @@ -8278,6 +8457,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKListbox = element.Widget = tk.Listbox(listbox_frame, height=element_size[1], width=width, selectmode=element.SelectMode, font=font, exportselection=False) + element.Widget.config(highlightthickness=0) for index, item in enumerate(element.Values): element.TKListbox.insert(tk.END, item) if element.DefaultValues is not None and item in element.DefaultValues: @@ -8311,7 +8491,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu element.TKListbox.bind('', element._RightClickMenuCallback) - # ------------------------- MULTILINE element ------------------------- # + # ------------------------- MULTILINE placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_MULTILINE: element = element # type: Multiline default_text = element.DefaultText @@ -8321,6 +8501,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): wrap='word', bd=bd, font=font, relief=RELIEF_SUNKEN) element.TKText.insert(1.0, default_text) # set the default text + element.TKText.config(highlightthickness=0) if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: element.TKText.configure(background=element.BackgroundColor) if DEFAULT_SCROLLBAR_COLOR not in (None, COLOR_SYSTEM_DEFAULT): @@ -8373,14 +8554,16 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): 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.Widget.configure(highlightthickness=0) element.TKCheckbutton.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1]) if element.Visible is False: element.TKCheckbutton.pack_forget() if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKCheckbutton, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- PROGRESS BAR element ------------------------- # + # ------------------------- PROGRESS placement element ------------------------- # elif element_type == ELEM_TYPE_PROGRESS_BAR: + element = element # type: ProgressBar # save this form because it must be 'updated' (refreshed) solely for the purpose of updating bar width = element_size[0] fnt = tkinter.font.Font() @@ -8400,7 +8583,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if element.Visible is False: element.TKProgressBar.TKProgressBarForReal.pack_forget() element.Widget = element.TKProgressBar.TKProgressBarForReal - # ------------------------- RADIO BUTTON element ------------------------- # + # ------------------------- RADIO placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_RADIO: element = element # type: Radio width = 0 if auto_size_text else element_size[0] @@ -8432,8 +8615,10 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if not element.BackgroundColor in (None, COLOR_SYSTEM_DEFAULT): element.TKRadio.configure(background=element.BackgroundColor) element.TKRadio.configure(selectcolor=element.BackgroundColor) + element.TKRadio.configure(activebackground=element.BackgroundColor) if text_color is not None and text_color != COLOR_SYSTEM_DEFAULT: element.TKRadio.configure(fg=text_color) + element.Widget.config(highlightthickness=0) if element.Disabled: element.TKRadio['state'] = 'disabled' element.TKRadio.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1]) @@ -8441,19 +8626,21 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKRadio.pack_forget() if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKRadio, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- SPIN element ------------------------- # + # ------------------------- SPIN placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_SPIN: - element = element # type: Spin + element = element # type: Spin width, height = element_size width = 0 if auto_size_text else element_size[0] element.TKStringVar = tk.StringVar() element.TKSpinBox = element.Widget = tk.Spinbox(tk_row_frame, values=element.Values, textvariable=element.TKStringVar, width=width, bd=border_depth) - element.TKStringVar.set(element.DefaultValue) + if element.DefaultValue is not None: + 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.Widget.config(highlightthickness=0) element.TKSpinBox.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1]) if element.Visible is False: element.TKSpinBox.pack_forget() @@ -8466,7 +8653,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKSpinBox, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- OUTPUT element ------------------------- # + # ------------------------- OUTPUT placement element ------------------------- # elif element_type == ELEM_TYPE_OUTPUT: width, height = element_size element._TKOut = element.Widget = TKOutput(tk_row_frame, width=width, height=height, bd=border_depth, @@ -8488,7 +8675,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # row_should_expand = True # ------------------------- IMAGE element ------------------------- # elif element_type == ELEM_TYPE_IMAGE: - element = element # type: Image + element = element # type: Image if element.Filename is not None: photo = tk.PhotoImage(file=element.Filename) elif element.Data is not None: @@ -8530,7 +8717,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu element.tktext_label.bind('', element._RightClickMenuCallback) - # ------------------------- Canvas element ------------------------- # + # ------------------------- Canvas placement element ------------------------- # elif element_type == ELEM_TYPE_CANVAS: width, height = element_size if element._TKCanvas is None: @@ -8552,7 +8739,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu element._TKCanvas.bind('', element._RightClickMenuCallback) - # ------------------------- Graph element ------------------------- # + # ------------------------- Graph placement element ------------------------- # elif element_type == ELEM_TYPE_GRAPH: element = element # type: Graph width, height = element_size @@ -8586,7 +8773,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu element._TKCanvas2.bind('', element._RightClickMenuCallback) - # ------------------------- MENUBAR element ------------------------- # + # ------------------------- MENU placement element ------------------------- # elif element_type == ELEM_TYPE_MENUBAR: element = element # type: MenuBar menu_def = element.MenuDefinition @@ -8611,14 +8798,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): if len(menu_entry) > 1: AddMenuItem(baritem, menu_entry[1], element) toplevel_form.TKroot.configure(menu=element.TKMenu) - # ------------------------- Frame element ------------------------- # + # ------------------------- Frame placement element ------------------------- # elif element_type == ELEM_TYPE_FRAME: - element = element # type: Frame + element = element # type: Frame labeled_frame = element.Widget = tk.LabelFrame(tk_row_frame, text=element.Title, relief=element.Relief) element.TKFrame = labeled_frame PackFormIntoFrame(element, labeled_frame, toplevel_form) labeled_frame.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.NONE, expand=False) - if element.Size != (None,None): + if element.Size != (None, None): labeled_frame.config(width=element.Size[0], height=element.Size[1]) if not element.Visible: labeled_frame.pack_forget() @@ -8643,15 +8830,17 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKRightClickMenu = top_menu labeled_frame.bind('', element._RightClickMenuCallback) # row_should_expand=True - # ------------------------- Tab element ------------------------- # + # ------------------------- Tab placement element ------------------------- # elif element_type == ELEM_TYPE_TAB: - element = element # type: Tab + element = element # type: Tab element.TKFrame = element.Widget = tk.Frame(form.TKNotebook) PackFormIntoFrame(element, element.TKFrame, toplevel_form) + state = 'normal' if element.Disabled: - form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled') - else: - form.TKNotebook.add(element.TKFrame, text=element.Title) + state = 'disabled' + if element.Visible is False: + state = 'hidden' + form.TKNotebook.add(element.TKFrame, text=element.Title, state=state) form.TKNotebook.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill=tk.NONE, expand=False) element.ParentNotebook = form.TKNotebook element.TabID = form.TabCount @@ -8660,13 +8849,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): 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) @@ -8680,9 +8862,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKRightClickMenu = top_menu element.TKFrame.bind('', element._RightClickMenuCallback) # row_should_expand = True - # ------------------------- TabGroup element ------------------------- # + # ------------------------- TabGroup placement element ------------------------- # elif element_type == ELEM_TYPE_TAB_GROUP: - element=element # type: TabGroup + element = element # type: TabGroup custom_style = str(element.Key) + 'customtab.TNotebook' style = ttk.Style(tk_row_frame) style.theme_use(toplevel_form.TtkTheme) @@ -8699,19 +8881,16 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): 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: + # FINALLY the proper styling to get tab colors! + if element.SelectedTitleColor is not None and element.SelectedTitleColor != COLOR_SYSTEM_DEFAULT: style.map(custom_style + '.Tab', foreground=[("selected", element.SelectedTitleColor)]) + if element.SelectedBackgroundColor is not None and element.SelectedBackgroundColor != COLOR_SYSTEM_DEFAULT: + style.map(custom_style + '.Tab', background=[("selected", element.SelectedBackgroundColor)]) + if element.TabBackgroundColor is not None and element.TabBackgroundColor != COLOR_SYSTEM_DEFAULT: + style.configure(custom_style + '.Tab', background=element.TabBackgroundColor) 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') + style.configure(custom_style + '.Tab', font=font) element.TKNotebook = element.Widget = ttk.Notebook(tk_row_frame, style=custom_style) @@ -8725,9 +8904,9 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TooltipObject = ToolTip(element.TKNotebook, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) # row_should_expand = True - # ------------------------- SLIDER element ------------------------- # + # ------------------------- SLIDER placement element ------------------------- # elif element_type == ELEM_TYPE_INPUT_SLIDER: - element = element # type: Slider + element = element # type: Slider slider_length = element_size[0] * CharWidthInPixels() slider_width = element_size[1] element.TKIntVar = tk.IntVar() @@ -8773,7 +8952,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element.TKScale['state'] = 'disabled' if element.Tooltip is not None: element.TooltipObject = ToolTip(element.TKScale, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) - # ------------------------- TABLE element ------------------------- # + # ------------------------- TABLE placement element ------------------------- # elif element_type == ELEM_TYPE_TABLE: element = element # type: Table frame = tk.Frame(tk_row_frame) @@ -8832,7 +9011,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): width = element.ColumnWidths[i] except: width = element.DefaultColumnWidth - treeview.column(heading, width=width * CharWidthInPixels(),minwidth=10, anchor=anchor, stretch=0) + treeview.column(heading, width=width * CharWidthInPixels(), minwidth=10, anchor=anchor, stretch=0) # Insert values into the tree for i, value in enumerate(element.Values): @@ -8859,6 +9038,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): table_style.configure(style_name, foreground=element.TextColor) if element.RowHeight is not None: table_style.configure(style_name, rowheight=element.RowHeight) + if element.HeaderTextColor is not None and element.HeaderTextColor != COLOR_SYSTEM_DEFAULT: + table_style.configure(style_name+'.Heading', foreground=element.HeaderTextColor) + if element.HeaderBackgroundColor is not None and element.HeaderBackgroundColor != COLOR_SYSTEM_DEFAULT: + table_style.configure(style_name+'.Heading', background=element.HeaderBackgroundColor) + if element.HeaderFont is not None: + table_style.configure(style_name+'.Heading', font=element.HeaderFont) + else: + table_style.configure(style_name+'.Heading', font=font) table_style.configure(style_name, font=font) treeview.configure(style=style_name) @@ -8893,7 +9080,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu element.TKTreeview.bind('', element._RightClickMenuCallback) - # ------------------------- Tree element ------------------------- # + # ------------------------- Tree placement element ------------------------- # elif element_type == ELEM_TYPE_TREE: element = element # type: Tree frame = tk.Frame(tk_row_frame) @@ -8945,13 +9132,13 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): else: photo = tk.PhotoImage(file=node.icon) node.photo = photo - id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, - open=element.ShowExpanded, image=node.photo) + id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, + open=element.ShowExpanded, image=node.photo) element.IdToKey[id] = node.key element.KeyToID[node.key] = id else: - id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, - open=element.ShowExpanded) + id = treeview.insert(element.KeyToID[node.parent], 'end', iid=None, text=node.text, values=node.values, + open=element.ShowExpanded) element.IdToKey[id] = node.key element.KeyToID[node.key] = id @@ -8966,14 +9153,21 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): tree_style.theme_use(toplevel_form.TtkTheme) if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: tree_style.configure(style_name, background=element.BackgroundColor, - fieldbackground=element.BackgroundColor) + fieldbackground=element.BackgroundColor) if element.TextColor is not None and element.TextColor != COLOR_SYSTEM_DEFAULT: tree_style.configure(style_name, foreground=element.TextColor) - + if element.HeaderTextColor is not None and element.HeaderTextColor != COLOR_SYSTEM_DEFAULT: + tree_style.configure(style_name+'.Heading', foreground=element.HeaderTextColor) + if element.HeaderBackgroundColor is not None and element.HeaderBackgroundColor != COLOR_SYSTEM_DEFAULT: + tree_style.configure(style_name+'.Heading', background=element.HeaderBackgroundColor) + if element.HeaderFont is not None: + tree_style.configure(style_name+'.Heading', font=element.HeaderFont) + else: + tree_style.configure(style_name+'.Heading', font=font) tree_style.configure(style_name, font=font) if element.RowHeight: tree_style.configure(style_name, rowheight=element.RowHeight) - treeview.configure(style=style_name) # IMPORTANT! Be sure and set the style name for this widget + treeview.configure(style=style_name) # IMPORTANT! Be sure and set the style name for this widget scrollbar = tk.Scrollbar(frame) scrollbar.pack(side=tk.RIGHT, fill='y') scrollbar.config(command=treeview.yview) @@ -8992,12 +9186,12 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): AddMenuItem(top_menu, menu[1], element) element.TKRightClickMenu = top_menu element.TKTreeview.bind('', element._RightClickMenuCallback) - # ------------------------- Separator element ------------------------- # + # ------------------------- Separator placement element ------------------------- # elif element_type == ELEM_TYPE_SEPARATOR: element = element # type: VerticalSeparator separator = element.Widget = ttk.Separator(tk_row_frame, orient=element.Orientation, ) separator.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1], fill='both', expand=True) - # ------------------------- StatusBar element ------------------------- # + # ------------------------- StatusBar placement element ------------------------- # elif element_type == ELEM_TYPE_STATUSBAR: # auto_size_text = element.AutoSizeText display_text = element.DisplayText # text to display @@ -9057,13 +9251,13 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # tk_row_frame.grid(row=row_num+2, sticky=tk.NW, padx=DEFAULT_MARGINS[0]) if row_justify.lower().startswith('c'): - anchor='n' - side=tk.CENTER + anchor = 'n' + side = tk.CENTER elif row_justify.lower().startswith('r'): - anchor='ne' + anchor = 'ne' side = tk.RIGHT elif row_justify.lower().startswith('l'): - anchor='nw' + anchor = 'nw' side = tk.LEFT elif toplevel_form.ElementJustification.lower().startswith('c'): anchor = 'n' @@ -9142,7 +9336,7 @@ def StartupTK(my_flex_form): :param my_flex_form: (Window): """ - my_flex_form = my_flex_form # type: Window + my_flex_form = my_flex_form # type: Window # global _my_windows # ow = _my_windows.NumOpenWindows ow = Window.NumOpenWindows @@ -9528,7 +9722,7 @@ class DebugWin(): self.window.Read(timeout=0) # Show a non-blocking form, returns immediately return - def Print(self, *args, end=None, sep=None): + def Print(self, *args, end=None, sep=None, text_color=None, background_color=None): """ :param *args: @@ -9554,7 +9748,7 @@ class DebugWin(): for arg in args: outstring += str(arg) + sepchar outstring += endchar - self.output_element.Update(outstring, append=True) + self.output_element.Update(outstring, append=True, text_color_for_value=text_color, background_color_for_value=background_color) else: print(*args, sep=sepchar, end=endchar) @@ -9571,7 +9765,7 @@ def PrintClose(): 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, do_not_reroute_stdout=True): + no_button=False, grab_anywhere=False, keep_on_top=False, do_not_reroute_stdout=True, text_color=None, background_color=None): """ :param *args: @@ -9591,7 +9785,7 @@ def EasyPrint(*args, size=(None, None), end=None, sep=None, location=(None, None DebugWin.debug_window = 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, do_not_reroute_stdout=do_not_reroute_stdout) - DebugWin.debug_window.Print(*args, end=end, sep=sep) + DebugWin.debug_window.Print(*args, end=end, sep=sep, text_color=text_color, background_color=background_color) Print = EasyPrint @@ -9815,8 +10009,6 @@ def SetOptions(icon=None, button_color=None, element_size=(None, None), button_e if use_ttk_buttons is not None: USE_TTK_BUTTONS = use_ttk_buttons - - return True @@ -9824,795 +10016,984 @@ def SetOptions(icon=None, button_color=None, element_size=(None, None), button_e # 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}, +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}, - 'SystemDefaultForReal': - {'BACKGROUND': COLOR_SYSTEM_DEFAULT, - 'TEXT': COLOR_SYSTEM_DEFAULT, - 'INPUT': COLOR_SYSTEM_DEFAULT, - 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, - 'SCROLL': COLOR_SYSTEM_DEFAULT, - 'BUTTON': COLOR_SYSTEM_DEFAULT, - 'PROGRESS': COLOR_SYSTEM_DEFAULT, - 'BORDER': 1, 'SLIDER_DEPTH': 1, - 'PROGRESS_DEPTH': 0}, + 'SystemDefaultForReal': + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, - 'Material1': {'BACKGROUND': '#E3F2FD', - 'TEXT': '#000000', - 'INPUT': '#86A8FF', - 'TEXT_INPUT': '#000000', - 'SCROLL': '#86A8FF', - 'BUTTON': ('#FFFFFF', '#5079D3'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 0, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0, - 'ACCENT1': '#FF0266', - 'ACCENT2': '#FF5C93', - 'ACCENT3': '#C5003C'}, + 'Material1': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, - 'Material2': {'BACKGROUND': '#FAFAFA', - 'TEXT': '#000000', - 'INPUT': '#004EA1', - 'TEXT_INPUT': '#FFFFFF', - 'SCROLL': '#5EA7FF', - 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 0, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0, - 'ACCENT1': '#FF0266', - 'ACCENT2': '#FF5C93', - 'ACCENT3': '#C5003C'}, + 'Material2': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', + 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, - 'Reddit': {'BACKGROUND': '#ffffff', - 'TEXT': '#1a1a1b', - 'INPUT': '#dae0e6', - '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'}, + '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'}, + '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}, + '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': '#404040', - 'TEXT': 'white', - 'INPUT': '#4D4D4D', - 'TEXT_INPUT': 'white', - 'SCROLL': '#707070', - 'BUTTON': ('white', '#004F00'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, + 'Dark': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + '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}, + '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': '#404040', - 'TEXT': 'white', - 'INPUT': 'white', - 'TEXT_INPUT': 'black', - 'SCROLL': '#707070', - 'BUTTON': ('white', '#004F00'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, + 'Dark2': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': 'white', + 'TEXT_INPUT': 'black', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, - 'Black': {'BACKGROUND': 'black', - 'TEXT': 'white', - 'INPUT': '#4D4D4D', - 'TEXT_INPUT': 'white', - 'SCROLL': '#707070', - 'BUTTON': ('black', 'white'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, + 'Black': {'BACKGROUND': 'black', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, + '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}, -################################## Renamed Original Themes ################################## -'Default': - {'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}, + '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}, + ################################## Renamed Original Themes ################################## + 'Default': # plain gray but blue buttons + {'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}, - 'Default1': - {'BACKGROUND': COLOR_SYSTEM_DEFAULT, - 'TEXT': COLOR_SYSTEM_DEFAULT, - 'INPUT': COLOR_SYSTEM_DEFAULT, - 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, - 'SCROLL': COLOR_SYSTEM_DEFAULT, - 'BUTTON': COLOR_SYSTEM_DEFAULT, - 'PROGRESS': COLOR_SYSTEM_DEFAULT, - 'BORDER': 1, 'SLIDER_DEPTH': 1, - 'PROGRESS_DEPTH': 0}, + 'Default1': # everything is gray + {'BACKGROUND': COLOR_SYSTEM_DEFAULT, + 'TEXT': COLOR_SYSTEM_DEFAULT, + 'INPUT': COLOR_SYSTEM_DEFAULT, + 'TEXT_INPUT': COLOR_SYSTEM_DEFAULT, + 'SCROLL': COLOR_SYSTEM_DEFAULT, + 'BUTTON': COLOR_SYSTEM_DEFAULT, + 'PROGRESS': COLOR_SYSTEM_DEFAULT, + 'BORDER': 1, 'SLIDER_DEPTH': 1, + 'PROGRESS_DEPTH': 0}, - 'LightBlue': {'BACKGROUND': '#E3F2FD', - 'TEXT': '#000000', - 'INPUT': '#86A8FF', - 'TEXT_INPUT': '#000000', - 'SCROLL': '#86A8FF', - 'BUTTON': ('#FFFFFF', '#5079D3'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 0, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0, - 'ACCENT1': '#FF0266', - 'ACCENT2': '#FF5C93', - 'ACCENT3': '#C5003C'}, + 'DefaultNoMoreNagging': # a duplicate of "Default" for users that are tired of the nag screen + {'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}, - 'LightGrey': {'BACKGROUND': '#FAFAFA', - 'TEXT': '#000000', - 'INPUT': '#004EA1', - 'TEXT_INPUT': '#FFFFFF', - 'SCROLL': '#5EA7FF', - 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 0, 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0, - 'ACCENT1': '#FF0266', - 'ACCENT2': '#FF5C93', - 'ACCENT3': '#C5003C'}, + 'LightBlue': {'BACKGROUND': '#E3F2FD', + 'TEXT': '#000000', + 'INPUT': '#86A8FF', + 'TEXT_INPUT': '#000000', + 'SCROLL': '#86A8FF', + 'BUTTON': ('#FFFFFF', '#5079D3'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, - 'LightGrey1': {'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'}, + 'LightGrey': {'BACKGROUND': '#FAFAFA', + 'TEXT': '#000000', + 'INPUT': '#004EA1', + 'TEXT_INPUT': '#FFFFFF', + 'SCROLL': '#5EA7FF', + 'BUTTON': ('#FFFFFF', '#0079D3'), # based on Reddit color + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 0, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'ACCENT1': '#FF0266', + 'ACCENT2': '#FF5C93', + 'ACCENT3': '#C5003C'}, - 'DarkBrown': {'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'}, + 'LightGrey1': {'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'}, - 'LightGreen1': {'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}, + 'DarkBrown': {'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'}, - 'DarkGrey': {'BACKGROUND': '#404040', - 'TEXT': 'white', - 'INPUT': '#4D4D4D', - 'TEXT_INPUT': 'white', - 'SCROLL': '#707070', - 'BUTTON': ('white', '#004F00'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, + 'LightGreen1': {'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}, - 'LightGreen2': {'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}, + 'DarkGrey': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, - 'DarkGrey1': {'BACKGROUND': '#404040', - 'TEXT': 'white', - 'INPUT': 'white', - 'TEXT_INPUT': 'black', - 'SCROLL': '#707070', - 'BUTTON': ('white', '#004F00'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, + 'LightGreen2': {'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}, - 'DarkBlack': {'BACKGROUND': 'black', - 'TEXT': 'white', - 'INPUT': '#4D4D4D', - 'TEXT_INPUT': 'white', - 'SCROLL': '#707070', - 'BUTTON': ('black', 'white'), - 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, - 'BORDER': 1, - 'SLIDER_DEPTH': 0, - 'PROGRESS_DEPTH': 0}, + 'DarkGrey1': {'BACKGROUND': '#404040', + 'TEXT': 'white', + 'INPUT': 'white', + 'TEXT_INPUT': 'black', + 'SCROLL': '#707070', + 'BUTTON': ('white', '#004F00'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, - 'LightBrown': {'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}, + 'DarkBlack': {'BACKGROUND': 'black', + 'TEXT': 'white', + 'INPUT': '#4D4D4D', + 'TEXT_INPUT': 'white', + 'SCROLL': '#707070', + 'BUTTON': ('black', 'white'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, + 'BORDER': 1, + 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0}, - 'LightBrown1': {'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}, + 'LightBrown': {'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}, - 'DarkBlue1': {'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}, + 'LightBrown1': {'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}, - 'DarkBrown1': {'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}, + 'DarkBlue1': {'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}, - 'DarkBlue2': {'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}, + 'DarkBrown1': {'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}, - 'DarkBrown2': {'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}, + 'DarkBlue2': {'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}, - 'DarkGreen': {'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}, + 'DarkBrown2': {'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}, - 'LightBlue1': {'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}, + 'DarkGreen': {'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}, - 'LightPurple': {'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}, + 'LightBlue1': {'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}, - 'LightBlue2': {'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}, + 'LightPurple': {'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}, - 'LightGreen3': {'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}, + 'LightBlue2': {'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}, - 'DarkBlue3': {'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}, + 'LightGreen3': {'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}, - 'LightGreen4': {'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}, + 'DarkBlue3': {'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}, - 'LightGreen5': {'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}, + 'LightGreen4': {'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}, - 'LightBrown2': {'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}, + 'LightGreen5': {'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}, - 'LightBrown3': {'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}, + 'LightBrown2': {'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}, - 'LightBlue3': {'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}, + 'LightBrown3': {'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}, + 'LightBlue3': {'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}, -################################## End Renamed Original Themes ################################## + ################################## End Renamed Original Themes ################################## + # + 'LightBrown4': {'BACKGROUND': '#d7c79e', 'TEXT': '#a35638', 'INPUT': '#9dab86', 'TEXT_INPUT': '#000000', 'SCROLL': '#a35638', + 'BUTTON': ('white', '#a35638'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#a35638', '#9dab86', '#e08f62', '#d7c79e'], }, + 'DarkTeal': {'BACKGROUND': '#003f5c', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', + 'BUTTON': ('white', '#fb5b5a'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, + 'DarkPurple': {'BACKGROUND': '#472b62', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', + 'BUTTON': ('#FFFFFF', '#472b62'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, + 'LightGreen6': {'BACKGROUND': '#eafbea', 'TEXT': '#1f6650', 'INPUT': '#6f9a8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#1f6650', + 'BUTTON': ('white', '#1f6650'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#1f6650', '#6f9a8d', '#ea5e5e', '#eafbea'], }, + 'DarkGrey2': {'BACKGROUND': '#2b2b28', 'TEXT': '#f8f8f8', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', + 'BUTTON': ('#2b2b28', '#e3b04b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#2b2b28', '#e3b04b', '#f1d6ab', '#f8f8f8'], }, + 'LightBrown6': {'BACKGROUND': '#f9b282', 'TEXT': '#8f4426', 'INPUT': '#de6b35', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8f4426', + 'BUTTON': ('white', '#8f4426'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#8f4426', '#de6b35', '#64ccda', '#f9b282'], }, + 'DarkTeal1': {'BACKGROUND': '#396362', 'TEXT': '#ffe7d1', 'INPUT': '#f6c89f', 'TEXT_INPUT': '#000000', 'SCROLL': '#f6c89f', + 'BUTTON': ('#ffe7d1', '#4b8e8d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'], }, + 'LightBrown7': {'BACKGROUND': '#f6c89f', 'TEXT': '#396362', 'INPUT': '#4b8e8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#396362', + 'BUTTON': ('white', '#396362'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'], }, + 'DarkPurple1': {'BACKGROUND': '#0c093c', 'TEXT': '#fad6d6', 'INPUT': '#eea5f6', 'TEXT_INPUT': '#000000', 'SCROLL': '#eea5f6', + 'BUTTON': ('#FFFFFF', '#df42d1'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#0c093c', '#df42d1', '#eea5f6', '#fad6d6'], }, + 'DarkGrey3': {'BACKGROUND': '#211717', 'TEXT': '#dfddc7', 'INPUT': '#f58b54', 'TEXT_INPUT': '#000000', 'SCROLL': '#f58b54', + 'BUTTON': ('#dfddc7', '#a34a28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, + 'LightBrown8': {'BACKGROUND': '#dfddc7', 'TEXT': '#211717', 'INPUT': '#a34a28', 'TEXT_INPUT': '#dfddc7', 'SCROLL': '#211717', + 'BUTTON': ('#dfddc7', '#a34a28'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, + 'DarkBlue4': {'BACKGROUND': '#494ca2', 'TEXT': '#e3e7f1', 'INPUT': '#c6cbef', 'TEXT_INPUT': '#000000', 'SCROLL': '#c6cbef', + 'BUTTON': ('#FFFFFF', '#8186d5'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#494ca2', '#8186d5', '#c6cbef', '#e3e7f1'], }, + 'LightBlue4': {'BACKGROUND': '#5c94bd', 'TEXT': '#470938', 'INPUT': '#1a3e59', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#470938', + 'BUTTON': ('white', '#470938'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#470938', '#1a3e59', '#5c94bd', '#f2d6eb'], }, + 'DarkTeal2': {'BACKGROUND': '#394a6d', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', + 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, + 'DarkTeal3': {'BACKGROUND': '#3c9d9b', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', + 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, + 'DarkPurple5': {'BACKGROUND': '#730068', 'TEXT': '#f6f078', 'INPUT': '#01d28e', 'TEXT_INPUT': '#000000', 'SCROLL': '#01d28e', + 'BUTTON': ('#f6f078', '#730068'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#730068', '#434982', '#01d28e', '#f6f078'], }, + 'DarkPurple2': {'BACKGROUND': '#202060', 'TEXT': '#b030b0', 'INPUT': '#602080', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#602080', + 'BUTTON': ('white', '#202040'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#202040', '#202060', '#602080', '#b030b0'], }, + 'DarkBlue5': {'BACKGROUND': '#000272', 'TEXT': '#ff6363', 'INPUT': '#a32f80', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#a32f80', + 'BUTTON': ('#FFFFFF', '#341677'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#000272', '#341677', '#a32f80', '#ff6363'], }, + 'LightGrey2': {'BACKGROUND': '#f6f6f6', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', + 'BUTTON': ('#420000', '#d4d7dd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, + 'LightGrey3': {'BACKGROUND': '#eae9e9', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', + 'BUTTON': ('#420000', '#d4d7dd'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, + 'DarkBlue6': {'BACKGROUND': '#01024e', 'TEXT': '#ff6464', 'INPUT': '#8b4367', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8b4367', + 'BUTTON': ('#FFFFFF', '#543864'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#01024e', '#543864', '#8b4367', '#ff6464'], }, + 'DarkBlue7': {'BACKGROUND': '#241663', 'TEXT': '#eae7af', 'INPUT': '#a72693', 'TEXT_INPUT': '#eae7af', 'SCROLL': '#a72693', + 'BUTTON': ('#eae7af', '#160f30'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#160f30', '#241663', '#a72693', '#eae7af'], }, + 'LightBrown9': {'BACKGROUND': '#f6d365', 'TEXT': '#3a1f5d', 'INPUT': '#c83660', 'TEXT_INPUT': '#f6d365', 'SCROLL': '#3a1f5d', + 'BUTTON': ('#f6d365', '#c83660'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3a1f5d', '#c83660', '#e15249', '#f6d365'], }, + 'DarkPurple3': {'BACKGROUND': '#6e2142', 'TEXT': '#ffd692', 'INPUT': '#e16363', 'TEXT_INPUT': '#ffd692', 'SCROLL': '#e16363', + 'BUTTON': ('#ffd692', '#943855'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, + 'LightBrown10': {'BACKGROUND': '#ffd692', 'TEXT': '#6e2142', 'INPUT': '#943855', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6e2142', + 'BUTTON': ('white', '#6e2142'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, + 'DarkPurple4': {'BACKGROUND': '#200f21', 'TEXT': '#f638dc', 'INPUT': '#5a3d5c', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#5a3d5c', + 'BUTTON': ('#FFFFFF', '#382039'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#200f21', '#382039', '#5a3d5c', '#f638dc'], }, + 'LightBlue5': {'BACKGROUND': '#b2fcff', 'TEXT': '#3e64ff', 'INPUT': '#5edfff', 'TEXT_INPUT': '#000000', 'SCROLL': '#3e64ff', + 'BUTTON': ('white', '#3e64ff'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3e64ff', '#5edfff', '#b2fcff', '#ecfcff'], }, + 'DarkTeal4': {'BACKGROUND': '#464159', 'TEXT': '#c7f0db', 'INPUT': '#8bbabb', 'TEXT_INPUT': '#000000', 'SCROLL': '#8bbabb', + 'BUTTON': ('#FFFFFF', '#6c7b95'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'LightTeal': {'BACKGROUND': '#c7f0db', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', + 'BUTTON': ('white', '#464159'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'DarkTeal5': {'BACKGROUND': '#8bbabb', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', + 'BUTTON': ('#c7f0db', '#6c7b95'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, + 'LightGrey4': {'BACKGROUND': '#faf5ef', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', + 'BUTTON': ('#672f2f', '#99b19c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'LightGreen7': {'BACKGROUND': '#99b19c', 'TEXT': '#faf5ef', 'INPUT': '#d7d1c9', 'TEXT_INPUT': '#000000', 'SCROLL': '#d7d1c9', + 'BUTTON': ('#FFFFFF', '#99b19c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'LightGrey5': {'BACKGROUND': '#d7d1c9', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', + 'BUTTON': ('white', '#672f2f'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, + 'DarkBrown3': {'BACKGROUND': '#a0855b', 'TEXT': '#f9f6f2', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', + 'BUTTON': ('white', '#38470b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, + 'LightBrown11': {'BACKGROUND': '#f1d6ab', 'TEXT': '#38470b', 'INPUT': '#a0855b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#38470b', + 'BUTTON': ('#f9f6f2', '#a0855b'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, + 'DarkRed': {'BACKGROUND': '#83142c', 'TEXT': '#f9d276', 'INPUT': '#ad1d45', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#ad1d45', + 'BUTTON': ('#f9d276', '#ad1d45'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#44000d', '#83142c', '#ad1d45', '#f9d276'], }, + 'DarkTeal6': {'BACKGROUND': '#204969', 'TEXT': '#fff7f7', 'INPUT': '#dadada', 'TEXT_INPUT': '#000000', 'SCROLL': '#dadada', + 'BUTTON': ('black', '#fff7f7'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#204969', '#08ffc8', '#dadada', '#fff7f7'], }, + 'DarkBrown4': {'BACKGROUND': '#252525', 'TEXT': '#ff0000', 'INPUT': '#af0404', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#af0404', + 'BUTTON': ('white', '#252525'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#252525', '#414141', '#af0404', '#ff0000'], }, + 'LightYellow': {'BACKGROUND': '#f4ff61', 'TEXT': '#27aa80', 'INPUT': '#32ff6a', 'TEXT_INPUT': '#000000', 'SCROLL': '#27aa80', + 'BUTTON': ('#f4ff61', '#27aa80'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#27aa80', '#32ff6a', '#a8ff3e', '#f4ff61'], }, + 'DarkGreen1': {'BACKGROUND': '#2b580c', 'TEXT': '#fdef96', 'INPUT': '#f7b71d', 'TEXT_INPUT': '#000000', 'SCROLL': '#f7b71d', + 'BUTTON': ('#fdef96', '#2b580c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#2b580c', '#afa939', '#f7b71d', '#fdef96'], }, -# - 'LightBrown4': {'BACKGROUND': '#d7c79e', 'TEXT': '#a35638', 'INPUT': '#9dab86', 'TEXT_INPUT': '#000000', 'SCROLL': '#a35638', 'BUTTON': ('white', '#a35638'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#a35638', '#9dab86', '#e08f62', '#d7c79e'], }, - 'DarkTeal': {'BACKGROUND': '#003f5c', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', 'BUTTON': ('white', '#fb5b5a'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, - 'DarkPurple': {'BACKGROUND': '#472b62', 'TEXT': '#fb5b5a', 'INPUT': '#bc4873', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#bc4873', 'BUTTON': ('#FFFFFF', '#472b62'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#003f5c', '#472b62', '#bc4873', '#fb5b5a'], }, - 'LightGreen6': {'BACKGROUND': '#eafbea', 'TEXT': '#1f6650', 'INPUT': '#6f9a8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#1f6650', 'BUTTON': ('white', '#1f6650'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#1f6650', '#6f9a8d', '#ea5e5e', '#eafbea'], }, - 'DarkGrey2': {'BACKGROUND': '#2b2b28', 'TEXT': '#f8f8f8', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', 'BUTTON': ('#2b2b28', '#e3b04b'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#2b2b28', '#e3b04b', '#f1d6ab', '#f8f8f8'], }, - 'LightBrown6': {'BACKGROUND': '#f9b282', 'TEXT': '#8f4426', 'INPUT': '#de6b35', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8f4426', 'BUTTON': ('white', '#8f4426'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#8f4426', '#de6b35', '#64ccda', '#f9b282'], }, - 'DarkTeal1': {'BACKGROUND': '#396362', 'TEXT': '#ffe7d1', 'INPUT': '#f6c89f', 'TEXT_INPUT': '#000000', 'SCROLL': '#f6c89f', - 'BUTTON': ('#ffe7d1', '#4b8e8d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'],}, - 'LightBrown7': {'BACKGROUND': '#f6c89f', 'TEXT': '#396362', 'INPUT': '#4b8e8d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#396362', - 'BUTTON': ('white', '#396362'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#396362', '#4b8e8d', '#f6c89f', '#ffe7d1'],}, - 'DarkPurple1': {'BACKGROUND': '#0c093c', 'TEXT': '#fad6d6', 'INPUT': '#eea5f6', 'TEXT_INPUT': '#000000', 'SCROLL': '#eea5f6', 'BUTTON': ('#FFFFFF', '#df42d1'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#0c093c', '#df42d1', '#eea5f6', '#fad6d6'], }, - 'DarkGrey3': {'BACKGROUND': '#211717', 'TEXT': '#dfddc7', 'INPUT': '#f58b54', 'TEXT_INPUT': '#000000', 'SCROLL': '#f58b54', 'BUTTON': ('#dfddc7', '#a34a28'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, - 'LightBrown8': {'BACKGROUND': '#dfddc7', 'TEXT': '#211717', 'INPUT': '#a34a28', 'TEXT_INPUT': '#dfddc7', 'SCROLL': '#211717', 'BUTTON': ('#dfddc7', '#a34a28'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#211717', '#a34a28', '#f58b54', '#dfddc7'], }, - 'DarkBlue4': {'BACKGROUND': '#494ca2', 'TEXT': '#e3e7f1', 'INPUT': '#c6cbef', 'TEXT_INPUT': '#000000', 'SCROLL': '#c6cbef', 'BUTTON': ('#FFFFFF', '#8186d5'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#494ca2', '#8186d5', '#c6cbef', '#e3e7f1'],}, - 'LightBlue4': {'BACKGROUND': '#5c94bd', 'TEXT': '#470938', 'INPUT': '#1a3e59', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#470938', 'BUTTON': ('white', '#470938'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#470938', '#1a3e59', '#5c94bd', '#f2d6eb'],}, - 'DarkTeal2': {'BACKGROUND': '#394a6d', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', - 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'],}, - 'DarkTeal3': {'BACKGROUND': '#3c9d9b', 'TEXT': '#c0ffb3', 'INPUT': '#52de97', 'TEXT_INPUT': '#000000', 'SCROLL': '#52de97', - 'BUTTON': ('#c0ffb3', '#394a6d'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#394a6d', '#3c9d9b', '#52de97', '#c0ffb3'], }, - 'DarkPurple5': {'BACKGROUND': '#730068', 'TEXT': '#f6f078', 'INPUT': '#01d28e', 'TEXT_INPUT': '#000000', 'SCROLL': '#01d28e', 'BUTTON': ('#f6f078', '#730068'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#730068', '#434982', '#01d28e', '#f6f078'],}, - 'DarkPurple2': {'BACKGROUND': '#202060', 'TEXT': '#b030b0', 'INPUT': '#602080', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#602080', 'BUTTON': ('white', '#202040'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#202040', '#202060', '#602080', '#b030b0'], }, - 'DarkBlue5': {'BACKGROUND': '#000272', 'TEXT': '#ff6363', 'INPUT': '#a32f80', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#a32f80', 'BUTTON': ('#FFFFFF', '#341677'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#000272', '#341677', '#a32f80', '#ff6363'], }, - 'LightGrey2': {'BACKGROUND': '#f6f6f6', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', 'BUTTON': ('#420000', '#d4d7dd'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'],}, - 'LightGrey3': {'BACKGROUND': '#eae9e9', 'TEXT': '#420000', 'INPUT': '#d4d7dd', 'TEXT_INPUT': '#420000', 'SCROLL': '#420000', 'BUTTON': ('#420000', '#d4d7dd'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#420000', '#d4d7dd', '#eae9e9', '#f6f6f6'], }, - 'DarkBlue6': {'BACKGROUND': '#01024e', 'TEXT': '#ff6464', 'INPUT': '#8b4367', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#8b4367', 'BUTTON': ('#FFFFFF', '#543864'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#01024e', '#543864', '#8b4367', '#ff6464'],}, - 'DarkBlue7': {'BACKGROUND': '#241663', 'TEXT': '#eae7af', 'INPUT': '#a72693', 'TEXT_INPUT': '#eae7af', 'SCROLL': '#a72693', 'BUTTON': ('#eae7af', '#160f30'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#160f30', '#241663', '#a72693', '#eae7af'], }, - 'LightBrown9': {'BACKGROUND': '#f6d365', 'TEXT': '#3a1f5d', 'INPUT': '#c83660', 'TEXT_INPUT': '#f6d365', 'SCROLL': '#3a1f5d', 'BUTTON': ('#f6d365', '#c83660'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#3a1f5d', '#c83660', '#e15249', '#f6d365'], }, - 'DarkPurple3': {'BACKGROUND': '#6e2142', 'TEXT': '#ffd692', 'INPUT': '#e16363', 'TEXT_INPUT': '#ffd692', 'SCROLL': '#e16363', 'BUTTON': ('#ffd692', '#943855'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'], }, - 'LightBrown10': {'BACKGROUND': '#ffd692', 'TEXT': '#6e2142', 'INPUT': '#943855', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6e2142', 'BUTTON': ('white', '#6e2142'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#6e2142', '#943855', '#e16363', '#ffd692'],}, - 'DarkPurple4': {'BACKGROUND': '#200f21', 'TEXT': '#f638dc', 'INPUT': '#5a3d5c', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#5a3d5c', 'BUTTON': ('#FFFFFF', '#382039'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#200f21', '#382039', '#5a3d5c', '#f638dc'],}, - 'LightBlue5': {'BACKGROUND': '#b2fcff', 'TEXT': '#3e64ff', 'INPUT': '#5edfff', 'TEXT_INPUT': '#000000', 'SCROLL': '#3e64ff', 'BUTTON': ('white', '#3e64ff'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#3e64ff', '#5edfff', '#b2fcff', '#ecfcff'], }, - 'DarkTeal4': {'BACKGROUND': '#464159', 'TEXT': '#c7f0db', 'INPUT': '#8bbabb', 'TEXT_INPUT': '#000000', 'SCROLL': '#8bbabb', - 'BUTTON': ('#FFFFFF', '#6c7b95'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, - 'LightTeal': {'BACKGROUND': '#c7f0db', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', - 'BUTTON': ('white', '#464159'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'],}, - 'DarkTeal5': {'BACKGROUND': '#8bbabb', 'TEXT': '#464159', 'INPUT': '#6c7b95', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#464159', - 'BUTTON': ('#c7f0db', '#6c7b95'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#464159', '#6c7b95', '#8bbabb', '#c7f0db'], }, - 'LightGrey4': {'BACKGROUND': '#faf5ef', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', 'BUTTON': ('#672f2f', '#99b19c'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, - 'LightGreen7': {'BACKGROUND': '#99b19c', 'TEXT': '#faf5ef', 'INPUT': '#d7d1c9', 'TEXT_INPUT': '#000000', 'SCROLL': '#d7d1c9', 'BUTTON': ('#FFFFFF', '#99b19c'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'],}, - 'LightGrey5': {'BACKGROUND': '#d7d1c9', 'TEXT': '#672f2f', 'INPUT': '#99b19c', 'TEXT_INPUT': '#672f2f', 'SCROLL': '#672f2f', 'BUTTON': ('white', '#672f2f'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#672f2f', '#99b19c', '#d7d1c9', '#faf5ef'], }, - 'DarkBrown3': {'BACKGROUND': '#a0855b', 'TEXT': '#f9f6f2', 'INPUT': '#f1d6ab', 'TEXT_INPUT': '#000000', 'SCROLL': '#f1d6ab', 'BUTTON': ('white', '#38470b'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'], }, - 'LightBrown11': {'BACKGROUND': '#f1d6ab', 'TEXT': '#38470b', 'INPUT': '#a0855b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#38470b', 'BUTTON': ('#f9f6f2', '#a0855b'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#38470b', '#a0855b', '#f1d6ab', '#f9f6f2'],}, - 'DarkRed': {'BACKGROUND': '#83142c', 'TEXT': '#f9d276', 'INPUT': '#ad1d45', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#ad1d45', 'BUTTON': ('#f9d276', '#ad1d45'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#44000d', '#83142c', '#ad1d45', '#f9d276'], }, - 'DarkTeal6': {'BACKGROUND': '#204969', 'TEXT': '#fff7f7', 'INPUT': '#dadada', 'TEXT_INPUT': '#000000', 'SCROLL': '#dadada', - 'BUTTON': ('black', '#fff7f7'), 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#204969', '#08ffc8', '#dadada', '#fff7f7'],}, - 'DarkBrown4': {'BACKGROUND': '#252525', 'TEXT': '#ff0000', 'INPUT': '#af0404', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#af0404', 'BUTTON': ('white', '#252525'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#252525', '#414141', '#af0404', '#ff0000'], }, - 'LightYellow': {'BACKGROUND': '#f4ff61', 'TEXT': '#27aa80', 'INPUT': '#32ff6a', 'TEXT_INPUT': '#000000', 'SCROLL': '#27aa80', 'BUTTON': ('#f4ff61', '#27aa80'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#27aa80', '#32ff6a', '#a8ff3e', '#f4ff61'],}, - 'DarkGreen1': {'BACKGROUND': '#2b580c', 'TEXT': '#fdef96', 'INPUT': '#f7b71d', 'TEXT_INPUT': '#000000', 'SCROLL': '#f7b71d', 'BUTTON': ('#fdef96', '#2b580c'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#2b580c', '#afa939', '#f7b71d', '#fdef96'], }, - 'LightGreen8': {'BACKGROUND': '#c8dad3', 'TEXT': '#63707e', 'INPUT': '#93b5b3', 'TEXT_INPUT': '#000000', 'SCROLL': '#63707e', 'BUTTON': ('white', '#63707e'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#63707e', '#93b5b3', '#c8dad3', '#f2f6f5'], }, - 'DarkTeal7': {'BACKGROUND': '#248ea9', 'TEXT': '#fafdcb', 'INPUT': '#aee7e8', 'TEXT_INPUT': '#000000', 'SCROLL': '#aee7e8', 'BUTTON': ('black', '#fafdcb'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#248ea9', '#28c3d4', '#aee7e8', '#fafdcb'],}, -'DarkBlue8': {'BACKGROUND': '#454d66', 'TEXT': '#d9d872', 'INPUT': '#58b368', 'TEXT_INPUT': '#000000', 'SCROLL': '#58b368', - 'BUTTON': ('black', '#009975'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#009975', '#454d66', '#58b368', '#d9d872'], }, - 'DarkBlue9': {'BACKGROUND': '#263859', 'TEXT': '#ff6768', 'INPUT': '#6b778d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6b778d', 'BUTTON': ('#ff6768', '#263859'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#17223b', '#263859', '#6b778d', '#ff6768'], }, - 'DarkBlue10': {'BACKGROUND': '#0028ff', 'TEXT': '#f1f4df', 'INPUT': '#10eaf0', 'TEXT_INPUT': '#000000', 'SCROLL': '#10eaf0', 'BUTTON': ('#f1f4df', '#24009c'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#24009c', '#0028ff', '#10eaf0', '#f1f4df'],}, - 'DarkBlue11': {'BACKGROUND': '#6384b3', 'TEXT': '#e6f0b6', 'INPUT': '#b8e9c0', 'TEXT_INPUT': '#000000', 'SCROLL': '#b8e9c0', 'BUTTON': ('#e6f0b6', '#684949'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#684949', '#6384b3', '#b8e9c0', '#e6f0b6'], }, + 'LightGreen8': {'BACKGROUND': '#c8dad3', 'TEXT': '#63707e', 'INPUT': '#93b5b3', 'TEXT_INPUT': '#000000', 'SCROLL': '#63707e', + 'BUTTON': ('white', '#63707e'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#63707e', '#93b5b3', '#c8dad3', '#f2f6f5'], }, + + 'DarkTeal7': {'BACKGROUND': '#248ea9', 'TEXT': '#fafdcb', 'INPUT': '#aee7e8', 'TEXT_INPUT': '#000000', 'SCROLL': '#aee7e8', + 'BUTTON': ('black', '#fafdcb'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#248ea9', '#28c3d4', '#aee7e8', '#fafdcb'], }, + 'DarkBlue8': {'BACKGROUND': '#454d66', 'TEXT': '#d9d872', 'INPUT': '#58b368', 'TEXT_INPUT': '#000000', 'SCROLL': '#58b368', + 'BUTTON': ('black', '#009975'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#009975', '#454d66', '#58b368', '#d9d872'], }, + 'DarkBlue9': {'BACKGROUND': '#263859', 'TEXT': '#ff6768', 'INPUT': '#6b778d', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#6b778d', + 'BUTTON': ('#ff6768', '#263859'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#17223b', '#263859', '#6b778d', '#ff6768'], }, + 'DarkBlue10': {'BACKGROUND': '#0028ff', 'TEXT': '#f1f4df', 'INPUT': '#10eaf0', 'TEXT_INPUT': '#000000', 'SCROLL': '#10eaf0', + 'BUTTON': ('#f1f4df', '#24009c'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#24009c', '#0028ff', '#10eaf0', '#f1f4df'], }, + 'DarkBlue11': {'BACKGROUND': '#6384b3', 'TEXT': '#e6f0b6', 'INPUT': '#b8e9c0', 'TEXT_INPUT': '#000000', 'SCROLL': '#b8e9c0', + 'BUTTON': ('#e6f0b6', '#684949'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#684949', '#6384b3', '#b8e9c0', '#e6f0b6'], }, + + 'DarkTeal8': {'BACKGROUND': '#71a0a5', 'TEXT': '#212121', 'INPUT': '#665c84', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#212121', + 'BUTTON': ('#fab95b', '#665c84'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#212121', '#665c84', '#71a0a5', '#fab95b']}, + 'DarkRed1': {'BACKGROUND': '#c10000', 'TEXT': '#eeeeee', 'INPUT': '#dedede', 'TEXT_INPUT': '#000000', 'SCROLL': '#dedede', + 'BUTTON': ('#c10000', '#eeeeee'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#c10000', '#ff4949', '#dedede', '#eeeeee'], }, + 'LightBrown5': {'BACKGROUND': '#fff591', 'TEXT': '#e41749', 'INPUT': '#f5587b', 'TEXT_INPUT': '#000000', 'SCROLL': '#e41749', + 'BUTTON': ('#fff591', '#e41749'), + 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#e41749', '#f5587b', '#ff8a5c', '#fff591']}, + 'LightGreen9': {'BACKGROUND': '#f1edb3', 'TEXT': '#3b503d', 'INPUT': '#4a746e', 'TEXT_INPUT': '#f1edb3', 'SCROLL': '#3b503d', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}, + 'DarkGreen2': {'BACKGROUND': '#3b503d', 'TEXT': '#f1edb3', 'INPUT': '#c8cf94', 'TEXT_INPUT': '#000000', 'SCROLL': '#c8cf94', + 'BUTTON': ('#f1edb3', '#3b503d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + 'COLOR_LIST': ['#3b503d', '#4a746e', '#c8cf94', '#f1edb3'], 'DESCRIPTION': ['Green', 'Turquoise', 'Yellow']}, + 'LightGray1': {'BACKGROUND': '#f2f2f2', 'TEXT': '#222831', 'INPUT': '#393e46', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#222831', + 'BUTTON': ('#f2f2f2', '#222831'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#222831', '#393e46', '#f96d00', '#f2f2f2'], + 'DESCRIPTION': ['Black', 'Grey', 'Orange', 'Grey', 'Autumn']}, + 'DarkGrey4': {'BACKGROUND': '#52524e', 'TEXT': '#e9e9e5', 'INPUT': '#d4d6c8', 'TEXT_INPUT': '#000000', 'SCROLL': '#d4d6c8', + 'BUTTON': ('#FFFFFF', '#9a9b94'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#52524e', '#9a9b94', '#d4d6c8', '#e9e9e5'], + 'DESCRIPTION': ['Grey', 'Pastel', 'Winter']}, + 'DarkBlue12': {'BACKGROUND': '#324e7b', 'TEXT': '#f8f8f8', 'INPUT': '#86a6df', 'TEXT_INPUT': '#000000', 'SCROLL': '#86a6df', + 'BUTTON': ('#FFFFFF', '#5068a9'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#324e7b', '#5068a9', '#86a6df', '#f8f8f8'], + 'DESCRIPTION': ['Blue', 'Grey', 'Cold', 'Winter']}, + 'DarkPurple6': {'BACKGROUND': '#070739', 'TEXT': '#e1e099', 'INPUT': '#c327ab', 'TEXT_INPUT': '#e1e099', 'SCROLL': '#c327ab', + 'BUTTON': ('#e1e099', '#521477'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#070739', '#521477', '#c327ab', '#e1e099'], + 'DESCRIPTION': ['Black', 'Purple', 'Yellow', 'Dark']}, + 'DarkBlue13': {'BACKGROUND': '#203562', 'TEXT': '#e3e8f8', 'INPUT': '#c0c5cd', 'TEXT_INPUT': '#000000', 'SCROLL': '#c0c5cd', + 'BUTTON': ('#FFFFFF', '#3e588f'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#203562', '#3e588f', '#c0c5cd', '#e3e8f8'], + 'DESCRIPTION': ['Blue', 'Grey', 'Wedding', 'Cold']}, + 'DarkBrown5': {'BACKGROUND': '#3c1b1f', 'TEXT': '#f6e1b5', 'INPUT': '#e2bf81', 'TEXT_INPUT': '#000000', 'SCROLL': '#e2bf81', + 'BUTTON': ('#3c1b1f', '#f6e1b5'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3c1b1f', '#b21e4b', '#e2bf81', '#f6e1b5'], + 'DESCRIPTION': ['Brown', 'Red', 'Yellow', 'Warm']}, + 'DarkGreen3': {'BACKGROUND': '#062121', 'TEXT': '#eeeeee', 'INPUT': '#e4dcad', 'TEXT_INPUT': '#000000', 'SCROLL': '#e4dcad', + 'BUTTON': ('#eeeeee', '#181810'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#062121', '#181810', '#e4dcad', '#eeeeee'], + 'DESCRIPTION': ['Black', 'Black', 'Brown', 'Grey']}, + 'DarkBlack1': {'BACKGROUND': '#181810', 'TEXT': '#eeeeee', 'INPUT': '#e4dcad', 'TEXT_INPUT': '#000000', 'SCROLL': '#e4dcad', + 'BUTTON': ('white', '#062121'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#062121', '#181810', '#e4dcad', '#eeeeee'], + 'DESCRIPTION': ['Black', 'Black', 'Brown', 'Grey']}, + 'DarkGrey5': {'BACKGROUND': '#343434', 'TEXT': '#f3f3f3', 'INPUT': '#e9dcbe', 'TEXT_INPUT': '#000000', 'SCROLL': '#e9dcbe', + 'BUTTON': ('#FFFFFF', '#8e8b82'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#343434', '#8e8b82', '#e9dcbe', '#f3f3f3'], 'DESCRIPTION': ['Grey', 'Brown']}, + 'LightBrown12': {'BACKGROUND': '#8e8b82', 'TEXT': '#f3f3f3', 'INPUT': '#e9dcbe', 'TEXT_INPUT': '#000000', 'SCROLL': '#e9dcbe', + 'BUTTON': ('#f3f3f3', '#8e8b82'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#343434', '#8e8b82', '#e9dcbe', '#f3f3f3'], 'DESCRIPTION': ['Grey', 'Brown']}, + 'DarkTeal9': {'BACKGROUND': '#13445a', 'TEXT': '#fef4e8', 'INPUT': '#446878', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#446878', + 'BUTTON': ('#fef4e8', '#446878'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#13445a', '#970747', '#446878', '#fef4e8'], + 'DESCRIPTION': ['Red', 'Grey', 'Blue', 'Wedding', 'Retro']}, + 'DarkBlue14': {'BACKGROUND': '#21273d', 'TEXT': '#f1f6f8', 'INPUT': '#b9d4f1', 'TEXT_INPUT': '#000000', 'SCROLL': '#b9d4f1', + 'BUTTON': ('#FFFFFF', '#6a759b'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#21273d', '#6a759b', '#b9d4f1', '#f1f6f8'], + 'DESCRIPTION': ['Blue', 'Black', 'Grey', 'Cold', 'Winter']}, + 'LightBlue6': {'BACKGROUND': '#f1f6f8', 'TEXT': '#21273d', 'INPUT': '#6a759b', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#21273d', + 'BUTTON': ('#f1f6f8', '#6a759b'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#21273d', '#6a759b', '#b9d4f1', '#f1f6f8'], + 'DESCRIPTION': ['Blue', 'Black', 'Grey', 'Cold', 'Winter']}, + 'DarkGreen4': {'BACKGROUND': '#044343', 'TEXT': '#e4e4e4', 'INPUT': '#045757', 'TEXT_INPUT': '#e4e4e4', 'SCROLL': '#045757', + 'BUTTON': ('#e4e4e4', '#045757'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#222222', '#044343', '#045757', '#e4e4e4'], + 'DESCRIPTION': ['Black', 'Turquoise', 'Grey', 'Dark']}, + 'DarkGreen5': {'BACKGROUND': '#1b4b36', 'TEXT': '#e0e7f1', 'INPUT': '#aebd77', 'TEXT_INPUT': '#000000', 'SCROLL': '#aebd77', + 'BUTTON': ('#FFFFFF', '#538f6a'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#1b4b36', '#538f6a', '#aebd77', '#e0e7f1'], 'DESCRIPTION': ['Green', 'Grey']}, + 'DarkTeal10': {'BACKGROUND': '#0d3446', 'TEXT': '#d8dfe2', 'INPUT': '#71adb5', 'TEXT_INPUT': '#000000', 'SCROLL': '#71adb5', + 'BUTTON': ('#FFFFFF', '#176d81'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#0d3446', '#176d81', '#71adb5', '#d8dfe2'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter', 'Cold']}, + 'DarkGrey6': {'BACKGROUND': '#3e3e3e', 'TEXT': '#ededed', 'INPUT': '#68868c', 'TEXT_INPUT': '#ededed', 'SCROLL': '#68868c', + 'BUTTON': ('#FFFFFF', '#405559'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3e3e3e', '#405559', '#68868c', '#ededed'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter']}, + 'DarkTeal11': {'BACKGROUND': '#405559', 'TEXT': '#ededed', 'INPUT': '#68868c', 'TEXT_INPUT': '#ededed', 'SCROLL': '#68868c', + 'BUTTON': ('#ededed', '#68868c'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#3e3e3e', '#405559', '#68868c', '#ededed'], + 'DESCRIPTION': ['Grey', 'Turquoise', 'Winter']}, + 'LightBlue7': {'BACKGROUND': '#9ed0e0', 'TEXT': '#19483f', 'INPUT': '#5c868e', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#19483f', + 'BUTTON': ('white', '#19483f'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#19483f', '#5c868e', '#ff6a38', '#9ed0e0'], + 'DESCRIPTION': ['Orange', 'Blue', 'Turquoise']}, + 'LightGreen10': {'BACKGROUND': '#d8ebb5', 'TEXT': '#205d67', 'INPUT': '#639a67', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#205d67', + 'BUTTON': ('#d8ebb5', '#205d67'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#205d67', '#639a67', '#d9bf77', '#d8ebb5'], + 'DESCRIPTION': ['Blue', 'Green', 'Brown', 'Vintage']}, + 'DarkBlue15': {'BACKGROUND': '#151680', 'TEXT': '#f1fea4', 'INPUT': '#375fc0', 'TEXT_INPUT': '#f1fea4', 'SCROLL': '#375fc0', + 'BUTTON': ('#f1fea4', '#1c44ac'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#151680', '#1c44ac', '#375fc0', '#f1fea4'], + 'DESCRIPTION': ['Blue', 'Yellow', 'Cold']}, + 'DarkBlue16': {'BACKGROUND': '#1c44ac', 'TEXT': '#f1fea4', 'INPUT': '#375fc0', 'TEXT_INPUT': '#f1fea4', 'SCROLL': '#375fc0', + 'BUTTON': ('#f1fea4', '#151680'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#151680', '#1c44ac', '#375fc0', '#f1fea4'], + 'DESCRIPTION': ['Blue', 'Yellow', 'Cold']}, + 'DarkTeal12': {'BACKGROUND': '#004a7c', 'TEXT': '#fafafa', 'INPUT': '#e8f1f5', 'TEXT_INPUT': '#000000', 'SCROLL': '#e8f1f5', + 'BUTTON': ('#fafafa', '#005691'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#004a7c', '#005691', '#e8f1f5', '#fafafa'], + 'DESCRIPTION': ['Grey', 'Blue', 'Cold', 'Winter']}, + 'LightBrown13': {'BACKGROUND': '#ebf5ee', 'TEXT': '#921224', 'INPUT': '#bdc6b8', 'TEXT_INPUT': '#921224', 'SCROLL': '#921224', + 'BUTTON': ('white', '#921224'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#921224', '#bdc6b8', '#bce0da', '#ebf5ee'], + 'DESCRIPTION': ['Red', 'Blue', 'Grey', 'Vintage', 'Wedding']}, + 'DarkBlue17': {'BACKGROUND': '#21294c', 'TEXT': '#f9f2d7', 'INPUT': '#f2dea8', 'TEXT_INPUT': '#000000', 'SCROLL': '#f2dea8', + 'BUTTON': ('#f9f2d7', '#141829'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#141829', '#21294c', '#f2dea8', '#f9f2d7'], + 'DESCRIPTION': ['Black', 'Blue', 'Yellow']}, + 'DarkBrown6': {'BACKGROUND': '#785e4d', 'TEXT': '#f2eee3', 'INPUT': '#baaf92', 'TEXT_INPUT': '#000000', 'SCROLL': '#baaf92', + 'BUTTON': ('white', '#785e4d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#785e4d', '#ff8426', '#baaf92', '#f2eee3'], + 'DESCRIPTION': ['Grey', 'Brown', 'Orange', 'Autumn']}, + 'DarkGreen6': {'BACKGROUND': '#5c715e', 'TEXT': '#f2f9f1', 'INPUT': '#ddeedf', 'TEXT_INPUT': '#000000', 'SCROLL': '#ddeedf', + 'BUTTON': ('#f2f9f1', '#5c715e'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#5c715e', '#b6cdbd', '#ddeedf', '#f2f9f1'], + 'DESCRIPTION': ['Grey', 'Green', 'Vintage']}, + 'DarkGrey7': {'BACKGROUND': '#4b586e', 'TEXT': '#dddddd', 'INPUT': '#574e6d', 'TEXT_INPUT': '#dddddd', 'SCROLL': '#574e6d', + 'BUTTON': ('#dddddd', '#43405d'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#43405d', '#4b586e', '#574e6d', '#dddddd'], + 'DESCRIPTION': ['Grey', 'Winter', 'Cold']}, + 'DarkRed2': {'BACKGROUND': '#ab1212', 'TEXT': '#f6e4b5', 'INPUT': '#cd3131', 'TEXT_INPUT': '#f6e4b5', 'SCROLL': '#cd3131', + 'BUTTON': ('#f6e4b5', '#ab1212'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#ab1212', '#1fad9f', '#cd3131', '#f6e4b5'], + 'DESCRIPTION': ['Turquoise', 'Red', 'Yellow']}, + 'LightGrey6': {'BACKGROUND': '#e3e3e3', 'TEXT': '#233142', 'INPUT': '#455d7a', 'TEXT_INPUT': '#e3e3e3', 'SCROLL': '#233142', + 'BUTTON': ('#e3e3e3', '#455d7a'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, 'COLOR_LIST': ['#233142', '#455d7a', '#f95959', '#e3e3e3'], + 'DESCRIPTION': ['Black', 'Blue', 'Red', 'Grey']}, + 'HotDogStand': {'BACKGROUND': 'red', 'TEXT': 'yellow', 'INPUT': 'yellow', 'TEXT_INPUT': 'black', 'SCROLL': 'yellow', + 'BUTTON': ('red', 'yellow'), 'PROGRESS': DEFAULT_PROGRESS_BAR_COLOR, 'BORDER': 1, 'SLIDER_DEPTH': 0, + 'PROGRESS_DEPTH': 0, + }, + } - 'DarkTeal8': {'BACKGROUND': '#71a0a5', 'TEXT': '#212121', 'INPUT': '#665c84', 'TEXT_INPUT': '#FFFFFF', 'SCROLL': '#212121', 'BUTTON': ('#fab95b', '#665c84'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#212121', '#665c84', '#71a0a5', '#fab95b']}, - 'DarkRed1': {'BACKGROUND': '#c10000', 'TEXT': '#eeeeee', 'INPUT': '#dedede', 'TEXT_INPUT': '#000000', 'SCROLL': '#dedede', 'BUTTON': ('#c10000', '#eeeeee'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#c10000', '#ff4949', '#dedede', '#eeeeee'],}, - 'LightBrown5': {'BACKGROUND': '#fff591', 'TEXT': '#e41749', 'INPUT': '#f5587b', 'TEXT_INPUT': '#000000', 'SCROLL': '#e41749', 'BUTTON': ('#fff591', '#e41749'), - 'PROGRESS': ('#01826B', '#D0D0D0'), 'BORDER': 1, 'SLIDER_DEPTH': 0, 'PROGRESS_DEPTH': 0, - 'COLOR_LIST': ['#e41749', '#f5587b', '#ff8a5c', '#fff591']} - } def ListOfLookAndFeelValues(): """ @@ -10622,6 +11003,90 @@ def ListOfLookAndFeelValues(): return sorted(list(LOOK_AND_FEEL_TABLE.keys())) +def theme(new_theme=None): + """ + Sets / Gets the current Theme. If none is specified then returns the current theme. + This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + + :param new_theme: (str) the new theme name to use + :return: (str) the currently selected theme + """ + if new_theme is not None: + change_look_and_feel(new_theme) + return CURRENT_LOOK_AND_FEEL + + +def theme_background_color(): + """ + Returns the background color specified by the current color theme + + :return: (str) - color string of the background color defined by current theme + """ + return LOOK_AND_FEEL_TABLE[theme()]['BACKGROUND'] + + +def theme_text_color(): + """ + Returns the text color specified by the current color theme + + :return: (str) - color string of the text color defined by current theme + """ + return LOOK_AND_FEEL_TABLE[theme()]['TEXT'] + + +def theme_input_background_color(): + """ + Returns the input element background color specified by the current color theme + + :return: (str) - color string of the input element background color defined by current theme + """ + return LOOK_AND_FEEL_TABLE[theme()]['INPUT'] + + +def theme_input_text_color(): + """ + Returns the input element text color specified by the current color theme + + :return: (str) - color string of the input element text color defined by current theme + """ + return LOOK_AND_FEEL_TABLE[theme()]['TEXT_INPUT'] + + +def theme_text_color(): + """ + Returns the text color specified by the current color theme + + :return: (str) - color string of the text color defined by current theme + """ + return LOOK_AND_FEEL_TABLE[theme()]['TEXT'] + + +def theme_button_color(): + """ + Returns the button color specified by the current color theme + + :return: Tuple[str, str] - TUPLE with color strings of the button color defined by current theme (button text color, button background color) + """ + return LOOK_AND_FEEL_TABLE[theme()]['BUTTON'] + + +def theme_list(): + """ + Returns a sorted list of the currently available color themes + + :return: List[str] - A sorted list of the currently available color themes + """ + return list_of_look_and_feel_values() + + +def theme_previewer(columns=12): + """ + Show a window with all of the color themes - takes a while so be patient + + :param columns: (int) number of themes in a single row + """ + preview_all_look_and_feel_themes(columns) + def ChangeLookAndFeel(index, force=False): """ Change the "color scheme" of all future PySimpleGUI Windows. @@ -10629,35 +11094,6 @@ def ChangeLookAndFeel(index, force=False): There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. The original list was (prior to a major rework and renaming)... these names still work... - SystemDefault - SystemDefaultForReal - Material1 - Material2 - Reddit - Topanga - GreenTan - Dark - LightGreen - Dark2 - Black - Tan - TanBlue - DarkTanBlue - DarkAmber - DarkBlue - Reds - Green - BluePurple - Purple - BlueMono - GreenMono - BrownBlue - BrightColors - NeutralBlue - Kayak - SandyBeach - TealMono - In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: The "Formula" is: ["Dark" or "Light"] Color Number @@ -10665,10 +11101,12 @@ def ChangeLookAndFeel(index, force=False): The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. Default = The default settings (only button color is different than system default) Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - :param index: (str) the name of the index into the Look and Feel table - :param force: (bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors + :param index: (str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy") + :param force: (bool) no longer used """ + global CURRENT_LOOK_AND_FEEL + # if sys.platform.startswith('darwin') and not force: # print('*** Changing look and feel is not supported on Mac platform ***') # return @@ -10691,16 +11129,25 @@ def ChangeLookAndFeel(index, force=False): elif opt2 in lf_values: ix = lf_values.index(opt2) else: - ix = randint(0,len(lf_values)) + ix = randint(0, len(lf_values) - 1) print('** Warning - {} Look and Feel value not valid. Change your ChangeLookAndFeel call. **'.format(index)) print('valid values are', list_of_look_and_feel_values()) print('Instead, please enjoy a random Theme named {}'.format(list_of_look_and_feel_values()[ix])) selection = list_of_look_and_feel_values()[ix] - + CURRENT_LOOK_AND_FEEL = selection try: colors = LOOK_AND_FEEL_TABLE[selection] + # Color the progress bar using button background and input colors...unless they're the same + if colors['PROGRESS'] != COLOR_SYSTEM_DEFAULT: + if colors['BUTTON'][1] != colors['INPUT'] and colors['BUTTON'][1] != colors['BACKGROUND']: + colors['PROGRESS'] = colors['BUTTON'][1], colors['INPUT'] + else: # if the same, then use text input on top of input color + colors['PROGRESS'] = (colors['TEXT_INPUT'], colors['INPUT']) + else: + colors['PROGRESS'] = DEFAULT_PROGRESS_BAR_COLOR_OFFICIAL + # call to change all the colors SetOptions(background_color=colors['BACKGROUND'], text_element_background_color=colors['BACKGROUND'], element_background_color=colors['BACKGROUND'], @@ -10720,18 +11167,23 @@ def ChangeLookAndFeel(index, force=False): print('valid values are', list_of_look_and_feel_values()) -def preview_all_look_and_feel_themes(): +def preview_all_look_and_feel_themes(columns=12): """ Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + :param columns: (int) The number of themes to display per row """ - web=False + + # Show a "splash" type message so the user doesn't give up waiting + popup_quick_message('Hang on for a moment, this will take a bit to create....', background_color='red', text_color='white', auto_close=True, non_blocking=True) + + web = False WINDOW_BACKGROUND = 'lightblue' def sample_layout(): - return [[Text('Text element'), InputText('Input data here', size=(15, 1))], - [Button('Ok'), Button('Cancel'), Slider((1, 10), orientation='h', size=(10, 15))]] + return [[Text('Text element'), InputText('Input data here', size=(10, 1))], + [Button('Ok'), Button('Cancel'), Slider((1, 10), orientation='h', size=(5, 15))]] layout = [[Text('Here is a complete list of themes', font='Default 18', background_color=WINDOW_BACKGROUND)]] @@ -10740,7 +11192,7 @@ def preview_all_look_and_feel_themes(): row = [] for count, theme in enumerate(names): change_look_and_feel(theme) - if not count % 9: + if not count % columns: layout += [row] row = [] row += [Frame(theme, sample_layout() if not web else [[T(theme)]] + sample_layout())] @@ -10792,7 +11244,6 @@ def test_func(parm): return 'my return' - ###### # # #### ##### # # ##### #### # # # # # # # # # # # @@ -10807,7 +11258,9 @@ def test_func(parm): # ------------------------------------------------------------------------------------------------------------------ # # ----------------------------------- The mighty Popup! ------------------------------------------------------------ # -def Popup(*args, title=None, 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=None, line_width=None, font=None, no_titlebar=False, grab_anywhere=False, keep_on_top=False, location=(None, None)): +def Popup(*args, title=None, 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=None, line_width=None, font=None, no_titlebar=False, grab_anywhere=False, + keep_on_top=False, location=(None, None)): """ Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the "print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. @@ -10865,7 +11318,7 @@ def Popup(*args, title=None, button_color=None, background_color=None, text_colo if non_blocking: PopupButton = DummyButton # important to use or else button will close other windows too! else: - PopupButton = CloseButton + PopupButton = Button # show either an OK or Yes/No depending on paramater if custom_text != (None, None): if type(custom_text) is not tuple: @@ -10901,6 +11354,7 @@ def Popup(*args, title=None, button_color=None, background_color=None, text_colo button, values = window.Read(timeout=0) else: button, values = window.Read() + window.close(); del window return button @@ -10919,10 +11373,10 @@ def MsgBox(*args): raise DeprecationWarning('MsgBox is no longer supported... change your call to Popup') - # ======================== Scrolled Text Box =====# # ===================================================# -def PopupScrolled(*args, title=None, button_color=None, background_color=None, text_color=None, yes_no=False, auto_close=False, auto_close_duration=None, size=(None, None), location=(None, None),non_blocking=False,no_titlebar=False, grab_anywhere=False, keep_on_top=False, font=None): +def PopupScrolled(*args, title=None, button_color=None, background_color=None, text_color=None, yes_no=False, auto_close=False, auto_close_duration=None, + size=(None, None), location=(None, None), non_blocking=False, no_titlebar=False, grab_anywhere=False, keep_on_top=False, font=None): """ Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you want, just like a print statement. @@ -10964,7 +11418,7 @@ def PopupScrolled(*args, title=None, button_color=None, background_color=None, window.AddRow(Multiline(complete_output, size=(max_line_width, height_computed), background_color=background_color, text_color=text_color)) pad = max_line_total - 15 if max_line_total > 15 else 1 # show either an OK or Yes/No depending on paramater - button = DummyButton if non_blocking else CloseButton + button = DummyButton if non_blocking else Button if yes_no: window.AddRow(Text('', size=(pad, 1), auto_size_text=False, background_color=background_color), button('Yes'), button('No')) else: @@ -10975,7 +11429,7 @@ def PopupScrolled(*args, title=None, button_color=None, background_color=None, button, values = window.Read(timeout=0) else: button, values = window.Read() - # window.Close() + window.close(); del window return button @@ -10991,8 +11445,6 @@ ScrolledTextBox = PopupScrolled sprint = ScrolledTextBox - - # --------------------------- PopupNoButtons --------------------------- def PopupNoButtons(*args, title=None, button_color=None, background_color=None, text_color=None, auto_close=False, auto_close_duration=None, non_blocking=False, icon=None, line_width=None, font=None, @@ -11225,10 +11677,10 @@ def PopupError(*args, title=None, button_color=(None, None), background_color=No """ tbutton_color = DEFAULT_ERROR_BUTTON_COLOR if button_color == (None, None) else button_color return Popup(*args, title=title, 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=tbutton_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) + non_blocking=non_blocking, icon=icon, line_width=line_width, button_color=tbutton_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 --------------------------- @@ -11256,10 +11708,10 @@ def PopupCancel(*args, title=None, button_color=None, background_color=None, tex """ return Popup(*args, title=title, 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) + 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 --------------------------- @@ -11286,9 +11738,9 @@ def PopupOK(*args, title=None, button_color=None, background_color=None, text_co :param location: """ return Popup(*args, title=title, 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) + 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 --------------------------- @@ -11422,7 +11874,7 @@ def PopupGetFolder(message, title=None, default_path='', no_window=False, size=( location=location) button, values = window.Read() - window.Close() + window.close(); del window if button != 'Ok': return None else: @@ -11482,7 +11934,7 @@ def PopupGetFile(message, title=None, default_path='', default_extension='', sav # TODO - Macs will not like this code because of the filetypes being used. Need another Darwin check. if save_as: filename = tk.filedialog.asksaveasfilename(filetypes=file_types, - initialdir = initial_folder, + initialdir=initial_folder, defaultextension=default_extension) # show the 'get file' dialog box elif multiple_files: filename = tk.filedialog.askopenfilenames(filetypes=file_types, @@ -11499,7 +11951,7 @@ def PopupGetFile(message, title=None, default_path='', default_extension='', sav Window.hidden_master_root.destroy() Window.hidden_master_root = None if not multiple_files and type(filename) in (tuple, list): - if len(filename): # only if not 0 length, otherwise will get an error + if len(filename): # only if not 0 length, otherwise will get an error filename = filename[0] return filename @@ -11520,7 +11972,7 @@ def PopupGetFile(message, title=None, default_path='', default_extension='', sav no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) button, values = window.Read() - window.Close() + window.close(); del window if button != 'Ok': return None else: @@ -11563,7 +12015,7 @@ def PopupGetText(message, title=None, default_text='', password_char='', size=(N location=location) button, values = window.Read() - window.Close() + window.close(); del window if button != 'Ok': return None else: @@ -11619,7 +12071,7 @@ def PopupAnimated(image_source, message=None, background_color=None, text_color= window = Window.animated_popup_dict[image_source] window.Element('_IMAGE_').UpdateAnimation(image_source, time_between_frames=time_between_frames) - window.Refresh() # call refresh instead of Read to save significant CPU time + window.refresh() # call refresh instead of Read to save significant CPU time ##################################################################################################### @@ -11643,10 +12095,11 @@ WIDTH_LOCALS = 80 NUM_AUTO_WATCH = 9 MAX_LINES_PER_RESULT_FLOATING = 4 -MAX_LINES_PER_RESULT_MAIN = 3 +MAX_LINES_PER_RESULT_MAIN = 3 POPOUT_WINDOW_FONT = 'Sans 8' + class _Debugger(): """ """ @@ -11663,7 +12116,7 @@ class _Debugger(): def __init__(self): """ """ self.watcher_window = None # type: Window - self.popout_window = None # type: Window + self.popout_window = None # type: Window self.local_choices = {} self.myrc = '' self.custom_watch = '' @@ -11671,7 +12124,6 @@ class _Debugger(): self.globals = {} self.popout_choices = {} - # Includes the DUAL PANE (now 2 tabs)! Don't forget REPL is there too! def _build_main_debugger_window(self, location=(None, None)): """ @@ -11698,7 +12150,7 @@ class _Debugger(): InVar('_VAR2_'), ] interactive_frame = [[T('>>> '), In(size=(83, 1), key='_REPL_', - tooltip='Type in any "expression" or "statement"\n and it will be disaplayed below.\nPress RETURN KEY instead of "Go"\nbutton for faster use'), + tooltip='Type in any "expression" or "statement"\n and it will be disaplayed below.\nPress RETURN KEY instead of "Go"\nbutton for faster use'), B('Go', bind_return_key=True, visible=True)], [Multiline(size=(93, 26), key='_OUTPUT_', autoscroll=True, do_not_clear=True)], ] @@ -11712,12 +12164,12 @@ class _Debugger(): var_layout = [] for i in range(NUM_AUTO_WATCH): var_layout.append([T('', size=(WIDTH_WATCHER_VARIABLES, 1), key='_WATCH%s_' % i), - T('', size=(WIDTH_WATCHER_RESULTS, MAX_LINES_PER_RESULT_MAIN), key='_WATCH%s_RESULT_' % i, - )]) + T('', size=(WIDTH_WATCHER_RESULTS, MAX_LINES_PER_RESULT_MAIN), key='_WATCH%s_RESULT_' % i, + )]) col1 = [ # [Frame('Auto Watches', autowatch_frame+variable_values, title_color='blue')] - [Frame('Auto Watches', autowatch_frame+var_layout, title_color='blue')] + [Frame('Auto Watches', autowatch_frame + var_layout, title_color='blue')] ] col2 = [ @@ -11727,13 +12179,18 @@ class _Debugger(): # Tab based layout layout = [[TabGroup([[Tab('Variables', col1), Tab('REPL & Watches', col2)]])], - [Button('', image_data=red_x, key='_EXIT_', button_color=None),]] + [Button('', image_data=red_x, key='_EXIT_', button_color=None), ]] # ------------------------------- Create main window ------------------------------- - window = Window("PySimpleGUI Debugger", layout, icon=PSGDebugLogo, margins=(0, 0), location=location).Finalize() + window = Window("PySimpleGUI Debugger", layout, icon=PSGDebugLogo, margins=(0, 0), location=location) + + Window.read_call_from_debugger = True + window.finalize() + Window.read_call_from_debugger = False + window.Element('_VAR1_').SetFocus() self.watcher_window = window - ChangeLookAndFeel('SystemDefault') # set look and feel to default before exiting + ChangeLookAndFeel('SystemDefault') # set look and feel to default before exiting return window # # ####### # @@ -11751,17 +12208,18 @@ class _Debugger(): :param myglobals: """ - if not self.watcher_window: # if there is no window setup, nothing to do + if not self.watcher_window: # if there is no window setup, nothing to do return False event, values = self.watcher_window.Read(timeout=1) if event in (None, 'Exit', '_EXIT_'): # EXIT BUTTON / X BUTTON try: self.watcher_window.Close() - except: pass + except: + pass self.watcher_window = None return False # ------------------------------- Process events from REPL Tab ------------------------------- - cmd = values['_REPL_'] # get the REPL entered + cmd = values['_REPL_'] # get the REPL entered # BUTTON - GO (NOTE - This button is invisible!!) if event == 'Go': # GO BUTTON self.watcher_window.Element('_REPL_').Update('') @@ -11867,7 +12325,7 @@ class _Debugger(): self.watcher_window.Element('_WATCH{}_'.format(i)).Update('') self.watcher_window.Element('_WATCH{}_RESULT_'.format(i)).Update('') - return True # return indicating the window stayed open + return True # return indicating the window stayed open ###### # # # # #### ##### # # ##### # # # # # # ##### #### # # @@ -11914,21 +12372,21 @@ class _Debugger(): cur_col += 1 ScrolledTextBox(out_text, non_blocking=True) - ##### # # -# # # # #### #### #### ###### # # # ## ##### #### # # -# # # # # # # # # # # # # # # # # # # -# ###### # # # # #### ##### # # # # # # # ###### -# # # # # # # # # # # # ###### # # # # -# # # # # # # # # # # # # # # # # # # # # - ##### # # #### #### #### ###### ## ## # # # #### # # + ##### # # + # # # # #### #### #### ###### # # # ## ##### #### # # + # # # # # # # # # # # # # # # # # # # + # ###### # # # # #### ##### # # # # # # # ###### + # # # # # # # # # # # # ###### # # # # + # # # # # # # # # # # # # # # # # # # # # + ##### # # #### #### #### ###### ## ## # # # #### # # -# # # # -# # ## ##### # ## ##### # ###### #### # # # # # # -# # # # # # # # # # # # # # # # # # ## # -# # # # # # # # # ##### # ##### #### # # # # # # # - # # ###### ##### # ###### # # # # # # # # # # # # - # # # # # # # # # # # # # # # # # # # # ## - # # # # # # # # ##### ###### ###### #### ## ## # # # + # # # # + # # ## ##### # ## ##### # ###### #### # # # # # # + # # # # # # # # # # # # # # # # # # ## # + # # # # # # # # # ##### # ##### #### # # # # # # # + # # ###### ##### # ###### # # # # # # # # # # # # + # # # # # # # # # # # # # # # # # # # # ## + # # # # # # # # ##### ###### ###### #### ## ## # # # def _choose_auto_watches(self, my_locals): """ @@ -11949,7 +12407,7 @@ class _Debugger(): sorted_dict[key] = my_locals[key] for key in sorted_dict: line.append(CB(key, key=key, size=(longest_line, 1), - default=self.local_choices[key] if key in self.local_choices else False)) + default=self.local_choices[key] if key in self.local_choices else False)) if cur_col + 1 == num_cols: cur_col = 0 layout.append(line) @@ -11976,7 +12434,7 @@ class _Debugger(): break elif event == 'Clear All': PopupQuickMessage('Cleared Auto Watches', auto_close=True, auto_close_duration=3, non_blocking=True, - text_color='red', font='ANY 18') + text_color='red', font='ANY 18') for key in sorted_dict: window.Element(key).Update(False) window.Element('_CUSTOM_WATCH_').Update('') @@ -12013,7 +12471,7 @@ class _Debugger(): :param location: """ - if self.popout_window: # if floating window already exists, close it first + if self.popout_window: # if floating window already exists, close it first self.popout_window.Close() ChangeLookAndFeel('Topanga') num_cols = 2 @@ -12024,7 +12482,7 @@ class _Debugger(): col = 0 # self.popout_choices = self.local_choices self.popout_choices = {} - if self.popout_choices == {}: # if nothing chosen, then choose all non-_ variables + if self.popout_choices == {}: # if nothing chosen, then choose all non-_ variables for key in sorted(self.locals.keys()): self.popout_choices[key] = not key.startswith('_') @@ -12032,7 +12490,7 @@ class _Debugger(): for key in self.popout_choices: if self.popout_choices[key] is True: value = str(self.locals.get(key)) - h = min(len(value)//width_value + 1, MAX_LINES_PER_RESULT_FLOATING) + h = min(len(value) // width_value + 1, MAX_LINES_PER_RESULT_FLOATING) line += [Text('{}'.format(key), size=(width_var, 1), font=POPOUT_WINDOW_FONT), Text(' = ', font=POPOUT_WINDOW_FONT), Text(value, key=key, size=(width_value, h), font=POPOUT_WINDOW_FONT)] @@ -12049,8 +12507,13 @@ class _Debugger(): [[Button('', key='_EXIT_', image_data=red_x, button_color=('#282923', '#282923'), border_width=0)]])]] self.popout_window = Window('Floating', layout, alpha_channel=0, no_titlebar=True, grab_anywhere=True, - element_padding=(0, 0), margins=(0, 0), keep_on_top=True, - right_click_menu=['&Right', ['Debugger::RightClick', 'Exit::RightClick']], location=location ).Finalize() + element_padding=(0, 0), margins=(0, 0), keep_on_top=True, + right_click_menu=['&Right', ['Debugger::RightClick', 'Exit::RightClick']], location=location, finalize=False) + + Window.read_call_from_debugger = True + self.popout_window.Finalize() + Window.read_call_from_debugger = False + if location == (None, None): screen_size = self.popout_window.GetScreenDimensions() self.popout_window.Move(screen_size[0] - self.popout_window.Size[0], 0) @@ -12118,8 +12581,6 @@ class _Debugger(): # 888 "Y88888 888 888 "Y8888P "Y888 888 "Y88P" 888 888 88888P' - - def show_debugger_window(location=(None, None), *args): """ Shows the large main debugger window @@ -12192,7 +12653,6 @@ def _refresh_debugger(): return rc - # d8b # Y8P # @@ -12203,7 +12663,6 @@ def _refresh_debugger(): # 888 888 888 "Y888888 888 888 888 - def main(): """ The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. @@ -12212,8 +12671,8 @@ def main(): """ from random import randint # preview_all_look_and_feel_themes() - look_and_feel = 'DarkRed' - ChangeLookAndFeel(look_and_feel) + # look_and_feel = 'Hot Dog Stand' + # theme('Hot Dog Stand') # ------ Menu Definition ------ # menu_def = [['&File', ['!&Open', '&Save::savekey', '---', '&Properties', 'E&xit']], ['!&Edit', ['!&Paste', ['Special', 'Normal', ], 'Undo'], ], @@ -12239,15 +12698,14 @@ def main(): [Input('Input Text', size=(25, 1)), ], [Multiline(size=(30, 5), default_text='Multiline Input')], ] - theme = 'default' frame2 = [ # [ProgressBar(100, bar_color=('red', 'green'), orientation='h')], [Listbox(['Listbox 1', 'Listbox 2', 'Listbox 3'], select_mode=SELECT_MODE_EXTENDED, size=(20, 5), no_scrollbar=True)], - [Combo(['Combo item %s'%i for i in range(5)], size=(20, 3), default_value='Combo item 2',key='_COMBO1_', background_color='green')], + [Combo(['Combo item %s' % i for i in range(5)], size=(20, 3), default_value='Combo item 2', key='_COMBO1_', )], # [Combo(['Combo item 1', 2,3,4], size=(20, 3), readonly=False, text_color='blue', background_color='red', key='_COMBO2_')], - [Spin([1, 2, 3, 'a','b','c'], initial_value='a', size=(4, 3))], + [Spin([1, 2, 3, 'a', 'b', 'c'], initial_value='a', size=(4, 3))], ] frame3 = [ @@ -12257,20 +12715,20 @@ def main(): ] frame4 = [ - [Slider(range=(0, 100), orientation='v', size=(7, 15), default_value=40), - Slider(range=(0, 100), orientation='h', size=(11, 15), default_value=40), ], + [Slider(range=(0, 100), orientation='v', size=(7, 15), default_value=40, key='-SLIDER1-'), + Slider(range=(0, 100), orientation='h', size=(11, 15), default_value=40, key='-SLIDER2-'), ], ] - matrix = [[str(x * y) for x in range(1,5)] for y in range(1,8)] + matrix = [[str(x * y) for x in range(1, 5)] for y in range(1, 8)] frame5 = [[ Table(values=matrix, headings=matrix[0], - auto_size_columns=False, display_row_numbers=True, change_submits=False, justification='right', - num_rows=10, alternating_row_color='lightblue', key='_table_', text_color='black', - col_widths=[5, 5, 5, 5], size=(400, 200), background_color='green'), + auto_size_columns=False, display_row_numbers=True, change_submits=False, justification='right', + num_rows=10, alternating_row_color='lightblue', key='_table_', + col_widths=[5, 5, 5, 5], size=(400, 200), ), T(' '), Tree(data=treedata, headings=['col1', 'col2', 'col3'], change_submits=True, auto_size_columns=True, - num_rows=10, col0_width=10, key='_TREE_', show_expanded=True, background_color='green'), - ], + num_rows=10, col0_width=10, key='_TREE_', show_expanded=True,), + ], ] graph_elem = Graph((600, 150), (0, 0), (800, 300), key='+GRAPH+') @@ -12279,21 +12737,20 @@ def main(): [graph_elem], ] - tab1 = Tab('Graph', frame6, tooltip='Graph is in here', title_color='red' ) - tab2 = Tab('Multiple/Binary Choice Groups', [ [Frame('Multiple Choice Group', frame2, title_color='green', tooltip='Checkboxes, radio buttons, etc'), - Frame('Binary Choice Group', frame3, title_color='white', tooltip='Binary Choice'),]]) - tab3 = Tab('Table and Tree', [[Frame('Structured Data Group', frame5, title_color='red', element_justification='l')]], tooltip='tab 3', title_color='red' ) - tab4 = Tab('Variable Choice', [[Frame('Variable Choice Group', frame4, title_color='blue')]], tooltip='tab 4', title_color='red' ) - - + tab1 = Tab('Graph', frame6, tooltip='Graph is in here', title_color='red') + tab2 = Tab('Multiple/Binary Choice Groups', [[Frame('Multiple Choice Group', frame2, title_color='green', tooltip='Checkboxes, radio buttons, etc'), + Frame('Binary Choice Group', frame3, title_color='white', tooltip='Binary Choice'), ]]) + tab3 = Tab('Table and Tree', [[Frame('Structured Data Group', frame5, title_color='red', element_justification='l')]], tooltip='tab 3', title_color='red') + tab4 = Tab('Variable Choice', [[Frame('Variable Choice Group', frame4, title_color='blue')]], tooltip='tab 4', title_color='red') layout1 = [ - [Image(data=DEFAULT_BASE64_ICON),Image(data=DEFAULT_BASE64_LOADING_GIF, key='_IMAGE_'), - Text('You are running the PySimpleGUI.py file instead of importing it.\nAnd are thus seeing a test harness instead of your code', font='ANY 15', tooltip='My tooltip', key='_TEXT1_')], + [Image(data=DEFAULT_BASE64_ICON), Image(data=DEFAULT_BASE64_LOADING_GIF, key='_IMAGE_'), + Text('You are running the PySimpleGUI.py file instead of importing it.\nAnd are thus seeing a test harness instead of your code', font='ANY 15', + tooltip='My tooltip', key='_TEXT1_')], [Frame('Input Text Group', frame1, title_color='red'), Text('VERSION\n{}'.format(__version__), size=(25, 4), font='ANY 20'), ], - [TabGroup([[tab1, tab2, tab3, tab4]],key='_TAB_GROUP_', background_color='green',selected_title_color='red', title_color='blue' )], + [TabGroup([[tab1, tab2, tab3, tab4]], key='_TAB_GROUP_', )], [Button('Button'), B('Hide Stuff', metadata='my metadata'), Button('ttk Button', use_ttk_buttons=True, tooltip='This is a TTK Button'), Button('See-through Mode', tooltip='Make the background transparent'), @@ -12302,7 +12759,7 @@ def main(): layout = [[Column([[Menu(menu_def, key='_MENU_')]] + layout1), Column([[ProgressBar(max_value=800, size=(50, 25), orientation='v', key='+PROGRESS+')]])]] window = Window('Window Title', layout, - font=('Helvetica', 13), + # font=('Helvetica', 18), # background_color='black', right_click_menu=['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']], # transparent_color= '#9FB8AD', @@ -12310,15 +12767,18 @@ def main(): keep_on_top=True, element_justification='left', metadata='My window metadata', + # ttk_theme=THEME_VISTA, # icon=PSG_DEBUGGER_LOGO ) # graph_elem.DrawCircle((200, 200), 50, 'blue') i = 0 + Print('', location=(0, 0), font='Courier 12', size=(60, 15), grab_anywhere=True) while True: # Event Loop event, values = window.Read(timeout=5) if event != TIMEOUT_KEY: print(event, values) - Print(event, values, location=(0,0), font='Courier 8', size=(60,15), grab_anywhere=True) + Print(event, text_color='green', background_color='white', end='') + Print(values) if event is None or event == 'Exit': break if i < 800: @@ -12342,9 +12802,8 @@ def main(): elif event == 'About...': popup_no_wait('About this program...', 'You are looking at the test harness for the PySimpleGUI program') elif event.startswith('See'): - window.SetTransparentColor(LOOK_AND_FEEL_TABLE[look_and_feel]['BACKGROUND']) - window.Close() - + window.set_transparent_color(LOOK_AND_FEEL_TABLE[get_theme()]['BACKGROUND']) + window.close() # ------------------------ PEP8-ify The SDK ------------------------# @@ -12392,9 +12851,13 @@ set_options = SetOptions test = main -# __all__ = ['** YOUR from PySimpleGUI import * HAS BEEN BLOCKED. YOU ARE NOT ALLOWED THIS KIND OF IMPORT WITH THIS LIBRARY **'] # do not allow import * +#------------------------ Set the "Official PySimpleGUI Theme Colors" ------------------------ +theme(CURRENT_LOOK_AND_FEEL) + + # -------------------------------- ENTRY POINT IF RUN STANDALONE -------------------------------- # if __name__ == '__main__': main() exit(69) + diff --git a/readme_creator/make_real_readme.py b/readme_creator/make_real_readme.py index 6cd36076..2c5f26fe 100644 --- a/readme_creator/make_real_readme.py +++ b/readme_creator/make_real_readme.py @@ -298,6 +298,7 @@ def get_sig_table_parts(function_obj, function_name, doc_string, logger=None, is elif type(val) is str: rows.append(f'{key}="{val}"') elif type(val) is tuple: rows.append(f'{key}={val}') elif type(val) is bool: rows.append(f'{key}={val}') + elif type(val) is bytes: rows.append(f'{key}=...') else: raise Exception(f'IDK this type -> {key, val}') @@ -434,8 +435,22 @@ def main(do_full_readme=False, files_to_include: list = [], logger:object=None, # 8888888888888888888888888888888888888888888888888888888888888888888888888 # =========== 2 GET classes, funcions, varialbe a.k.a. memes =========== # # 8888888888888888888888888888888888888888888888888888888888888888888888888 - psg_members = getmembers(PySimpleGUIlib) # variables, functions, classes + def valid_field(pair): + bad_fields = 'LOOK_AND_FEEL_TABLE copyright __builtins__ icon'.split(' ') + bad_prefix = 'TITLE_ TEXT_ ELEM_TYPE_ DEFAULT_ BUTTON_TYPE_ LISTBOX_SELECT METER_ POPUP_ THEME_'.split(' ') + + field_name, python_object = pair + if type(python_object) is bytes: + return False + if field_name in bad_fields: + return False + if any([i for i in bad_prefix if field_name.startswith(i)]): + return False + return True + + psg_members = [i for i in getmembers(PySimpleGUIlib) if valid_field(i)] # variables, functions, classes + # psg_members = getmembers(PySimpleGUIlib) # variables, functions, classes psg_funcs = [o for o in psg_members if isfunction(o[1])] # only functions psg_classes = [o for o in psg_members if isclass(o[1])] # only classes psg_classes_ = list(set([i[1] for i in psg_classes])) # boildown B,Btn,Butt -into-> Button diff --git a/readme_creator/readme.md b/readme_creator/readme.md index bd234a64..e131764c 100644 --- a/readme_creator/readme.md +++ b/readme_creator/readme.md @@ -1,16 +1,20 @@ ![pysimplegui_logo](https://user-images.githubusercontent.com/13696193/43165867-fe02e3b2-8f62-11e8-9fd0-cc7c86b11772.png) [![Downloads](http://pepy.tech/badge/pysimplegui)](http://pepy.tech/project/pysimplegui) tkinter + [![Downloads ](https://pepy.tech/badge/pysimplegui27)](https://pepy.tech/project/pysimplegui27) tkinter 2.7 (WARNING - DISAPPEARING Entirely on 12/31/2019!!!) + [![Downloads](https://pepy.tech/badge/pysimpleguiqt)](https://pepy.tech/project/pysimpleguiqt) Qt + [![Downloads](https://pepy.tech/badge/pysimpleguiwx)](https://pepy.tech/project/pysimpleguiWx) WxPython + [![Downloads](https://pepy.tech/badge/pysimpleguiweb)](https://pepy.tech/project/pysimpleguiWeb) Web (Remi) ![Documentation Status](https://readthedocs.org/projects/pysimplegui/badge/?version=latest) ![Awesome Meter](https://img.shields.io/badge/Awesome_meter-100-yellow.svg) ![Python Version](https://img.shields.io/badge/Python-2.7_3.x-yellow.svg) -![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.7.0-red.svg?longCache=true&style=for-the-badge) +![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_3.x_Version-4.13.1-red.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUI_For_Python_2.7_Version-2.4.1-blue.svg?longCache=true&style=for-the-badge) ![Python Version](https://img.shields.io/badge/PySimpleGUIQt_Version-0.30.0-orange.svg?longCache=true&style=for-the-badge) @@ -155,12 +159,19 @@ and returns the value input as well as the button clicked. [How to submit an Issue](https://github.com/PySimpleGUI/PySimpleGUI/issues/1646) -The YouTube videos - If you like instructional videos, there are over 15 videos +The YouTube videos - If you like instructional videos, there are over 15 videos made by PySimpleGUI project - [5 part series of basics](https://www.youtube.com/playlist?list=PLl8dD0doyrvHMoJGTdMtgLuHymaqJVjzt) - [10 part series of more detail](https://www.youtube.com/playlist?list=PLl8dD0doyrvGyXjORNvirTIZxKopJr8s0) - [The Naked Truth (An updaate on the technology)](https://youtu.be/BFTxBmihsUY) - There are numerous short videos also on that channel that demonstrate PySimpleGUI being used +YouTube Videos made by others. These have much higher production values than the above videos. + +- A ***fantastic*** tutorial [PySimpleGUI Concepts - Video 1](https://youtu.be/cLcfLm_GgiM) +- Build a calculator [Python Calculator with GUI | PySimpleGUI | Texas Instruments DataMath II](https://youtu.be/x5LSTDdffFk) +- Notepad [Notepad in Python - PySimpleGUI](https://youtu.be/JQY641uynKo) +- File Search Engine [File Search Engine | Project for Python Portfolio with GUI | PySimpleGUI](https://youtu.be/IWDC9vcBIFQ) + # About The PySimpleGUI Documentation System This User's Manual (also the project's readme) is one ***vital*** part of the PySimpleGUI programming environment. @@ -222,10 +233,10 @@ PySimpleGUI runs on Windows, Linux and Mac, just like tkinter, Qt, WxPython and ### OS * Windows 7, 8, 10 -* Linux on PC - Tested on **many** distributions +* Linux on PC - Tested on several distributions * Linux on Raspbnerry Pi * Linux on Android - Can use either Termux or PyDroid3 -* Mac OS (Sorry don't know much about Macs other than Macs don't like tkinter) +* Mac OS #### Python versions @@ -392,6 +403,35 @@ PySimpleGUIWeb is first and foremost a **GUI**, a program's front-end. It is des If more than 1 person connects at a time, then both users will see the exact same stuff and will be interacting with the program as if a single user was using it. +## Android Version + +PySimpleGUI runs on Android devices with the help of either the PyDroid3 app or the Termux app. Both are capable of running tkinter programs which means both are capable of running PySimpleGUI. + +To use with PyDroid3 you will need to add this import to the top of all of your PySimpleGUI program files: + +```python +import tkinter +``` + +This evidently triggers PyDroid3 that the application is going to need to use the GUI. + +You will also want to create your windows with the `location` parameter set to `(0,0)`. + +Here's a quick demo that uses OpenCV2 to display your webcam in a window that runs on PyDroid3: + +```python +import tkinter +import cv2, PySimpleGUI as sg +USE_CAMERA = 0 # change to 1 for front facing camera +window, cap = sg.Window('Demo Application - OpenCV Integration', [[sg.Image(filename='', key='image')], ], location=(0, 0), grab_anywhere=True), cv2.VideoCapture(USE_CAMERA) +while window(timeout=20)[0] is not None: + window['image'](data=cv2.imencode('.png', cap.read()[1])[1].tobytes()) +``` + +You will need to pip install opencv-python as well as PySimpleGUI to run this program. + +Also, you must be using the Premium, yes paid, version of PyDroid3 in order to run OpenCV. The cost is CHEAP when compared to the rest of things in life. A movie ticket will cost you more. Which is more fun, seeing **your Python program** running on your phone and using your phone's camera, or some random movie currently playing? From experience, the Python choice is a winner. If you're cheap, well, then you won't get to use OpenCV. No, there is no secret commercial pact between the PySimpleGUI project and the PyDroid3 app team. + ## Source code compatibility In theory, your source code is completely portable from one platform to another by simply changing the import statement. That's the GOAL and suprisingly many times this 1-line change works. Seeing your code run on tkinter, then change the import to `import PySimpleGUIWeb as sg` and instead of a tkinter window, up pops your default browser with your window running on it is an incredible feeling. @@ -444,13 +484,16 @@ Repl.it is not meant to serve up applications and web pages. Trying to use it t It's surprising that Python GUI code is completely cross platform from Windows to Mac to Linux. No source code changes. This is true for both PySimpleGUI and PySimpleGUIQt. -However, **Macs** suck. They suck on tkinter in particular. The "Look and feel" calls are disabled for Macs. Colored buttons in particular are broken. And, you are unable to specify filetypes when using the FileBrowse button. None of this is PySimpleGUI code issues, of course, they're all in tkinter. Consider using Qt instead of tkinter on the Mac. Or, if using tkinter, create your own button images. +Historicly, PySimpleGUI using tkinter have struggled on Macs. This was because of a problem setting button colors on the Mac. However, two events has turned this problem around entirely. -***Look through the open and closed issues if you're a Mac person with a problem. It's highly likely the problem has been at least seen previously and there may even be a fix or workaround*** +1. Use of ttk Buttons for Macs +2. Ability for Mac users to install Python from python.org rather than the Homebrew version with button problems -*Switching to "Light Mode" is known to fix some of the problems.* They honestly are tkinter/Mac problems. +It's been a long road for Mac users with many deciding to use PySimpleGUIQt so that multi-colored windows could be made. It's completely understandable to want to make attractive windows that utilitize colors. -Make sure you're running tkinter 8.6 and up. However, as I'm learning 8.6 can mean almost anything as the minor release numbers are not provided (8.6.1, etc). Turns out 8.6 has been in development for YEARS. The 8.6 that comes with Python 3.7.4 doesn't support table colors for example even though it's version 8.6. +PySimpleGUI now supports Macs, Linux, and Windows equally well. They all are able to use the "Themes" that automatically add color to your windows. + +Be aware that Macs default to using ttk buttons. You can override this setting at the Window and Button levels. If you installed Python from python.org, then it's likely you can use the non-ttk buttons should you wish. # Support @@ -684,13 +727,16 @@ Creating and reading the user's inputs for the window occupy the last 2 lines of ```python import PySimpleGUI as sg -layout = [[sg.Text('Filename')], - [sg.Input(), sg.FileBrowse()], - [sg.OK(), sg.Cancel()]] +sg.change_look_and_feel('Dark Blue 3') # please make your creations colorful + +layout = [ [sg.Text('Filename')], + [sg.Input(), sg.FileBrowse()], + [sg.OK(), sg.Cancel()]] window = sg.Window('Get filename example', layout) event, values = window.Read() +window.close() ``` ![get filename](https://user-images.githubusercontent.com/13696193/44960039-f1018880-aec5-11e8-8a43-3d7f8ff93b67.jpg) @@ -785,7 +831,9 @@ Just because you can't match a pair of socks doesn't mean your windows have to a In PySimpleGUI release 4.6 the number of themes was dramatically increased from a couple dozen to over 100. To use the color schemes shown in the window below, add a call to `change_look_and_feel('Theme Name)` to your code, passing in the name of thd desired color theme. To see this window and the list of available themes on your releeae of softrware, call the function `preview_all_look_and_feel_themes()`. This will create a window with the frames like those below. It will shows you exactly what's available in your version of PySimpleGUI. -![Nov 2019 Look and Feel Themes](https://user-images.githubusercontent.com/46163555/68987669-91a54500-07f9-11ea-921e-8bf9320e3156.png) +In release 4.9 another 32 Color Themes were added... here are the current choices + +![Dec 2019 Look And Feel Themes](https://user-images.githubusercontent.com/46163555/70382042-796da500-1923-11ea-8432-80d08cd5f503.jpg) Make beautiful looking, alpha-blended (partially transparent) Rainmeter-style Desktop Widgets that run in the background. @@ -909,6 +957,7 @@ Features of PySimpleGUI include: - Calendar chooser - Color chooser - Button Menu +- TTK Buttons or "normal" TK Buttons - Checkboxes - Radio Buttons - Listbox @@ -1022,7 +1071,7 @@ Beginners certainly can add more `if event == 'my button':` statements to the ev The hope is that beginners that are interested in graphic design, and are taking a Python course, will have an easy way to express themselves, right from the start of their Python experience. Even if they're not the best programmers they will be able express themselves to show custom GUI layouts, colors and artwork with ease. -> Fill the GUI Gap +> Fill the GUI Gap (Democratize GUIs) There is a noticeable gap in the Python GUI solution. Fill that gap and who knows what will happen. At the moment, to make a tradiional GUI window using tkinter, Qt, WxPython and Remi, it takes much more than a week, or a month of Python education to use these GUI packages. @@ -1077,6 +1126,8 @@ More information about installing tkinter can be found here: https://www.techinf ### Installing for Python 2.7 +**IMPORTANT** PySimpleGUI27 will disappear from the GitHub on Dec 31, 2019. PLEASE migrate to 3.6 at least. It's not painful for most people. + `pip install --upgrade PySimpleGUI27` or `pip2 install --upgrade PySimpleGUI27` @@ -1087,8 +1138,6 @@ You may need to also install "future" for version 2.7 or `pip2 install future` -Python 2.7 support is relatively new and the bugs are still being worked out. I'm unsure what may need to be done to install tkinter for Python 2.7. Will update this readme when more info is available - Like above, you may have to install either pip or tkinter. To do this on Python 2.7: `sudo apt install python-pip` @@ -1216,34 +1265,15 @@ Then use either "high level" API calls or build your own windows. Yes, it's just that easy to have a window appear on the screen using Python. With PySimpleGUI, making a custom window appear isn't much more difficult. The goal is to get you running on your GUI within ***minutes***, not hours nor days. -***WARNING*** Do NOT use PySimpleGUI with Python 3.7.3 and 3.7.4. tkiter is having issues with that release. Things like Table colors stopped working entirely. None of us want to debug tkinter code. It's difficult enough debugging your code and PySimpleGUI code. A lot of time has already been spent debugging this one so no need for you to suffer too. - ### Python 3.7 -It puzzles me why a beginner would install 3.7. Or even a seasoned programmer. What specific feature of 3.7 are you using that is not in 3.6? If you are unable to answer this, then ***it's strongly suggested that you run 3.6***, an immensely solid release of Python with all those goodie inside like f-strings. If you must run 3.7, try 3.7.2 instead. It does work with PySimpleGUI with no known issues. +If you must run 3.7, try 3.7.2. It does work with PySimpleGUI with no known issues. -## Using - Python 2.7 +***PySimpleGUI with Python 3.7.3 and 3.7.4+.*** tkinter is having issues with all the newer releases. Things like Table colors stopped working entirely. It's unclear if there's been a change that makes the tkinter API no longer working which means they are not backwards compatible. That would be a real shame. If so, more work needs to be done in PySimpleGUI -Those using Python 2.7 will import a different module name +## Python 2.7 -```python -import PySimpleGUI27 as sg -``` - -## Code to Automatically Import Correct Version - -Many of the demo programs use this check to see which package to use: -```python -import sys -if sys.version_info[0] >= 3: - import PySimpleGUI as sg -else: - import PySimpleGUI27 as sg -``` - -This will automatically import the correct library based on the Python version number reported by the Python interpreter. - -NOTE: It's 2019 and 2.7 support is being systematically removed. This construct will be removed from the demo programs shortly. 2.7 users can still run these demos, but they will need to change the import from PySimpleGUI to PySimpleGUI27. It save 4 lines of code and an import from sys in the process. +On December 31, 2019 the Python 2.7 version of PySimpleGUI will be **deleted** from the GitHub. Sorry but Legacy Python has no permanent home here. The security experts claim that supporting 2.7 is doing a diservice to the Python community. I understand why. There are some very narrow cases where 2.7 is required. If you have one, make a copy of PySimpleGUI27.py quickly before it disappears for good. --- @@ -1912,11 +1942,13 @@ Writing the code for this one is just as straightforward. There is one tricky t ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('Filename')], [sg.Input(), sg.FileBrowse()], [sg.OK(), sg.Cancel()] ] -window sg.Window('Get filename example', layout) +window = sg.Window('Get filename example', layout) event, values = window.read() window.close() @@ -1938,6 +1970,8 @@ The input fields in your window will be returned to you as a dictionary (syntact ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('SHA-1 and SHA-256 Hashes for the file')], [sg.InputText(), sg.FileBrowse()], [sg.Submit(), sg.Cancel()]] @@ -1959,6 +1993,8 @@ This code will present a window and will print values until the user clicks the ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('Persistent window')], [sg.Input()], [sg.Button('Read'), sg.Exit()]] @@ -1987,7 +2023,9 @@ This example introduces the concept of "keys". Keys are super important in PySi ```python import PySimpleGUI as sg -layout = [[sg.Text('Your typed chars appear here:'), sg.Text('', size=(12,1), key='_OUTPUT_')], +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + +layout = [[sg.Text('Your typed chars appear here:'), sg.Text(size=(12,1), key='_OUTPUT_')], [sg.Input(key='_IN_')], [sg.Button('Show'), sg.Button('Exit')]] @@ -2024,6 +2062,8 @@ Let's dissect this little program ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [[sg.Text('Rename files or folders')], [sg.Text('Source for Folders', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], [sg.Text('Source for Files ', size=(15, 1)), sg.InputText(), sg.FolderBrowse()], @@ -2037,8 +2077,16 @@ folder_path, file_path = values[0], values[1] # get the data from the valu print(folder_path, file_path) ``` +#### Colors + +![image](https://user-images.githubusercontent.com/46163555/70470775-cd01ff00-1a99-11ea-8b9c-8b33c8880c99.png) + +The first line of code after the import is a call to `change_look_and_feel`. This single line of code make the window look like the window above instead of the window below. It will also stop PySimpleGUI from nagging you to put one of these calls into your program. + ![snap0131](https://user-images.githubusercontent.com/13696193/43417007-df6d8408-9407-11e8-9986-30f0415f08a5.jpg) +#### Window contents + Let's agree the window has 4 rows. The first row only has **text** that reads `Rename files or folders` @@ -2062,6 +2110,8 @@ For return values the window is scanned from top to bottom, left to right. Each In our example window, there are 2 fields, so the return values from this window will be a dictionary with 2 values in it. Remember, if you do not specify a `key` when creating an element, one will be created for you. They are ints starting with 0. In this example, we have 2 input elements. They will be addressable as values[0] and values[1] +#### "Reading" the window's values (also displays the window) + ```python event, values = window.read() folder_path, file_path = values[0], values[1] @@ -2129,7 +2179,7 @@ while True: event, values = window.read() if event is None: break -window.Close() +window.close() ``` You will very often see the examples and demo programs write this check as: @@ -2268,6 +2318,8 @@ Let's take a look at your first dictionary-based window. ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Blue 3') # please make your windows colorful + layout = [ [sg.Text('Please enter your Name, Address, Phone')], [sg.Text('Name', size=(15, 1)), sg.InputText('1', key='_NAME_')], @@ -2278,7 +2330,7 @@ layout = [ window = sg.Window('Simple data entry window', layout) event, values = window.read() -window.Close() +window.close() sg.Popup(event, values, values['_NAME_'], values['_ADDRESS_'], values['_PHONE_']) ``` @@ -2357,6 +2409,7 @@ layout = [ window = sg.Window('Everything bagel', layout, default_element_size=(40, 1), grab_anywhere=False) event, values = window.read() +window.close() sg.Popup('Title', 'The results of the window.', @@ -2477,12 +2530,6 @@ You can get your window's size by access the `Size` property. The window has to To finalize your window: -```python -window = Window('My Title', layout).Finalize() -``` - -If using PySimpleGUI 4.2 and later: - ```python window = Window('My Title', layout, finalize=True) ``` @@ -2529,6 +2576,27 @@ To keep a window on top of all other windows on the screen, set keep_on_top = Tr PySimpleGUI will set a default focus location for you. This generally means the first input field. You can set the focus to a particular element. If you are going to set the focus yourself, then you should turn off the automatic focus by setting `use_default_focus=False` in your Window call. +### TTK Buttons + +Beginning in release 4.7.0 PySimpleGUI supports both "normal" tk Buttons and ttk Buttons. This change was needed so that Mac users can use colors on their buttons. There is a bug that causes tk Buttons to not show text when you attempt to change the button color. Note that this problem goes away if you install Python from the official Python.org site rather than using Homebrew. A number of users have switched and are quite happy since even tk Buttons work on the Mac after the switch. + +By default Mac users will get ttk Buttons when a Button Element is used. All other platforms will get a normal tk Button. There are ways to override this behavior. One is by using the parameter `use_ttk_buttons` when you create your window. If set to True, all buttons will be ttk Buttons in the window. If set to False, all buttons will be normal tk Buttons. If not set then the platform or the Button Element determines which is used. + +If a system-wide setting is desired, then the default can be set using `set_options`. This will affect all windows such as popups and the debug window. + +### TTK Themes + +tkinter has a number of "Themes" that can be used with ttk widgets. In PySimpleGUI these widgets include - Table, Tree, Combobox, Button, ProgressBar, Tabs & TabGroups. Some elements have a 'theme' parameter but these are no longer used and should be ignored. The initial release of PySimpleGUI attempted to mix themes in a single window but since have learned this is not possible so instead it is set at the Window or the system level. + +If a system-wide setting is desired, then the default can be set using `set_options`. This will affect all windows such as popups and the debug window. + +The ttk theme choices depend on the platform. Linux has a shorter number of selections than Windows. These are the Windows choices: +'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative' + +There are constants defined to help you with code completion to determine what your choices are. Theme constants start with `THEME_`. For example, the "clam" theme is `THEME_CLAM` + +You're urged to experiment with this setting to determine which you like the most. They change the ttk-based elements in subtle but still significant ways. + ## Closing Windows When you are completely done with a window, you should close it and then delete it so that the resources, in particular the tkinter resources, are properly cleaned up. @@ -2559,8 +2627,8 @@ This is the "long form" as each method is called individually. ```python window = sg.Window('My Title') -window.Layout(layout) -window.Finalize() +window.layout(layout) +window.finalize() ``` ### Chaining The Calls (the old method) @@ -2568,7 +2636,7 @@ window.Finalize() The next level of compression that was done was to chain the calls together into a single line of code. ```python -window = sg.Window('My Title').Layout(layout).Finalize() +window = sg.Window('My Title').Layout(layout).finalize() ``` ### Using Parameters Instead of Calls (New Preferred Method) @@ -2589,13 +2657,13 @@ Call to set the window layout. Must be called prior to `Read`. Most likely "ch window = sg.Window('My window title', layout) ``` -#### `Finalize()` or `Window` parameter `finalize=True` +#### `finalize()` or `Window` parameter `finalize=True` Call to force a window to go through the final stages of initialization. This will cause the tkinter resources to be allocated so that they can then be modified. This also causes your window to appear. If you do not want your window to appear when Finalize is called, then set the Alpha to 0 in your window's creation parameters. If you want to call an element's `Update` method or call a `Graph` element's drawing primitives, you ***must*** either call `Read` or `Finalize` prior to making those calls. -#### Read(timeout=None, timeout_key=TIMEOUT_KEY) +#### read(timeout=None, timeout_key=TIMEOUT_KEY) Read the Window's input values and button clicks in a blocking-fashion @@ -2819,11 +2887,13 @@ The first part should look familiar since it was just discussed as being what bu ### Putting it all together -Here is our final program that uses simple addition to add the headers onto the top of the input matrix. +Here is our final program that uses simple addition to add the headers onto the top of the input matrix. To make it more attractive, the color theme is set to 'Dark Brown 1'. ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Brown 1') + headings = ['HEADER 1', 'HEADER 2', 'HEADER 3','HEADER 4'] header = [[sg.Text(' ')] + [sg.Text(h, size=(14,1)) for h in headings]] @@ -2835,6 +2905,8 @@ window = sg.Window('Table Simulation', layout, font='Courier 12') event, values = window.read() ``` +![image](https://user-images.githubusercontent.com/46163555/70472374-f7a18700-1a9c-11ea-9cd1-27d386cd9066.png) + ## User Defined Elements / Compound Elements "User Defined Elements" and "Compound Elements" are one or more PySimpleGUI Elements that are wrapped in a function definition. In a layout, they have the appearance of being a custom elements of some type. @@ -3360,8 +3432,6 @@ You can call the method without setting the `time_between_frames` value and it w ## Button Element -**MAC USERS** - Macs suck when it comes to tkinter and button colors. It sucks so badly with colors that the `LookAndFeel` call is disabled. You cannot change button colors for Macs. You're stuck with the system default color if you are using the tkinter version of PySimpleGUI. The Qt version does not have this issue. - Buttons are the most important element of all! They cause the majority of the action to happen. After all, it's a button press that will get you out of a window, whether it be Submit or Cancel, one way or another a button is involved in all windows. The only exception is to this is when the user closes the window using the "X" in the upper corner which means no button was involved. The Types of buttons include: @@ -3425,6 +3495,12 @@ layout = [[sg.Ok(), sg.Cancel()]] In reality `Button` is in fact being called on your behalf. Behind the scenes, `sg.Ok` and `sg.Cancel` call `Button` with the text set to `Ok` and `Cancel` and returning the results that then go into the layout. If you were to print the layout it will look identical to the first layout shown that has `Button` shown specifically in the layout. +### TTK Buttons & Macs + +In 2019 support for ttk Buttons was added. This gets around the problem of not being able to change button colors on a Mac. There are a number of places you can control whether or not ttk buttons are used, be it on MAc or other platform. + +TTK Buttons and TK Buttons operate slightly differently. Button highlighting is one different. How images and text are displayed at the same time is another. You've got options now that weren't there previously. It's nice to see that Mac users can finally use the color themes. + ### Button Element Shortcuts These Pre-made buttons are some of the most important elements of all because they are used so much. They all basically do the same thing, **set the button text to match the function name and set the parameters to commonly used values**. If you find yourself needing to create a custom button often because it's not on this list, please post a request on GitHub. . They include: @@ -4454,7 +4530,7 @@ while True: print("Nothing happened") ``` -Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and yuou've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? +Use async windows sparingly. It's possible to have a window that appears to be async, but it is not. **Please** try to find other methods before going to async windows. The reason for this plea is that async windows poll tkinter over and over. If you do not have a timeout in your Read and you've got nothing else your program will block on, then you will eat up 100% of the CPU time. It's important to be a good citizen. Don't chew up CPU cycles needlessly. Sometimes your mouse wants to move ya know? Non-blocking (timeout=0) is generally reserved as a "last resort". Too many times people use non-blocking reads when a blocking read will do just fine. @@ -4501,7 +4577,7 @@ sg.ChangeLookAndFeel('Black') sg.SetOptions(element_padding=(0, 0)) layout = [[sg.Text('')], - [sg.Text('', size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], + [sg.Text(size=(8, 2), font=('Helvetica', 20), justification='center', key='text')], [sg.ReadButton('Pause', key='button', button_color=('white', '#001480')), sg.ReadButton('Reset', button_color=('white', '#007339'), key='Reset'), sg.Exit(button_color=('white', 'firebrick4'), key='Exit')]] @@ -4684,7 +4760,7 @@ import PySimpleGUI as sg # Recipe for getting keys, one at a time as they are released # If want to use the space bar, then be sure and disable the "default focus" -text_elem = sg.Text("", size=(18, 1)) +text_elem = sg.Text(size=(18, 1)) layout = [[sg.Text("Press a key or scroll mouse")], [text_elem], @@ -4843,7 +4919,7 @@ import PySimpleGUI as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2'), sg.Button('Exit')]] win1 = sg.Window('Window 1', layout) @@ -4878,7 +4954,7 @@ import PySimpleGUIQt as sg layout = [[ sg.Text('Window 1'),], [sg.Input(do_not_clear=True)], - [sg.Text('', key='_OUTPUT_')], + [sg.Text(size=(15,1), key='_OUTPUT_')], [sg.Button('Launch 2')]] win1 = sg.Window('Window 1', layout) @@ -5264,55 +5340,57 @@ Watch this space in the future for the more standardized variable name for this ## Binding tkiner "events" -If you wish to receive events directly from tkinter, but do it in a PySimpleGUI way, then there's a particular way at the moment to make this happen. +If you wish to receive events directly from tkinter, but do it in a PySimpleGUI way, then you can do that and get those events returned to you via your standard `Window.read()` call. -tkinter performs a callback into user code when an event happens, but that's not how PySimpleGUI works. Instead of callbacks, a PySimpleGUI user's program simply returns an event via the `window.read()` call. In order for your "event" to generate an event that will be returned to you via your read call, follow these instructions: +Both the Elements and Window objects have a method called `bind`. You specify 2 parameters to this function. One is the string that is used to tell tkinter what events to bind. The other is a "key modifier" for Elements and a "key" for Windows. -1. Create a Button for each event you wish to receive -2. Set visible=False when creating the buttons -3. Make the Button text be the event you want to see returned to you or set the button's Key to that value -4. After creating / finalizing the window, make the tkinter bind call, passing `element.ButtonReboundCallback` as the function to call. +The `key_modifier` in the `Element.bind` call is something that is added to your key. If your key is a string, then this modifier will be appended to your key and the event will be a single string. -This sample code binds not an element events but events from the window itself. In this case, Focus events. +If your element's key is not a string, then a tuple will be returned as the event +(your_key, key_modifier) + +This will enable you to continue to use your weird, non-string keys. Just be aware that you'll be getting back a tuple instead of your key in these situations. + +The best example of when this can happen is in a Minesweeper game where each button is already a tuple of the (x,y) position of the button. Normal left clicks will return (x,y). A right click that was generated as a result of bind call will be ((x,y), key_modifier). + +It'll be tricky for the user to parse these events, but it's assumed you're an advanced user if you're using this capability and are also using non-string keys. + +There are 2 member variables that have also been added as shown in the documentation for the bind methods. This added variable contains the tkinter specific event information. In other words, the 'event' that tkinter normally sends back when a callback happens. + +Here is sample code that shows how to make these calls. + +Three events are being bound. + +1. Any button clicks in the window will return an event "Window Click" from window.read() +2. Right clicking the "Go" buttons will return an event "Go+RIGHT CLICK+" from window.read() +3. When the Input Element receives focus, an event "-IN-+FOCUS+" will be returned from window.read() ```python import PySimpleGUI as sg +sg.change_look_and_feel('Dark Green 2') + layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], - [sg.Button('Do Something'), sg.Button('Exit'), - sg.Button('-FOCUS-IN-', visible=False), sg.Button('-FOCUS-OUT-', visible=False)] ] + [sg.Input(key='-IN-'), sg.Text(size=(15,1), key='-OUT-')], + [sg.Button('Go'), sg.Button('Exit')] + ] window = sg.Window('Window Title', layout, finalize=True) -window.TKroot.bind("", window['-FOCUS-IN-'].ButtonReboundCallback) -window.TKroot.bind("", window['-FOCUS-OUT-'].ButtonReboundCallback) -``` +window['-IN-'].bind("", '+FOCUS+') +window.bind("", 'Window Click') +window['Go'].bind("", '+RIGHT CLICK+') -This code binds the right mouse button to a button so that you can right click a button and get a different event than if you left clicked it. - -```python -import PySimpleGUI as sg - -layout = [ [sg.Text('My Window')], - [sg.Input(key='-IN-'), sg.Text('', key='-OUT-')], - [sg.Button('Do Something'), sg.Button('Right Click Me')], - [sg.Button('-RIGHT-', visible=False)] - ] - -window = sg.Window('Window Title', layout, finalize=True) - -window['Right Click Me'].Widget.bind("", window['-RIGHT-'].ButtonReboundCallback) - -has_focus = True while True: # Event Loop event, values = window.read() print(event, values) if event in (None, 'Exit'): break -window.close() + +window.close(); del window ``` +There is no way to "unbind" and event at this time. (sorry, didn't think of it before releasing) --- ------------------ @@ -5353,6 +5431,7 @@ Button(button_text="", size=(None, None), auto_size_button=None, button_color=None, + disabled_button_color=None, use_ttk_buttons=None, font=None, bind_return_key=False, @@ -5384,6 +5463,7 @@ Parameter Descriptions: |size|Tuple[int, int] (width, height) of the button in characters wide, rows high| |auto_size_button|(bool) if True the button size is sized to fit the text| |button_color|Tuple[str, str] (text color, background color) of button. Easy to remember which is which if you say "ON" between colors. "red" on "green".| +|disabled_button_color|Tuple[str, str] colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color| |use_ttk_buttons|(bool) True = use ttk buttons. False = do not use ttk buttons. None (Default) = use ttk buttons only if on a Mac and not with button images| |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |bind_return_key|(bool) If True the return key will cause this button to be pressed| @@ -5393,58 +5473,6 @@ Parameter Descriptions: |visible|(bool) set visibility state of the element| |metadata|(Any) User metadata that can be set to ANYTHING| -### ButtonCallBack - -Not user callable! Called by tkinter when a button is clicked. This is where all the fun begins! - -```python -ButtonCallBack() -``` - -### ButtonPressCallBack - -Not a user callable method. Callback called by tkinter when a "realtime" button is pressed - -``` -ButtonPressCallBack(parm) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|parm|Event info passed in by tkinter| - -### ButtonReboundCallback - -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. - -``` -ButtonReboundCallback(event) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|event|(unknown) Not used in this function.| - -### ButtonReleaseCallBack - -Not a user callable function. Called by tkinter when a "realtime" button is released - -``` -ButtonReleaseCallBack(parm) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|parm|the event info from tkinter| - ### Click Generates a click of the button as if the user clicked the button @@ -5504,6 +5532,7 @@ Update(text=None, image_filename=None, visible=None, image_subsample=None, + disabled_button_color=(None, None), image_size=None) ``` @@ -5516,15 +5545,31 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |image_data|Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data| |image_filename|(str) image filename if there is a button image. GIFs and PNGs only.| +|disabled_button_color|Tuple[str, str] colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color| |visible|(bool) control visibility of element| |image_subsample|(int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc| |image_size|Tuple[int, int] Size of the image in pixels (width, height)| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -5550,7 +5595,9 @@ click() Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -5559,6 +5606,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -5653,6 +5701,7 @@ update(text=None, image_filename=None, visible=None, image_subsample=None, + disabled_button_color=(None, None), image_size=None) ``` @@ -5665,6 +5714,7 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |image_data|Union[bytes, str] Raw or Base64 representation of the image to put on button. Choose either filename or data| |image_filename|(str) image filename if there is a button image. GIFs and PNGs only.| +|disabled_button_color|Tuple[str, str] colors to use when button is disabled (text, background). Use None for a color if don't want to change. Only ttk buttons support both text and background colors. tk buttons only support changing text color| |visible|(bool) control visibility of element| |image_subsample|(int) amount to reduce the size of the image. Divides the size by this number. 2=1/2, 3=1/3, 4=1/4, etc| |image_size|Tuple[int, int] Size of the image in pixels (width, height)| @@ -5719,9 +5769,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -5785,11 +5834,26 @@ Parameter Descriptions: |menu_definition|(List[List]) New menu definition (in menu definition format)| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -5806,7 +5870,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -5815,6 +5881,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -5932,9 +5999,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -5978,11 +6044,26 @@ Parameter Descriptions: #### property: TKCanvas +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -5999,7 +6080,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -6008,6 +6091,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -6128,9 +6212,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -6199,11 +6282,26 @@ Parameter Descriptions: |disabled|(bool) disable or enable element| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -6220,7 +6318,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -6229,6 +6329,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -6366,25 +6467,10 @@ Parameter Descriptions: |element_justification|(str) All elements inside the Column will have this justification 'left', 'right', 'center' are valid values| |metadata|(Any) User metadata that can be set to ANYTHING| -### AddRow - -Not recommended user call. Used to add rows of Elements to the Column Element. - -``` -AddRow(args) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|List[Element] The list of elements for this row| - ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -6396,22 +6482,6 @@ Parameter Descriptions: |---|---| |event|(unknown) Not used in this function.| -### Layout - -Can use like the Window.Layout method, but it's better to use the layout parameter when creating - -``` -Layout(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|List[List[Element]] The rows of Elements| -||| -| **return** | (Column) Used for chaining | - ### SetFocus Sets the current focus to be on this element @@ -6468,11 +6538,26 @@ Parameter Descriptions: |---|---| |*args|List[Element] The list of elements for this row| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -6489,7 +6574,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -6498,6 +6585,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -6646,9 +6734,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -6725,11 +6812,26 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -6746,7 +6848,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -6755,6 +6859,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -6908,25 +7013,10 @@ Parameter Descriptions: |element_justification|(str) All elements inside the Frame will have this justification 'left', 'right', 'center' are valid values| |metadata|(Any) User metadata that can be set to ANYTHING| -### AddRow - -Not recommended user call. Used to add rows of Elements to the Frame Element. - -``` -AddRow(args) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|List[Element] The list of elements for this row| - ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -6938,22 +7028,6 @@ Parameter Descriptions: |---|---| |event|(unknown) Not used in this function.| -### Layout - -Can use like the Window.Layout method, but it's better to use the layout parameter when creating - -``` -Layout(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|List[List[Element]] The rows of Elements| -||| -| **return** | (Frame) Used for chaining | - ### SetFocus Sets the current focus to be on this element @@ -6997,25 +7071,26 @@ Parameter Descriptions: |value|(Any) New text value to show on frame| |visible|(bool) control visibility of element| -### add_row +### bind -Not recommended user call. Used to add rows of Elements to the Frame Element. +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event ``` -add_row(args) +bind(bind_string, key_modifier) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|*args|List[Element] The list of elements for this row| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -7032,7 +7107,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -7041,6 +7118,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -7061,22 +7139,6 @@ Hide the entire row an Element is located on. hide_row() ``` -### layout - -Can use like the Window.Layout method, but it's better to use the layout parameter when creating - -``` -layout(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|List[List[Element]] The rows of Elements| -||| -| **return** | (Frame) Used for chaining | - ### set_focus Sets the current focus to be on this element @@ -7222,9 +7284,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -7236,20 +7297,6 @@ Parameter Descriptions: |---|---| |event|(unknown) Not used in this function.| -### ButtonReleaseCallBack - -Not a user callable method. Used to get Graph click events. Called by tkinter when button is released - -``` -ButtonReleaseCallBack(event) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|event|(event) event info from tkinter. Note not used in this method| - ### DeleteFigure Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive @@ -7298,7 +7345,8 @@ Draws a circle, cenetered at the location provided. Can set the fill and outlin DrawCircle(center_location, radius, fill_color=None, - line_color="black") + line_color="black", + line_width=1) ``` Parameter Descriptions: @@ -7309,6 +7357,7 @@ Parameter Descriptions: |radius|Union[int, float] Radius in user's coordinate values.| |fill_color|(str) color of the point to draw| |line_color|(str) color of the outer line that goes around the circle (sorry, can't set thickness)| +|line_width|(int) width of the line around the circle, the outline, in pixels| ||| | **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the circle | @@ -7368,7 +7417,8 @@ Draws an oval based on coordinates in user coordinate system. Provide the locati DrawOval(top_left, bottom_right, fill_color=None, - line_color=None) + line_color=None, + line_width=1) ``` Parameter Descriptions: @@ -7379,6 +7429,7 @@ Parameter Descriptions: |bottom_right|Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle| |fill_color|(str) color of the interrior| |line_color|(str) color of outline of oval| +|line_width|(int) width of the line around the oval, the outline, in pixels| ||| | **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the oval | @@ -7459,19 +7510,37 @@ Erase the Graph - Removes all figures previously "drawn" using the Graph methods Erase() ``` -### MotionCallBack +### GetBoundingBox -Not a user callable method. Used to get Graph mouse motion events. Called by tkinter when mouse moved +Given a figure, returns the upper left and lower right bounding box coordinates ``` -MotionCallBack(event) +GetBoundingBox(figure) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|event|(event) event info from tkinter. Contains the x and y coordinates of a mouse| +|figure|a previously drawing figure| +||| +| **return** | Union[Tuple[int, int, int, int], Tuple[float, float, float, float]] (upper left x, upper left y, lower right x, lower right y | + +### GetFiguresAtLocation + +Returns a list of figures located at a particular x,y location within the Graph + +``` +GetFiguresAtLocation(location) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|location|Union[Tuple[int, int], Tuple[float, float]] point to check| +||| +| **return** | List[int] a list of previously drawn "Figures" (returned from the drawing primitives) | ### Move @@ -7586,6 +7655,22 @@ Parameter Descriptions: |background_color|color of background| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### bring_figure_to_front Changes Z-order of figures on the Graph. Brings the indicated figure to the front of all other drawn figures @@ -7616,9 +7701,8 @@ Parameter Descriptions: ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -7630,20 +7714,6 @@ Parameter Descriptions: |---|---| |event|(unknown) Not used in this function.| -### button_release_call_back - -Not a user callable method. Used to get Graph click events. Called by tkinter when button is released - -``` -button_release_call_back(event) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|event|(event) event info from tkinter. Note not used in this method| - ### delete_figure Remove from the Graph the figure represented by id. The id is given to you anytime you call a drawing primitive @@ -7692,7 +7762,8 @@ Draws a circle, cenetered at the location provided. Can set the fill and outlin draw_circle(center_location, radius, fill_color=None, - line_color="black") + line_color="black", + line_width=1) ``` Parameter Descriptions: @@ -7703,6 +7774,7 @@ Parameter Descriptions: |radius|Union[int, float] Radius in user's coordinate values.| |fill_color|(str) color of the point to draw| |line_color|(str) color of the outer line that goes around the circle (sorry, can't set thickness)| +|line_width|(int) width of the line around the circle, the outline, in pixels| ||| | **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the circle | @@ -7762,7 +7834,8 @@ Draws an oval based on coordinates in user coordinate system. Provide the locati draw_oval(top_left, bottom_right, fill_color=None, - line_color=None) + line_color=None, + line_width=1) ``` Parameter Descriptions: @@ -7773,6 +7846,7 @@ Parameter Descriptions: |bottom_right|Union[Tuple[int, int], Tuple[float, float]] the bottom right point of bounding rectangle| |fill_color|(str) color of the interrior| |line_color|(str) color of outline of oval| +|line_width|(int) width of the line around the oval, the outline, in pixels| ||| | **return** | Union[int, None] id returned from tkinter that you'll need if you want to manipulate the oval | @@ -7858,7 +7932,9 @@ erase() Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -7867,6 +7943,39 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| + +### get_bounding_box + +Given a figure, returns the upper left and lower right bounding box coordinates + +``` +get_bounding_box(figure) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|figure|a previously drawing figure| +||| +| **return** | Union[Tuple[int, int, int, int], Tuple[float, float, float, float]] (upper left x, upper left y, lower right x, lower right y | + +### get_figures_at_location + +Returns a list of figures located at a particular x,y location within the Graph + +``` +get_figures_at_location(location) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|location|Union[Tuple[int, int], Tuple[float, float]] point to check| +||| +| **return** | List[int] a list of previously drawn "Figures" (returned from the drawing primitives) | ### get_size @@ -7887,20 +7996,6 @@ Hide the entire row an Element is located on. hide_row() ``` -### motion_call_back - -Not a user callable method. Used to get Graph mouse motion events. Called by tkinter when mouse moved - -``` -motion_call_back(event) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|event|(event) event info from tkinter. Contains the x and y coordinates of a mouse| - ### move Moves the entire drawing area (the canvas) by some delta from the current position. Units are indicated in your coordinate system indicated number of ticks in your coordinate system @@ -8074,9 +8169,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -8152,11 +8246,26 @@ Parameter Descriptions: |source|Union[str,bytes] Filename or Base64 encoded string containing Animated GIF| |time_between_frames|(int) Number of milliseconds to wait between showing frames| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -8173,7 +8282,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -8182,6 +8293,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -8342,9 +8454,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -8420,11 +8531,26 @@ Parameter Descriptions: |background_color|(str) change color of the background| |move_cursor_to|Union[int, str] Moves the cursor to a particular offset. Defaults to 'end'| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -8441,7 +8567,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -8450,6 +8578,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -8610,9 +8739,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -8708,11 +8836,26 @@ Parameter Descriptions: |scroll_to_index|(int) scroll the listbox so that this index is the first shown| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -8729,7 +8872,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -8738,6 +8883,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_indexes @@ -8909,9 +9055,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -8966,11 +9111,26 @@ Parameter Descriptions: |menu_definition|List[List[Tuple[str, List[str]]]| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -8987,7 +9147,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -8996,6 +9158,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -9139,9 +9302,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -9202,6 +9364,8 @@ Update(value=None, font=None, text_color=None, background_color=None, + text_color_for_value=None, + background_color_for_value=None, visible=None, autoscroll=None) ``` @@ -9219,11 +9383,26 @@ Parameter Descriptions: |visible|(bool) set visibility state of the element| |autoscroll|(bool) if True then contents of element are scrolled down when new text is added to the end| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -9240,7 +9419,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -9249,6 +9430,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -9342,6 +9524,8 @@ update(value=None, font=None, text_color=None, background_color=None, + text_color_for_value=None, + background_color_for_value=None, visible=None, autoscroll=None) ``` @@ -9400,9 +9584,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -9462,11 +9645,26 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -9483,7 +9681,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -9492,6 +9692,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -9618,9 +9819,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -9689,11 +9889,26 @@ Parameter Descriptions: |value|(str) string that will replace current contents of the output area| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -9848,9 +10063,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -9904,11 +10118,26 @@ Parameter Descriptions: |---|---| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -9925,7 +10154,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -9934,6 +10165,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -10058,9 +10290,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -10129,11 +10360,26 @@ Parameter Descriptions: |current_count|(int) sets the current value| |max|(int) changes the max value| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -10150,7 +10396,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -10159,6 +10407,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -10307,9 +10556,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -10385,11 +10633,26 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -10406,7 +10669,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -10415,6 +10680,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -10577,9 +10843,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -10639,11 +10904,26 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -10660,7 +10940,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -10669,6 +10951,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -10805,9 +11088,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -10879,11 +11161,26 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -10900,7 +11197,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -10909,6 +11208,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -11057,9 +11357,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -11121,11 +11420,26 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) set visibility state of the element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -11142,7 +11456,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -11151,6 +11467,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -11286,25 +11603,10 @@ Parameter Descriptions: |element_justification|(str) All elements inside the Tab will have this justification 'left', 'right', 'center' are valid values| |metadata|(Any) User metadata that can be set to ANYTHING| -### AddRow - -Not recommended use call. Used to add rows of Elements to the Frame Element. - -``` -AddRow(args) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|List[Element] The list of elements for this row| - ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -11316,22 +11618,6 @@ Parameter Descriptions: |---|---| |event|(unknown) Not used in this function.| -### Layout - -Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements - -``` -Layout(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|List[List[Element]] The list of rows| -||| -| **return** | (Tab) used for chaining | - ### Select Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first! @@ -11383,25 +11669,26 @@ Parameter Descriptions: |disabled|(bool) disable or enable state of the element| |visible|(bool) control visibility of element| -### add_row +### bind -Not recommended use call. Used to add rows of Elements to the Frame Element. +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event ``` -add_row(args) +bind(bind_string, key_modifier) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|*args|List[Element] The list of elements for this row| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -11418,7 +11705,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -11427,6 +11716,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -11447,22 +11737,6 @@ Hide the entire row an Element is located on. hide_row() ``` -### layout - -Not user callable. Use layout parameter instead. Creates the layout using the supplied rows of Elements - -``` -layout(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|List[List[Element]] The list of rows| -||| -| **return** | (Tab) used for chaining | - ### select Create a tkinter event that mimics user clicking on a tab. Must have called window.Finalize / Read first! @@ -11546,7 +11820,9 @@ Parameter Descriptions: TabGroup(layout, tab_location=None, title_color=None, + tab_background_color=None, selected_title_color=None, + selected_background_color=None, background_color=None, font=None, change_submits=False, @@ -11567,8 +11843,10 @@ Parameter Descriptions: |layout|List[List[Tab]] Layout of Tabs. Different than normal layouts. ALL Tabs should be on first row| |tab_location|(str) location that tabs will be displayed. Choices are left, right, top, bottom, lefttop, leftbottom, righttop, rightbottom, bottomleft, bottomright, topleft, topright| |title_color|(str) color of text on tabs| -|selected_title_color|(str) color of tab when it is selected| -|background_color|(str) color of background of tabs| +|tab_background_color|(str) color of all tabs that are not selected| +|selected_title_color|(str) color of tab text when it is selected| +|selected_background_color|(str) color of tab when it is selected| +|background_color|(str) color of background area that tabs are located on| |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |change_submits|(bool) * DEPRICATED DO NOT USE! Same as enable_events| |enable_events|(bool) If True then switching tabs will generate an Event| @@ -11580,25 +11858,10 @@ Parameter Descriptions: |visible|(bool) set visibility state of the element| |metadata|(Any) User metadata that can be set to ANYTHING| -### AddRow - -Not recommended user call. Used to add rows of Elements to the Frame Element. - -``` -AddRow(args) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|List[Element] The list of elements for this row| - ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -11639,22 +11902,6 @@ are using this method correctly? |---|---| | **return** | Union[Any, None] The key of the currently selected tab or the tab's text if it has no key | -### Layout - -Can use like the Window.Layout method, but it's better to use the layout parameter when creating - -``` -Layout(rows) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|rows|List[List[Element]] The rows of Elements| -||| -| **return** | (Frame) Used for chaining | - ### SetFocus Sets the current focus to be on this element @@ -11683,25 +11930,26 @@ Parameter Descriptions: |---|---| |tooltip_text|(str) the text to show in tooltip.| -### add_row +### bind -Not recommended user call. Used to add rows of Elements to the Frame Element. +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event ``` -add_row(args) +bind(bind_string, key_modifier) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|*args|List[Element] The list of elements for this row| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -11718,7 +11966,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -11727,6 +11977,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### find_key_from_tab_name @@ -11863,6 +12114,9 @@ Table(values, text_color=None, background_color=None, alternating_row_color=None, + header_text_color=None, + header_background_color=None, + header_font=None, row_colors=None, vertical_scroll_only=True, hide_vertical_scroll=False, @@ -11898,7 +12152,10 @@ Parameter Descriptions: |text_color|(str) color of the text| |background_color|(str) color of background| |alternating_row_color|(str) if set then every other row will have this color in the background.| -|row_colors|| +|header_text_color|(str) sets the text color for the header| +|header_background_color|(str) sets the background color for the header| +|header_font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|row_colors|List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Sets the colors of listed rows to the color(s) provided (note the optional foreground color)| |vertical_scroll_only|(bool) if True only the vertical scrollbar will be visible| |hide_vertical_scroll|(bool) if True vertical scrollbar will be hidden| |size|Tuple[int, int] DO NOT USE! Use num_rows instead| @@ -11914,9 +12171,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -11992,11 +12248,26 @@ Parameter Descriptions: |alternating_row_color|(str) the color to make every other row| |row_colors|List[Union[Tuple[int, str], Tuple[Int, str, str]] list of tuples of (row, background color) OR (row, foreground color, background color). Changes the colors of listed rows to the color(s) provided (note the optional foreground color)| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -12013,7 +12284,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -12022,6 +12295,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get @@ -12097,36 +12371,6 @@ Parameter Descriptions: |---|---| |tooltip_text|(str) the text to show in tooltip.| -### treeview_double_click - -Not user callable. Callback function that is called when something is selected from Table. -Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read - -``` -treeview_double_click(event) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|event|(unknown) event information from tkinter| - -### treeview_selected - -Not user callable. Callback function that is called when something is selected from Table. -Stores the selected rows in Element as they are being selected. If events enabled, then returns from Read - -``` -treeview_selected(event) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|event|(unknown) event information from tkinter| - ### unhide_row Unhides (makes visible again) the row container that the Element is located on. @@ -12208,9 +12452,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -12272,11 +12515,26 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) set visibility state of the element| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -12293,7 +12551,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -12302,6 +12562,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -12396,6 +12657,86 @@ Parameter Descriptions: |font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |visible|(bool) set visibility state of the element| +## ToolTip Element + + Create a tooltip for a given widget + (inspired by https://stackoverflow.com/a/36221216) + This is an INTERNALLY USED only class. Users should not refer to this class at all. + +``` +ToolTip(widget, + text, + timeout=400) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|widget|(widget type varies) The tkinter widget| +|text|(str) text for the tooltip. It can inslude| +|timeout|(int) Time in milliseconds that mouse must remain still before tip is shown| + +### enter + +Called by tkinter when mouse enters a widget + +``` +enter(event=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|from tkinter. Has x,y coordinates of mouse| + +### hidetip + +Destroy the tooltip window + +```python +hidetip() +``` + +### leave + +Called by tktiner when mouse exits a widget + +``` +leave(event=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|event|from tkinter. Event info that's not used by function.| + +### schedule + +Schedule a timer to time how long mouse is hovering + +```python +schedule() +``` + +### showtip + +Creates a topoltip window with the tooltip text inside of it + +```python +showtip() +``` + +### unschedule + +Cancel timer used to time mouse hover + +```python +unschedule() +``` + ## Tree Element Tree Element - Presents data in a tree-like manner, much like a file/folder browser. Uses the TreeData class @@ -12418,6 +12759,9 @@ Tree(data=None, justification="right", text_color=None, background_color=None, + header_text_color=None, + header_background_color=None, + header_font=None, num_rows=None, row_height=None, pad=None, @@ -12448,6 +12792,9 @@ Parameter Descriptions: |justification|(str) 'left', 'right', 'center' are valid choices| |text_color|(str) color of the text| |background_color|(str) color of background| +|header_text_color|(str) sets the text color for the header| +|header_background_color|(str) sets the background color for the header| +|header_font|Union[str, Tuple[str, int]] specifies the font family, size, etc| |num_rows|(int) The number of rows of the table to display at a time| |row_height|(int) height of a single row in pixels| |pad|(int, int) or ((int, int),(int,int)) Amount of padding to put around element (left/right, top/bottom) or ((left, right), (top, bottom))| @@ -12459,9 +12806,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -12539,11 +12885,26 @@ Parameter Descriptions: |---|---| |node|(TreeData) The node to insert. Will insert all nodes from starting point downward, recursively| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -12560,7 +12921,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -12569,6 +12932,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -12767,9 +13131,8 @@ Parameter Descriptions: ### ButtonReboundCallback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` ButtonReboundCallback(event) @@ -12809,11 +13172,26 @@ Parameter Descriptions: |---|---| |tooltip_text|(str) the text to show in tooltip.| +### bind + +Used to add tkinter events to an Element. +The tkinter specific data is in the Element's member variable user_bind_event + +``` +bind(bind_string, key_modifier) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key_modifier|Additional data to be added to the element's key when event is returned| + ### button_rebound_callback -Used in combination with tkinter's widget.bind function. If you wish to have a double-click for a button to call back the button's normal -callback routine, then you should target your call to tkinter's bind method to point to this function which will in turn call the button -callback function that is normally called. +*** DEPRICATED *** +Use Element.bind instead ``` button_rebound_callback(event) @@ -12830,7 +13208,9 @@ Parameter Descriptions: Causes the Element to expand to fill available space in the X and Y directions. Can specify which or both directions ``` -expand(expand_x=False, expand_y=False) +expand(expand_x=False, + expand_y=False, + expand_row=True) ``` Parameter Descriptions: @@ -12839,6 +13219,7 @@ Parameter Descriptions: |---|---| |expand_x|(Bool) If True Element will expand in the Horizontal directions| |expand_y|(Bool) If True Element will expand in the Vertical directions| +|expand_row|(Bool) If True the row containing the element will also expand. Without this your element is "trapped" within the row| ### get_size @@ -12911,7 +13292,7 @@ Unhides (makes visible again) the row container that the Element is located on. unhide_row() ``` -## Window +## Window Element Represents a single Window @@ -13572,6 +13953,22 @@ A property that changes the current alpha channel value (internal value) |---|---| | **return** | (float) the current alpha channel setting according to self, not read directly from tkinter | +### bind + +Used to add tkinter events to a Window. +The tkinter specific data is in the Window's member variable user_bind_event + +``` +bind(bind_string, key) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|bind_string|The string tkinter expected in its bind function| +|key|The event that will be generated when the tkinter event occurs| + ### bring_to_front Brings this window to the top of all other windows (perhaps may not be brought before a window made to "stay @@ -14071,6 +14468,8 @@ call and then have that same source run on plain PySimpleGUI. |---|---| | **return** | | +## Function Reference + ``` CButton(button_text, image_filename=None, @@ -14199,59 +14598,6 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| -Change the "color scheme" of all future PySimpleGUI Windows. -The scheme are string names that specify a group of colors. Background colors, text colors, button colors. -There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel -The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. -The original list was (prior to a major rework and renaming)... these names still work... -SystemDefault -SystemDefaultForReal -Material1 -Material2 -Reddit -Topanga -GreenTan -Dark -LightGreen -Dark2 -Black -Tan -TanBlue -DarkTanBlue -DarkAmber -DarkBlue -Reds -Green -BluePurple -Purple -BlueMono -GreenMono -BrownBlue -BrightColors -NeutralBlue -Kayak -SandyBeach -TealMono - -In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: -The "Formula" is: -["Dark" or "Light"] Color Number -Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black -The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. -Default = The default settings (only button color is different than system default) -Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - -``` -ChangeLookAndFeel(index, force=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|index|(str) the name of the index into the Look and Feel table| -|force|(bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors| - ``` CloseButton(button_text, image_filename=None, @@ -14416,39 +14762,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -``` -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, - do_not_reroute_stdout=True) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -EasyPrintClose() -``` - ``` Exit(button_text="Exit", size=(None, None), @@ -14558,6 +14871,9 @@ Parameter Descriptions: ||| | **return** | (Button) | +Allows browsing of multiple files. File list is returned as a single list with the delimeter defined using the variable +BROWSE_FILES_DELIMETER. This defaults to ';' but is changable by the user + ``` FilesBrowse(button_text="Browse", target=(555666777, -1), @@ -14680,12 +14996,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -Get a list of the valid values to pass into your call to change_look_and_feel - -``` -ListOfLookAndFeelValues() -> List[str] - list of valid string values -``` - ``` No(button_text="No", size=(None, None), @@ -14809,46 +15119,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -``` -OneLineProgressMeter(title, - current_value, - max_value, - key, - args, - orientation="v", - bar_color=(None, None), - button_color=None, - size=(20, 20), - border_width=None, - grab_anywhere=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|title|text to display| -|current_value|current progressbar value| -|max_value|max value of progressbar| -|key|Used with window.FindElement and with return values to uniquely identify this element| -|*args|stuff to output.| -|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| -|bar_color|| -|button_color|button color (foreground, background)| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| -|border_width|width of border around element| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| - -``` -OneLineProgressMeterCancel(key) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|key|Used with window.FindElement and with return values to uniquely identify this element| - ``` Open(button_text="Open", size=(None, None), @@ -14880,240 +15150,6 @@ Parameter Descriptions: |pad|Amount of padding to put around element| |key|Used with window.FindElement and with return values to uniquely identify this element| -Show Popup box that doesn't block and closes itself - -``` -PopupQuick(args, - title=None, - button_type=0, - button_color=None, - background_color=None, - text_color=None, - auto_close=True, - auto_close_duration=2, - non_blocking=True, - icon=None, - line_width=None, - font=None, - no_titlebar=False, - grab_anywhere=False, - keep_on_top=False, - location=(None, None)) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|title|| -|button_type|(Default value = POPUP_BUTTONS_OK)| -|button_color|button color (foreground, background)| -|background_color|color of background| -|text_color|color of the text| -|auto_close|(Default = True)| -|auto_close_duration|(Default value = 2)| -|non_blocking|(Default = True)| -|icon|Icon to display| -|line_width|Width of lines in characters| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|location|| - -Show Popup window with no titlebar, doesn't block, and auto closes itself. - -``` -PopupQuickMessage(args, - title=None, - button_type=5, - button_color=None, - background_color=None, - text_color=None, - auto_close=True, - auto_close_duration=2, - non_blocking=True, - icon=None, - line_width=None, - font=None, - no_titlebar=True, - grab_anywhere=False, - keep_on_top=False, - location=(None, None)) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|title|| -|button_type|(Default value = POPUP_BUTTONS_NO_BUTTONS)| -|button_color|button color (foreground, background)| -|background_color|color of background| -|text_color|color of the text| -|auto_close|(Default = True)| -|auto_close_duration|(Default value = 2)| -|non_blocking|(Default = True)| -|icon|Icon to display| -|line_width|Width of lines in characters| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = True)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|location|| - -Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you -want, just like a print statement. - -``` -PopupScrolled(args, - title=None, - button_color=None, - background_color=None, - text_color=None, - yes_no=False, - auto_close=False, - auto_close_duration=None, - size=(None, None), - location=(None, None), - non_blocking=False, - no_titlebar=False, - grab_anywhere=False, - keep_on_top=False, - font=None) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|(Any) Variable number of items to display| -|title|(str) Title to display in the window.| -|button_color|Tuple[str, str] button color (foreground, background)| -|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| -|auto_close|(bool) if True window will close itself| -|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| -|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| -||| -| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | - -Popup that closes itself after some time period - -``` -PopupTimed(args, - title=None, - button_type=0, - button_color=None, - background_color=None, - text_color=None, - auto_close=True, - auto_close_duration=None, - non_blocking=False, - icon=None, - line_width=None, - font=None, - no_titlebar=False, - grab_anywhere=False, - keep_on_top=False, - location=(None, None)) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|title|| -|button_type|(Default value = POPUP_BUTTONS_OK)| -|button_color|button color (foreground, background)| -|background_color|color of background| -|text_color|color of the text| -|auto_close|(Default = True)| -|auto_close_duration|| -|non_blocking|(Default = False)| -|icon|Icon to display| -|line_width|Width of lines in characters| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|location|| - -Display Popup with Yes and No buttons - -``` -PopupYesNo(args, - title=None, - button_color=None, - background_color=None, - text_color=None, - auto_close=False, - auto_close_duration=None, - non_blocking=False, - icon=None, - line_width=None, - font=None, - no_titlebar=False, - grab_anywhere=False, - keep_on_top=False, - location=(None, None)) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|title|| -|button_color|button color (foreground, background)| -|background_color|color of background| -|text_color|color of the text| -|auto_close|(Default = False)| -|auto_close_duration|| -|non_blocking|(Default = False)| -|icon|Icon to display| -|line_width|Width of lines in characters| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|location|Location on screen to display| -||| -| **return** | Union["Yes", "No", None] | - -``` -Print(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -PrintClose() -``` - ``` Quit(button_text="Quit", size=(None, None), @@ -15503,18 +15539,6 @@ Parameter Descriptions: ||| | **return** | (Button) | -Time your code easily.... start the timer. - -``` -TimerStart() -``` - -Time your code easily.... stop the timer and print the number of ms since the timer start - -``` -TimerStop() -``` - ``` Yes(button_text="Yes", size=(None, None), @@ -15548,58 +15572,7 @@ Parameter Descriptions: ||| | **return** | (Button) | -Change the "color scheme" of all future PySimpleGUI Windows. -The scheme are string names that specify a group of colors. Background colors, text colors, button colors. -There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel -The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. -The original list was (prior to a major rework and renaming)... these names still work... -SystemDefault -SystemDefaultForReal -Material1 -Material2 -Reddit -Topanga -GreenTan -Dark -LightGreen -Dark2 -Black -Tan -TanBlue -DarkTanBlue -DarkAmber -DarkBlue -Reds -Green -BluePurple -Purple -BlueMono -GreenMono -BrownBlue -BrightColors -NeutralBlue -Kayak -SandyBeach -TealMono - -In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: -The "Formula" is: -["Dark" or "Light"] Color Number -Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black -The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. -Default = The default settings (only button color is different than system default) -Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) - -``` -change_look_and_feel(index, force=False) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|index|(str) the name of the index into the Look and Feel table| -|force|(bool) if True allows Macs to use the look and feel feature. Otherwise Macs are blocked due to problems with button colors| +## Debug Window Output ``` easy_print(args, @@ -15612,7 +15585,9 @@ easy_print(args, no_button=False, grab_anywhere=False, keep_on_top=False, - do_not_reroute_stdout=True) + do_not_reroute_stdout=True, + text_color=None, + background_color=None) ``` Parameter Descriptions: @@ -15645,7 +15620,9 @@ eprint(args, no_button=False, grab_anywhere=False, keep_on_top=False, - do_not_reroute_stdout=True) + do_not_reroute_stdout=True, + text_color=None, + background_color=None) ``` Parameter Descriptions: @@ -15663,56 +15640,152 @@ Parameter Descriptions: |grab_anywhere|If True can grab anywhere to move the window (Default = False)| |do_not_reroute_stdout|(Default = True)| -Fills a window with values provided in a values dictionary { element_key : new_value } - ``` -fill_form_with_values(window, values_dict) +sgprint(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|window|(Window) The window object to fill| -|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| - -Get a list of the valid values to pass into your call to change_look_and_feel +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| ``` -list_of_look_and_feel_values() -> List[str] - list of valid string values +sgprint_close() ``` -The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. - ``` -main() -``` - -Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form - -``` -obj_to_string(obj, extra=" ") +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, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|obj|(Any) The object to display| -|extra|(Default value = ' ') returns (str) Formatted output of the object's values| - -Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form -Returns only the top-most object's variables instead of drilling down to dispolay more +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| ``` -obj_to_string_single_obj(obj) +EasyPrintClose() +``` + +``` +Print(args, + size=(None, None), + end=None, + sep=None, + location=(None, None), + font=None, + no_titlebar=False, + no_button=False, + grab_anywhere=False, + keep_on_top=False, + do_not_reroute_stdout=True, + text_color=None, + background_color=None) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|obj|(Any) The object to display returns (str) Formatted output of the object's values| +|*args|| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|end|| +|sep|| +|location|Location on screen to display| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|no_button|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|do_not_reroute_stdout|(Default = True)| + +``` +PrintClose() +``` + +## OneLineProgressMeter + +``` +OneLineProgressMeter(title, + current_value, + max_value, + key, + args, + orientation="v", + bar_color=(None, None), + button_color=None, + size=(20, 20), + border_width=None, + grab_anywhere=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|title|text to display| +|current_value|current progressbar value| +|max_value|max value of progressbar| +|key|Used with window.FindElement and with return values to uniquely identify this element| +|*args|stuff to output.| +|orientation|'horizontal' or 'vertical' ('h' or 'v' work) (Default value = 'vertical')(Default value = 'v')| +|bar_color|| +|button_color|button color (foreground, background)| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high (Default value = DEFAULT_PROGRESS_BAR_SIZE)| +|border_width|width of border around element| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| + +``` +OneLineProgressMeterCancel(key) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|key|Used with window.FindElement and with return values to uniquely identify this element| ``` one_line_progress_meter(title, @@ -15754,6 +15827,902 @@ Parameter Descriptions: |---|---| |key|Used with window.FindElement and with return values to uniquely identify this element| +## Popup Functions + +Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the +"print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. + +``` +Popup(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + button_type=0, + auto_close=False, + auto_close_duration=None, + custom_text=(None, None), + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|(Any) Variable number of your arguments. Load up the call with stuff to see!| +|title|(str) Optional title for the window. If none provided, the first arg will be used instead.| +|button_color|Tuple[str, str] Color of the buttons shown (text color, button color)| +|background_color|(str) Window's background color| +|text_color|(str) text color| +|button_type|(enum) NOT USER SET! Determines which pre-defined buttons will be shown (Default value = POPUP_BUTTONS_OK). There are many Popup functions and they call Popup, changing this parameter to get the desired effect.| +|auto_close|(bool) If True the window will automatically close| +|auto_close_duration|(int) time in seconds to keep window open before closing it automatically| +|custom_text|Union[Tuple[str, str], str] A string or pair of strings that contain the text to display on the buttons| +|non_blocking|(bool) If True then will immediately return from the function without waiting for the user's input.| +|icon|Union[str, bytes] icon to display on the window. Same format as a Window call| +|line_width|(int) Width of lines in characters. Defaults to MESSAGE_BOX_LINE_WIDTH| +|font|Union[str, tuple(font name, size, modifiers) specifies the font family, size, etc| +|no_titlebar|(bool) If True will not show the frame around the window and the titlebar across the top| +|grab_anywhere|(bool) If True can grab anywhere to move the window. If no_titlebar is True, grab_anywhere should likely be enabled too| +|location|Tuple[int, int] Location on screen to display the top left corner of window. Defaults to window centered on screen| +||| +| **return** | Union[str, None] Returns text of the button that was pressed. None will be returned if user closed window with X | + +Show animation one frame at a time. This function has its own internal clocking meaning you can call it at any frequency + and the rate the frames of video is shown remains constant. Maybe your frames update every 30 ms but your + event loop is running every 10 ms. You don't have to worry about delaying, just call it every time through the + loop. + +``` +PopupAnimated(image_source, + message=None, + background_color=None, + text_color=None, + font=None, + no_titlebar=True, + grab_anywhere=True, + keep_on_top=True, + location=(None, None), + alpha_channel=None, + time_between_frames=0, + transparent_color=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|image_source|Union[str, bytes] Either a filename or a base64 string.| +|message|(str) An optional message to be shown with the animation| +|background_color|(str) color of background| +|text_color|(str) color of the text| +|font|Union[str, tuple) specifies the font family, size, etc| +|no_titlebar|(bool) If True then the titlebar and window frame will not be shown| +|grab_anywhere|(bool) If True then you can move the window just clicking anywhere on window, hold and drag| +|keep_on_top|(bool) If True then Window will remain on top of all other windows currently shownn| +|location|(int, int) (x,y) location on the screen to place the top left corner of your window. Default is to center on screen| +|alpha_channel|(float) Window transparency 0 = invisible 1 = completely visible. Values between are see through| +|time_between_frames|(int) Amount of time in milliseconds between each frame| +|transparent_color|(str) This color will be completely see-through in your window. Can even click through| + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +PopupAnnoying(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Popup that closes itself after some time period + +``` +PopupAutoClose(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display Popup with "cancelled" button text + +``` +PopupCancel(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Popup with colored button and 'Error' as button text + +``` +PopupError(args, + title=None, + button_color=(None, None), + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|(Default = (None))| + +Display popup window with text entry field and browse button so that a file can be chosen by user. + +``` +PopupGetFile(message, + title=None, + default_path="", + default_extension="", + save_as=False, + multiple_files=False, + file_types=(('ALL Files', '*.*'),), + no_window=False, + size=(None, None), + button_color=None, + background_color=None, + text_color=None, + icon=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None), + initial_folder=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|message|(str) message displayed to user| +|title|(str) Window title| +|default_path|(str) path to display to user as starting point (filled into the input field)| +|default_extension|(str) If no extension entered by user, add this to filename (only used in saveas dialogs)| +|save_as|(bool) if True, the "save as" dialog is shown which will verify before overwriting| +|multiple_files|(bool) if True, then allows multiple files to be selected that are returned with ';' between each filename| +|file_types|Tuple[Tuple[str,str]] List of extensions to show using wildcards. All files (the default) = (("ALL Files", "*.*"),)| +|no_window|(bool) if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown| +|size|Tuple[int, int] (width, height) of the InputText Element| +|button_color|Tuple[str, str] Color of the button (text, background)| +|background_color|(str) background color of the entire window| +|text_color|(str) color of the message text| +|icon|Union[bytes, str] filename or base64 string to be used for the window's icon| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|no_titlebar|(bool) If True no titlebar will be shown| +|grab_anywhere|(bool) If True can click and drag anywhere in the window to move the window| +|keep_on_top|(bool) If True the window will remain above all current windows| +|location|Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window| +|initial_folder|(str) location in filesystem to begin browsing| +||| +| **return** | Union[str, None] string representing the file(s) chosen, None if cancelled or window closed with X | + +Display popup with text entry field and browse button so that a folder can be chosen. + +``` +PopupGetFolder(message, + title=None, + default_path="", + no_window=False, + size=(None, None), + button_color=None, + background_color=None, + text_color=None, + icon=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None), + initial_folder=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|message|(str) message displayed to user| +|title|(str) Window title| +|default_path|(str) path to display to user as starting point (filled into the input field)| +|no_window|(bool) if True, no PySimpleGUI window will be shown. Instead just the tkinter dialog is shown| +|size|Tuple[int, int] (width, height) of the InputText Element| +|button_color|Tuple[str, str] Color of the button (text, background)| +|background_color|(str) background color of the entire window| +|text_color|(str) color of the message text| +|icon|Union[bytes, str] filename or base64 string to be used for the window's icon| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|no_titlebar|(bool) If True no titlebar will be shown| +|grab_anywhere|(bool) If True can click and drag anywhere in the window to move the window| +|keep_on_top|(bool) If True the window will remain above all current windows| +|location|Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window| +|initial_folder|(str) location in filesystem to begin browsing| +||| +| **return** | Union[str, None] string representing the path chosen, None if cancelled or window closed with X | + +Display Popup with text entry field. Returns the text entered or None if closed / cancelled + +``` +PopupGetText(message, + title=None, + default_text="", + password_char="", + size=(None, None), + button_color=None, + background_color=None, + text_color=None, + icon=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|message|(str) message displayed to user| +|title|(str) Window title| +|default_text|(str) default value to put into input area| +|password_char|(str) character to be shown instead of actually typed characters| +|size|Tuple[int, int] (width, height) of the InputText Element| +|button_color|Tuple[str, str] Color of the button (text, background)| +|background_color|(str) background color of the entire window| +|text_color|(str) color of the message text| +|icon|Union[bytes, str] filename or base64 string to be used for the window's icon| +|font|Union[str, Tuple[str, int]] specifies the font family, size, etc| +|no_titlebar|(bool) If True no titlebar will be shown| +|grab_anywhere|(bool) If True can click and drag anywhere in the window to move the window| +|keep_on_top|(bool) If True the window will remain above all current windows| +|location|Tuyple[int, int] (x,y) Location on screen to display the upper left corner of window| +||| +| **return** | Union[str, None] Text entered or None if window was closed or cancel button clicked | + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +PopupNoBorder(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Show a Popup but without any buttons + +``` +PopupNoButtons(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +PopupNoFrame(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Display a Popup without a titlebar. Enables grab anywhere so you can move it + +``` +PopupNoTitlebar(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + grab_anywhere=True, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|grab_anywhere|(Default = True)| +|location|| + +Show Popup window and immediately return (does not block) + +``` +PopupNoWait(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show Popup window and immediately return (does not block) + +``` +PopupNonBlocking(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display Popup with OK button only + +``` +PopupOK(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display popup with OK and Cancel buttons + +``` +PopupOKCancel(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=..., + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|Location on screen to display| +||| +| **return** | Union["OK", "Cancel", None] | + +Show Popup box that doesn't block and closes itself + +``` +PopupQuick(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=2, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|(Default value = 2)| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show Popup window with no titlebar, doesn't block, and auto closes itself. + +``` +PopupQuickMessage(args, + title=None, + button_type=5, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=2, + non_blocking=True, + icon=None, + line_width=None, + font=None, + no_titlebar=True, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_NO_BUTTONS)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|(Default value = 2)| +|non_blocking|(Default = True)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = True)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Show a scrolled Popup window containing the user's text that was supplied. Use with as many items to print as you +want, just like a print statement. + +``` +PopupScrolled(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + yes_no=False, + auto_close=False, + auto_close_duration=None, + size=(None, None), + location=(None, None), + non_blocking=False, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + font=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|(Any) Variable number of items to display| +|title|(str) Title to display in the window.| +|button_color|Tuple[str, str] button color (foreground, background)| +|yes_no|(bool) If True, displays Yes and No buttons instead of Ok| +|auto_close|(bool) if True window will close itself| +|auto_close_duration|Union[int, float] Older versions only accept int. Time in seconds until window will close| +|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| +|location|Tuple[int, int] Location on the screen to place the upper left corner of the window| +|non_blocking|(bool) if True the call will immediately return rather than waiting on user input| +||| +| **return** | Union[str, None, TIMEOUT_KEY] Returns text of the button that was pressed. None will be returned if user closed window with X | + +Popup that closes itself after some time period + +``` +PopupTimed(args, + title=None, + button_type=0, + button_color=None, + background_color=None, + text_color=None, + auto_close=True, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_type|(Default value = POPUP_BUTTONS_OK)| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = True)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|| + +Display Popup with Yes and No buttons + +``` +PopupYesNo(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=None, + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|Location on screen to display| +||| +| **return** | Union["Yes", "No", None] | + +## Popups PEP8 Versions + Popup - Display a popup Window with as many parms as you wish to include. This is the GUI equivalent of the "print" statement. It's also great for "pausing" your program's flow until the user can read some error messages. @@ -16404,6 +17373,47 @@ Parameter Descriptions: |grab_anywhere|If True can grab anywhere to move the window (Default = False)| |location|| +Display popup with OK and Cancel buttons + +``` +popup_ok_cancel(args, + title=None, + button_color=None, + background_color=None, + text_color=None, + auto_close=False, + auto_close_duration=None, + non_blocking=False, + icon=..., + line_width=None, + font=None, + no_titlebar=False, + grab_anywhere=False, + keep_on_top=False, + location=(None, None)) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|*args|| +|title|| +|button_color|button color (foreground, background)| +|background_color|color of background| +|text_color|color of the text| +|auto_close|(Default = False)| +|auto_close_duration|| +|non_blocking|(Default = False)| +|icon|Icon to display| +|line_width|Width of lines in characters| +|font|specifies the font family, size, etc| +|no_titlebar|(Default = False)| +|grab_anywhere|If True can grab anywhere to move the window (Default = False)| +|location|Location on screen to display| +||| +| **return** | Union["OK", "Cancel", None] | + Show Popup box that doesn't block and closes itself ``` @@ -16605,38 +17615,52 @@ Parameter Descriptions: ||| | **return** | Union["Yes", "No", None] | +## PEP8 Function Bindings + +Fills a window with values provided in a values dictionary { element_key : new_value } + ``` -quit(button_text="Quit", - size=(None, None), - auto_size_button=None, - button_color=None, - disabled=False, - tooltip=None, - font=None, - bind_return_key=False, - focus=False, - pad=None, - key=None, - metadata=None) +fill_form_with_values(window, values_dict) ``` Parameter Descriptions: |Name|Meaning| |---|---| -|button_text|text in the button (Default value = 'Quit')| -|size|(w,h) w=characters-wide, h=rows-high| -|auto_size_button|True if button size is determined by button text| -|button_color|button color (foreground, background)| -|disabled|set disable state for element (Default = False)| -|tooltip|(str) text, that will appear when mouse hovers over the element| -|font|specifies the font family, size, etc| -|bind_return_key|(Default = False)| -|focus|if focus should be set to this| -|pad|Amount of padding to put around element| -|key|Used with window.FindElement and with return values to uniquely identify this element| -||| -| **return** | (Button) | +|window|(Window) The window object to fill| +|values_dict|(Dict[Any:Any]) A dictionary with element keys as key and value is values parm for Update call| + +The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the Elements. + +``` +main() +``` + +Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form + +``` +obj_to_string(obj, extra=" ") +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|obj|(Any) The object to display| +|extra|(Default value = ' ') returns (str) Formatted output of the object's values| + +Dumps an Object's values as a formatted string. Very nicely done. Great way to display an object's member variables in human form +Returns only the top-most object's variables instead of drilling down to dispolay more + +``` +obj_to_string_single_obj(obj) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|obj|(Any) The object to display returns (str) Formatted output of the object's values| Sets the icon which will be used any time a window is created if an icon is not provided when the window is created. @@ -16729,39 +17753,6 @@ Parameter Descriptions: |use_ttk_buttons|(bool) if True will cause all buttons to be ttk buttons| |ttk_theme|(str) Theme to use with ttk widgets. Choices (on Windows) include - 'default', 'winnative', 'clam', 'alt', 'classic', 'vista', 'xpnative'| -``` -sgprint(args, - size=(None, None), - end=None, - sep=None, - location=(None, None), - font=None, - no_titlebar=False, - no_button=False, - grab_anywhere=False, - keep_on_top=False, - do_not_reroute_stdout=True) -``` - -Parameter Descriptions: - -|Name|Meaning| -|---|---| -|*args|| -|size|Tuple[int, int] (w,h) w=characters-wide, h=rows-high| -|end|| -|sep|| -|location|Location on screen to display| -|font|specifies the font family, size, etc| -|no_titlebar|(Default = False)| -|no_button|(Default = False)| -|grab_anywhere|If True can grab anywhere to move the window (Default = False)| -|do_not_reroute_stdout|(Default = True)| - -``` -sgprint_close() -``` - Shows the smaller "popout" window. Default location is the upper right corner of your screen ``` @@ -16831,6 +17822,146 @@ The PySimpleGUI "Test Harness". This is meant to be a super-quick test of the E test() ``` +## Themes + +Sets / Gets the current Theme. If none is specified then returns the current theme. +This call replaces the ChangeLookAndFeel / change_look_and_feel call which only sets the theme. + +``` +theme(new_theme=None) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|new_theme|(str) the new theme name to use| +||| +| **return** | (str) the currently selected theme | + +Returns the background color specified by the current color theme + +``` +theme_background_color() -> (str) - color string of the background color defined by current theme +``` + +Returns the button color specified by the current color theme + +``` +theme_button_color() -> Tuple[str, str] - TUPLE with color strings of the button color defined by current theme (button text color, button background color) +``` + +Returns the input element background color specified by the current color theme + +``` +theme_input_background_color() -> (str) - color string of the input element background color defined by current theme +``` + +Returns the input element text color specified by the current color theme + +``` +theme_input_text_color() -> (str) - color string of the input element text color defined by current theme +``` + +Returns a sorted list of the currently available color themes + +``` +theme_list() -> List[str] - A sorted list of the currently available color themes +``` + +Show a window with all of the color themes - takes a while so be patient + +``` +theme_previewer(columns=12) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|columns|(int) number of themes in a single row| + +Returns the text color specified by the current color theme + +``` +theme_text_color() -> (str) - color string of the text color defined by current theme +``` + +## Old Themes (Look and Feel) - Replaced by theme() + +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. +The original list was (prior to a major rework and renaming)... these names still work... +In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: +The "Formula" is: +["Dark" or "Light"] Color Number +Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black +The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. +Default = The default settings (only button color is different than system default) +Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + +``` +ChangeLookAndFeel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| +|force|(bool) no longer used| + +Get a list of the valid values to pass into your call to change_look_and_feel + +``` +ListOfLookAndFeelValues() -> List[str] - list of valid string values +``` + +Displays a "Quick Reference Window" showing all of the different Look and Feel settings that are available. +They are sorted alphabetically. The legacy color names are mixed in, but otherwise they are sorted into Dark and Light halves + +``` +preview_all_look_and_feel_themes(columns=12) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|columns|(int) The number of themes to display per row| + +Get a list of the valid values to pass into your call to change_look_and_feel + +``` +list_of_look_and_feel_values() -> List[str] - list of valid string values +``` + +Change the "color scheme" of all future PySimpleGUI Windows. +The scheme are string names that specify a group of colors. Background colors, text colors, button colors. +There are 13 different color settings that are changed at one time using a single call to ChangeLookAndFeel +The look and feel table itself has these indexes into the dictionary LOOK_AND_FEEL_TABLE. +The original list was (prior to a major rework and renaming)... these names still work... +In Nov 2019 a new Theme Formula was devised to make choosing a theme easier: +The "Formula" is: +["Dark" or "Light"] Color Number +Colors can be Blue Brown Grey Green Purple Red Teal Yellow Black +The number will vary for each pair. There are more DarkGrey entries than there are LightYellow for example. +Default = The default settings (only button color is different than system default) +Default1 = The full system default including the button (everything's gray... how sad... don't be all gray... please....) + +``` +change_look_and_feel(index, force=False) +``` + +Parameter Descriptions: + +|Name|Meaning| +|---|---| +|index|(str) the name of the index into the Look and Feel table (does not have to be exact, can be "fuzzy")| +|force|(bool) no longer used| + --- # "Demo Programs" Applications @@ -16857,6 +17988,9 @@ https://github.com/PySimpleGUI/PySimpleGUI/tree/master/PySimpleGUIWeb/Demo%20Pro There are not many programs under each of the port's folders because the main Demo Programs should run on all of the other platforms with minimal changes (often only the import statement changes). +You will also find a lot of demos running on Trinket +http://Trinket.PySimpleGUI.org + ## Packages Used In Demos While the core PySimpleGUI code does not utilize any 3rd party packages, some of the demos do. They add a GUI to a few popular packages. These packages include: @@ -17022,37 +18156,78 @@ You'll quickly wonder how you ever coded without it. Well, there are a few quirks, and problems of course. Check the [GitHub Issues database](https://github.com/PySimpleGUI/PySimpleGUI/issues) for a list of them. -As previously mentioned this is also where you should post all problems and enhancements. +As previously mentioned **this is where you should post all problems and enhancements.** -## MACS + tkinter = SUCKS +Random crashes have been rared. The code is stable and hasn't been "quirky" nor have there been many "emergency" releases. -Not sure why, but for over a year and a half, setting the color of buttons does not work on Macs. There have been numerous other problems. Checking the Issues database is the best place to see what they are. If there was a magic wand it would have been used long ago to fix these problems, but there does not appear to be a magic fix. +## MACS & tkinter -This was already mentioned at the top of this document but want to make sure it's covered as a "known issue" +Macs and PySimpleGUI did not play well together up until Nov 2019 and the release of ttk buttons. Prior to that buttons had to be white. Now the Mac can use any color for buttons and they work great. Images on buttons work as well. + +The problems were the normal tk.Button was not working correctly on the Mac. You couldn't set the button color. If you tried it appeared as if the text was missing. + +Users have recently reported the ability to install Python 3.7 from the Python.org website and not use the Homebrew version. This resolved all of the button color problems. + +Regardless of where you get your Python / tkinter, Macs can now enjoy using all of the look and feel color themes that Windows and Linux users are able to achieve. + +Many PySimpleGUI users have switched from PySimpleGUI to PySimpleGUIQt due to the button problems. IF you're one of them, ***you should consider switching back***. One reason to return to PySimpleGUI is that features tend to get iumplemented on PySimpleGUI (tkinger version) and then later on the other ports. There are a number of other reasons to give tkinter another try. ## Multiple threads -While not an "issue" this is a ***stern warning*** +Consider this is a ***stern warning*** -## **Do not attempt** to call `PySimpleGUI` from multiple threads! It's `tkinter` based and `tkinter` has issues with multiple threads +### **Do not attempt** to call `PySimpleGUI` from multiple threads! At least the `tkinter` based port because tkinter is not threadsafe and has known issues with multiple threads Tkinter also wants to be the MAIN thread in your code. So, if you have to run multiple threads, make sure the GUI is the main thread. -Other than that, feel free to use threads with PySimpleGUI on all of the ports. You'll find a good example for how to run "long running tasks" in your event loop by looking at the demo program: `Demo_Multithreaded_Long_Tasks.py` +Other than that, feel free to use threads with PySimpleGUI on all of the ports. You'll find a good example for how to run "long running tasks" in your event loop by looking at the demo program: `Demo_Multithreaded_Long_Tasks.py`. There are several examples of using threads with PySimpleGUI. + +Be sure and **delete** your windows after you close them if you are running with multiple threads. There is a chance another thread's garbage collect will attempt to delete the window when not in the mainthread which will cause tkinter to crash. + +### The dreaded "Tcl_AsyncDelete: async handler deleted by the wrong thread" error + +This crash has plagued and mystified tkinter users for some time now. It happens when the user is running multiple threads in their application. Even if the user doesn't make any calls that are into tkinter, this problem can still cause your program to crash. + +I'm thrilled to say there's a solution and it's easy to implement. If you're getting this error, then here is what is causing it. + +When you close a window and delete the layout, the tkinter widgets that were in use in the window are no longer needed. Python marks them to be handled by the "Garbage Collector". They're deleted but not quite gone from memory. Then, later, while your thread is running, the Python Garbage Collect algorithm decides it's time to run garbage collect. When it tells tkinter to free up the memory, the tkinter code looks to see what context it is running under. It sees that it's a thread, not the main thread, and generates this exception. + +The way around this is actually quite easy. + +When you are finished with a window, be sure to: + +* Close the Window +* Set the `layout` variable to None +* Set the `window` variable to None +* Trigger Python's Garbage Collect to run immediately + +The sequence looks like this in code: + +```python + import gc + + # Do all your windows stuff... make a layout... show your window... then when time to exit + window.close() + layout = None + window = None + gc.collect() +``` + +This will ensure that the tkinter widgets are all deleted in the context of the mainthread and another thread won't accidently run the Garbage Collect # Contributing -## Core Code +## Write Applications -***Core code changes/pull requests are not being accepted at this time.*** +The way for you to contribute to the PySimpleGUI is to create and share PySimpleGUI GUIs. **Everyone** learns from seeing other peoples' implementations. It's through user's creating applications that new problems and needs are discovered. These have had a profound and positive impact on the project and helped to create thw you see today. -## Demos +## Pull Requests -You're welcome to share a PySimpleGUI program you've written that you think fits the model of a PySimpleGUI Demo Program. +***PySimpleGUI changes/pull requests are not being accepted at this time.*** ## GitHub Repos -If you've created a GitHub for your project that uses PySimpleGUI then please submit it to be included in this document or on the PySimpleGUI GitHub site. Also, you'll find a lot more people will look at your code, explore your repo if you have posted **screen shots in your readme**. People *love* success stories and showing your GUI's screen shows you've been successful. Everyone wins! +If you've created a GitHub for your project that uses PySimpleGUI then please post screenshots in in the "User's Screenshots" Issue on the PySimpleGUI GitHub. Say a little something about it and I'll also add it to the annoucements. People *love* success stories and showing your GUI's screen visually communicates your success. ## Versions |Version | Description | @@ -17937,9 +19112,151 @@ TTK WIDGETS! Welcome back Mac Users! * font * Test harness changes to help test new ttk stuff (want to shrink this window in the future so will fit on Trinket, Pi, etc +## 4.8.0 PySimpleGUI 4-Dec-2019 + +Multicolored multiline text! Often asked for feature going way back +ttk Buttons can have images +Print in color! + +* Multiline Element got 2 new parameters to the update method + * text_color_for_value - color for the newly added text + * background_color_for_value - background color of the newly added text +* New Print/EasyPrint parameters and capability + * text_color, background_color - control the text's color and background color when printing to "Debug Window" + * Must be done only when used in mode where stdout is not re-routed (the default) + * Wouldn't it be really nice if normal print calls had this parameter? + * Print(event, text_color='green', background_color='white', end='') +* ttk Buttons + * can have images. No longer forces Buttons with images to be the old tk Butons. Now you can choose either + * can update the button color + * can update the button image +* Set warning filter so that warnings are repeated +* New global variables: + * CURRENT_LOOK_AND_FEEL - The current look and feel setting in use. Starts out as "Default" + * BROWSE_FILES_DELIMITER - Defaults to ";" It is the string placed between entries returned from a FilesBrowse button + * TRANSPARENT_BUTTON - Depricated - was being used incorrectly as it was a relic from the early days. It's value was a color of gray +* Window - gentle reminder if you don't choose a look and feel for your window. It's easy to stop them. Add a change_look_and_feel line +* Test harness uses a debug window so don't be shocked when 2 windows appear when running PySimpleGUI by itself + * Prints the "Event" in Green on White text + * Prints the "values" normally + +## 4.9.0 PySimpleGUI 7-Dec-2019 + +The "Finally Nailed Tabs" release + +* Colors for Tabs! + * When creating TabGroup can now specify + * Text & Background color of all tabs + * Text & Background color of selected tab + * If nothing is specified then the Look and Feel theme will be used (which turned out GREAT) +* Tab visibility - Can finally control individual tab's visibility using update and when creating +* More "Look and Feel" Themes! There's no excuse to be grey again. There are now 126 themes to choose from. Here are the 32 new themes" + DefaultNoMoreNagging + DarkBlack1 + DarkBlue12 + DarkBlue13 + DarkBlue14 + DarkBlue15 + DarkBlue16 + DarkBlue17 + DarkBrown5 + DarkBrown6 + DarkGreen2 + DarkGreen3 + DarkGreen4 + DarkGreen5 + DarkGreen6 + DarkGrey4 + DarkGrey5 + DarkGrey6 + DarkGrey7 + DarkPurple6 + DarkRed2 + DarkTeal10 + DarkTeal11 + DarkTeal12 + DarkTeal9 + LightBlue6 + LightBlue7 + LightBrown12 + LightBrown13 + LightGray1 + LightGreen10 + LightGreen9 + LightGrey6 +* preview_all_look_and_feel_themes now has a columns parameter to control number of entries per rows + * also made each theme display smaller due to large number of themes + +## 4.10.0 PySimpleGUI 9-Dec-2019 + +"Oh crap the debugger is broken!" + "Pretty Progress Bars" release + +* Fix for built-in debugger not working + * Important due to upcoming educational usage + * Has been broken since 4.5.0 when a change to Finalize was made +* ProgessBar element colors set using Look and Feel colors + * Combination of button color, input element, and input element text are used + +## 4.11.0 PySimpleGUI 10-Dec-2019 + +The Element & Window bindings release + +* Element.bind - New method of all Elements + * Enables tkinter bindings to be added to any element + * Will get an event returned from window.read() if the tkinter event happens +* Window.bind - New method for Windows, just like Elements + * Enables tkinter bindings to be added to Windows + * Will get an event returned from window.read() if the tkinter event happens +* TabGroup fonts - can now set the font and font size for Tab text + +## 4.12.0 PySimpleGUI 14-Dec-2019 + +Finally no more outlines around TK Elements on Linux + +* Fixed a long-term problem of the mysterious white border around (almost) all TK Elements on Linux +* Ability to set the disabled button colors + * New Button and Button.update parameter - disabled_button_color + * Specified as (Text Color, Background Color) just like button colors + * For Normal / TK Buttons - can set button text color only + * For TTK Buttons - can set both a disabled button and text color + * Either parameter can be None to use current setting +* Removed use of CloseButton from Popups (still have a bug in the CloseButton code but not in popups now) +* Combobox - removed requirement of setting disabled if want to set to readonly using update method +* Fix for cancelling out of file/folder browse on Linux caused target to be cleared instead of just cancelling +* Removed try block around setting button colors - if user sets a bad color, well don't do that +* Now deleting windows after closing them for popup + +## 4.13.0 PySimpleGUI 18-Dec-2019 + +Table and Tree header colors, expanded Graph methods + +* Element.expand new parameter - expand_row. If true then row will expand along with the widgets. Provides better resizing control +* Using math.floor now instead of an int cast in Graph Element's unit conversions +* Graph.draw_point - now using caller's graph units for specifying point size +* Graph.draw_circle - converted radius size from user's graph units. +* Graph.draw_circle - added line_width parameter +* Graph.draw_oval - added line_width parameter +* Graph.get_figures_at_location - new method for getting a list of figures at a particular point +* Graph.get_bounding_box - returns bounding box for a previously drawn figure +* Table and Tree Elements + * 3 new element creation parameters + * header_text_color - color of the text for the column headings + * header_background_color - color of the background of column headings + * header_font - font family, style , size for the column headings + * Defaults to using the current look and feel setting + * Uses similar algorithm as Tabs - Input Text background and text colors are used +* Spin element - fixed bug that showed "None" if default value is "None" +* Test Harness sets incorrect look and feel on purpose so a random one is chosen + ### Upcoming -Make suggestions people! Future release features +There will always be overlapping work as the ports will never actually be "complete" as there's always something new that can be built. However there's a definition for the base functionality for PySimpleGUI. This is what is being strived for with the currnt ports that are underway. + +The current road ahead is to complete these ports - Qt (very close), Web (pretty close), Wx (not all that close). + +PySimpleGUIDroid is in the works.... + +In addition to the ports there is ongoing work with educators that want to bring PySimpleGUI into their classrooms. Some projects have already started with teachers. One effort is to examine a number of books that teach Python to kids and convert the exercises to use PySimpleGUI instead of tkinter or command line. Another educational effort is in integrating with Circuit Python. It's unclear exactly how PySimpleGUI will fit into the picture. A board from Adafruit is arriving soon which should help solidify what's possible. ## Code Condition @@ -17947,11 +19264,11 @@ Make suggestions people! Future release features Make it right Make it fast -It's a recipe for success if done right. PySimpleGUI has completed the "Make it run" phase. It's far from "right" in many ways. These are being worked on. The module is particularly poor for PEP 8 compliance. It was a learning exercise that turned into a somewhat complete GUI solution for lightweight problems. +It's a recipe for success if done right. PySimpleGUI has completed the "Make it run" phase. It's far from "right" in many ways. These are being worked on. The module has historically been particularly poor for PEP8 compliance. It was a learning exercise that turned into a somewhat complete GUI solution for lightweight problems. -While the internals to PySimpleGUI are a tad sketchy, the public interfaces into the SDK are more strictly defined and comply with PEP 8 for the most part. +While the internals to PySimpleGUI are a tad sketchy, the public interfaces into the SDK are more strictly defined and comply with PEP8 naming conventions. A set of "PEP8 Bindings" was released in summar 2019 to ensure the enternally facing interfaces all adhere to PEP8 names. -Please log bugs and suggestions in the GitHub! It will only make the code stronger and better in the end, a good thing for us all, right? +Please log bugs and suggestions **only on the PySimpleGUI GitHub**! It will only make the code stronger and better in the end, a good thing for us all, right? Logging them elsewhere doesn't enable the core developer and other PySimpleGUI users to help. To make matters worse, you may get bad advice from other sites because there are simply not many PySimpleGUI experts, yet. ## Design diff --git a/readme_creator/run_me.py b/readme_creator/run_me.py index 16ea9e22..282312c0 100644 --- a/readme_creator/run_me.py +++ b/readme_creator/run_me.py @@ -92,6 +92,7 @@ if method == 'with logs': ######################################## if enable_popup: import PySimpleGUI as sg + sg.change_look_and_feel('Dark Green 2') lines = open('usage.log.txt', mode='r').readlines() sg.PopupScrolled('Completed making {}'.format(OUTPUT_FILENAME), ''.join(lines), size=(80,50)) diff --git a/readme_creator/show_all_tags.py b/readme_creator/show_all_tags.py index b78cbff6..82306b33 100644 --- a/readme_creator/show_all_tags.py +++ b/readme_creator/show_all_tags.py @@ -8,6 +8,7 @@ import PySimpleGUIlib Displays the results in a PySimpleGUI window which can be used to copy and paste into other places. """ +PySimpleGUIlib.theme('Dark Green 2') layout = [[PySimpleGUIlib.Output(size=(80,50))]] window = PySimpleGUIlib.Window('Dump of tags', layout, resizable=True).Finalize()