From 9dc029e9cda09231428ba88f997ea8f11f257324 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Tue, 14 May 2019 12:18:29 -0400 Subject: [PATCH 1/2] Window gets new `transparent_color` parameter and `SetTransparentColor` method --- PySimpleGUI.py | 17 ++++- PySimpleGUI27.py | 159 +++++++++++++++++++++++++++++++++-------------- 2 files changed, 127 insertions(+), 49 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 182c21f1..c3c3f07f 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -3535,7 +3535,7 @@ class Window: progress_bar_color=(None, None), background_color=None, border_depth=None, auto_close=False, auto_close_duration=DEFAULT_AUTOCLOSE_TIME, icon=DEFAULT_WINDOW_ICON, force_toplevel=False, alpha_channel=1, return_keyboard_events=False, use_default_focus=True, text_justification=None, - no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=False, disable_close=False, disable_minimize=False, right_click_menu=None): + no_titlebar=False, grab_anywhere=False, keep_on_top=False, resizable=False, disable_close=False, disable_minimize=False, right_click_menu=None, transparent_color=None): ''' Window :param title: @@ -3623,6 +3623,8 @@ class Window: self.Margins = margins if margins != (None, None) else DEFAULT_MARGINS self.ContainerElemementNumber = Window.GetAContainerNumber() self.AllKeysDict = {} + self.TransparentColor = transparent_color + if layout is not None: self.Layout(layout) @@ -4164,6 +4166,9 @@ class Window: # A dummy function. Needed in Qt but not tkinter return + def SetTransparentColor(self, color): + self.TKroot.attributes('-transparentcolor', color) + def __enter__(self): return self @@ -6164,6 +6169,7 @@ def StartupTK(my_flex_form:Window): else: root = tk.Toplevel() + try: root.attributes('-alpha', 0) # hide window while building it. makes for smoother 'paint' except: @@ -6190,6 +6196,9 @@ def StartupTK(my_flex_form:Window): if my_flex_form.KeepOnTop: root.wm_attributes("-topmost", 1) + if my_flex_form.TransparentColor is not None: + my_flex_form.SetTransparentColor(my_flex_form.TransparentColor) + # root.protocol("WM_DELETE_WINDOW", MyFlexForm.DestroyedCallback()) # root.bind('', MyFlexForm.DestroyedCallback()) ConvertFlexToTK(my_flex_form) @@ -7779,7 +7788,9 @@ def main(): window = Window('Window Title', layout, font=('Helvetica', 13), + background_color='black', right_click_menu=['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']], + # transparent_color= '#9FB8AD', ).Finalize() graph_elem.DrawCircle((200, 200), 50, 'blue') i = 0 @@ -7802,6 +7813,10 @@ def main(): if event == 'Button': print(window.AllKeysDict) window.Element('_TEXT1_').SetTooltip('NEW TEXT') + window.SetTransparentColor( '#9FB8AD') + # window.TKroot.wm_attributes("-transparent", '#9FB8AD') + # window.TKroot.wm_attributes("-transparentcolor", '#9FB8AD') + # TimerStop() window.Close() diff --git a/PySimpleGUI27.py b/PySimpleGUI27.py index 6e09fab3..6ee4d365 100644 --- a/PySimpleGUI27.py +++ b/PySimpleGUI27.py @@ -10,8 +10,9 @@ from builtins import map from builtins import int from builtins import str from builtins import object + from future import standard_library -standard_library.install_aliases() +# standard_library.install_aliases() import sys if sys.version_info[0] >= 3: import tkinter as tk @@ -92,13 +93,7 @@ DEFAULT_BASE64_ICON = b'R0lGODlhIQAgAPcAAAAAADBpmDBqmTFqmjJrmzJsnDNtnTRrmTZtmzZu DEFAULT_BASE64_LOADING_GIF = b'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' - - - -if sys.version_info[0] >= 3: - DEFAULT_WINDOW_ICON = DEFAULT_BASE64_ICON -else: - DEFAULT_WINDOW_ICON = 'default_icon.ico' +DEFAULT_WINDOW_ICON = DEFAULT_BASE64_ICON DEFAULT_ELEMENT_SIZE = (45, 1) # In CHARACTERS DEFAULT_BUTTON_ELEMENT_SIZE = (10, 1) # In CHARACTERS @@ -114,7 +109,7 @@ DEFAULT_DEBUG_WINDOW_SIZE = (80, 20) DEFAULT_WINDOW_LOCATION = (None, None) MAX_SCROLLED_TEXT_BOX_HEIGHT = 50 DEFAULT_TOOLTIP_TIME = 400 -DEFAULT_TOOLTIP_OFFSET = (20,-20) +DEFAULT_TOOLTIP_OFFSET = (0,-20) #################### COLOR STUFF #################### BLUES = ("#082567", "#0A37A3", "#00345B") PURPLES = ("#480656", "#4F2398", "#380474") @@ -316,6 +311,8 @@ class ToolTip(object): self.widget.bind("", self.leave) def enter(self, event=None): + self.x = event.x + self.y = event.y self.schedule() def leave(self, event=None): @@ -334,8 +331,8 @@ class ToolTip(object): def showtip(self): if self.tipwindow: return - x = self.widget.winfo_rootx() + DEFAULT_TOOLTIP_OFFSET[0] - y = self.widget.winfo_rooty() + self.widget.winfo_height() + DEFAULT_TOOLTIP_OFFSET[1] + x = self.widget.winfo_rootx() + self.x + DEFAULT_TOOLTIP_OFFSET[0] + y = self.widget.winfo_rooty() + self.y + DEFAULT_TOOLTIP_OFFSET[1] self.tipwindow = tk.Toplevel(self.widget) self.tipwindow.wm_overrideredirect(True) self.tipwindow.wm_geometry("+%d+%d" % (x, y)) @@ -933,6 +930,10 @@ class Radio(Element): elif visible is True: self.TKRadio.pack() + def ResetGroup(self): + self.TKIntVar.set(0) + + def __del__(self): try: self.TKRadio.__del__() @@ -1705,6 +1706,17 @@ class Button(Element): pass + def Click(self): + """ + Generates a click of the button as if the user clicked the button + :return: + """ + try: + self.TKButton.invoke() + except: + print('Exception clicking button') + + def __del__(self): try: self.TKButton.__del__() @@ -2025,8 +2037,8 @@ class Graph(Element): self.CanvasSize = canvas_size self.BottomLeft = graph_bottom_left self.TopRight = graph_top_right - self._TKCanvas = None - self._TKCanvas2 = None # Type: tk.Canvas + # self._TKCanvas = None # type: tk.Canvas + self._TKCanvas2 = None # type: tk.Canvas self.ChangeSubmits = change_submits or enable_events self.DragSubmits = drag_submits self.ClickPosition = (None, None) @@ -2305,7 +2317,9 @@ class Graph(Element): self.ParentForm.TKroot.quit() # kick out of loop if read was called - + def SetFocus(self): + self._TKCanvas2.focus_set() + # self._TKCanvas2.focus_force() def __del__(self): super().__del__() @@ -2377,6 +2391,7 @@ class Frame(Element): for row in rows: self.AddRow(*row) + def _GetElementAtLocation(self, location): (row_num, col_num) = location row = self.Rows[row_num] @@ -3196,7 +3211,7 @@ MenuBar = Menu # another name for Menu to make it clear it's the Menu B # ---------------------------------------------------------------------- # 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, + 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, 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): ''' Table @@ -3244,6 +3259,7 @@ class Table(Element): self.TKTreeview = None self.AlternatingRowColor = alternating_row_color self.VerticalScrollOnly = vertical_scroll_only + self.HideVerticalScroll = hide_vertical_scroll self.SelectedRows = [] self.ChangeSubmits = change_submits or enable_events self.BindReturnKey = bind_return_key @@ -3616,6 +3632,7 @@ class Window(object): self.RightClickMenu = right_click_menu self.Margins = margins if margins != (None, None) else DEFAULT_MARGINS self.ContainerElemementNumber = Window.GetAContainerNumber() + self.AllKeysDict = {} if layout is not None: self.Layout(layout) @@ -3655,8 +3672,10 @@ class Window(object): def Layout(self, rows): self.AddRows(rows) + self.BuildKeyDict() return self + def LayoutAndRead(self, rows, non_blocking=False): raise DeprecationWarning('LayoutAndRead is no longer supported... change your call window.Layout(layout).Read()') # self.AddRows(rows) @@ -3756,6 +3775,7 @@ class Window(object): self.TKroot.quit() # kick the users out of the mainloop def Read(self, timeout=None, timeout_key=TIMEOUT_KEY): + timeout = int(timeout) if timeout is not None else None if timeout == 0: # timeout of zero runs the old readnonblocking event, values = self.ReadNonBlocking() if event is None: @@ -3910,7 +3930,11 @@ class Window(object): return self def FindElement(self, key, silent_on_error=False): - element = _FindElementFromKeyInSubForm(self, key) + try: + element = self.AllKeysDict[key] + except KeyError: + element = None + # element = _FindElementFromKeyInSubForm(self, key) if element is None: if not silent_on_error: print('*** WARNING = FindElement did not find the key. Please check your key\'s spelling ***') @@ -3930,6 +3954,33 @@ class Window(object): element = _FindElementWithFocusInSubForm(self) return element + def BuildKeyDict(self): + dict = {} + self.AllKeysDict = self._BuildKeyDictForWindow(self, dict) + + def _BuildKeyDictForWindow(self, window, key_dict): + for row_num, row in enumerate(window.Rows): + for col_num, element in enumerate(row): + if element.Type == ELEM_TYPE_COLUMN: + key_dict = self._BuildKeyDictForWindow(element, key_dict) + if element.Type == ELEM_TYPE_FRAME: + key_dict = self._BuildKeyDictForWindow(element, key_dict) + if element.Type == ELEM_TYPE_TAB_GROUP: + key_dict = self._BuildKeyDictForWindow(element, key_dict) + if element.Type == ELEM_TYPE_PANE: + key_dict = self._BuildKeyDictForWindow(element, key_dict) + if element.Type == ELEM_TYPE_TAB: + key_dict = self._BuildKeyDictForWindow(element, key_dict) + if element.Key is None and element.Type != ELEM_TYPE_TEXT: + if element.Type != ELEM_TYPE_BUTTON: + element.Key = window.DictionaryKeyCounter + window.DictionaryKeyCounter += 1 + else: + element.Key = element.ButtonText + if element.Key is not None: + key_dict[element.Key] = element + return key_dict + def SaveToDisk(self, filename): try: results = BuildResults(self, False, self) @@ -5173,6 +5224,7 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): # ------------------------- INPUT element ------------------------- # elif element_type == ELEM_TYPE_INPUT_TEXT: + element = element # type: InputText default_text = element.DefaultText element.TKStringVar = tk.StringVar() element.TKStringVar.set(default_text) @@ -5566,23 +5618,25 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): element._TKCanvas.bind('', element.RightClickMenuCallback) # ------------------------- Graph element ------------------------- # elif element_type == ELEM_TYPE_GRAPH: + element = element # type: Graph width, height = element_size - if element._TKCanvas is None: - element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) - else: - element._TKCanvas.master = tk_row_frame - element._TKCanvas2 = tk.Canvas(element._TKCanvas, width=width, height=height, bd=border_depth) + # I don't know why TWO canvases were being defined, on inside the other. Was it so entire canvas can move? + # if element._TKCanvas is None: + # element._TKCanvas = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) + # else: + # element._TKCanvas.master = tk_row_frame + element._TKCanvas2 = tk.Canvas(tk_row_frame, width=width, height=height, bd=border_depth) element._TKCanvas2.pack(side=tk.LEFT) element._TKCanvas2.addtag_all('mytag') if element.BackgroundColor is not None and element.BackgroundColor != COLOR_SYSTEM_DEFAULT: element._TKCanvas2.configure(background=element.BackgroundColor, highlightthickness=0) - element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) - element._TKCanvas.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1]) + # element._TKCanvas.configure(background=element.BackgroundColor, highlightthickness=0) + element._TKCanvas2.pack(side=tk.LEFT, padx=elementpad[0], pady=elementpad[1]) if element.Visible is False: - element._TKCanvas.pack_forget() + # element._TKCanvas.pack_forget() element._TKCanvas2.pack_forget() if element.Tooltip is not None: - element.TooltipObject = ToolTip(element._TKCanvas, text=element.Tooltip, + element.TooltipObject = ToolTip(element._TKCanvas2, text=element.Tooltip, timeout=DEFAULT_TOOLTIP_TIME) if element.ChangeSubmits: element._TKCanvas2.bind('', element.ButtonReleaseCallBack) @@ -5847,9 +5901,11 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): treeview.bind('', element.treeview_double_click) treeview.bind('', element.treeview_double_click) - scrollbar = tk.Scrollbar(frame) - scrollbar.pack(side=tk.RIGHT, fill='y') - scrollbar.config(command=treeview.yview) + if not element.HideVerticalScroll: + scrollbar = tk.Scrollbar(frame) + scrollbar.pack(side=tk.RIGHT, fill='y') + scrollbar.config(command=treeview.yview) + treeview.configure(yscrollcommand=scrollbar.set) if not element.VerticalScrollOnly: hscrollbar = tk.Scrollbar(frame, orient=tk.HORIZONTAL) @@ -5857,7 +5913,6 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): hscrollbar.config(command=treeview.xview) treeview.configure(xscrollcommand=hscrollbar.set) - treeview.configure(yscrollcommand=scrollbar.set) element.TKTreeview.pack(side=tk.LEFT, expand=True, padx=0, pady=0, fill='both') if element.Visible is False: @@ -7834,23 +7889,25 @@ def PopupGetFolder(message, title=None, default_path='', no_window=False, size=( return folder_name layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], - [InputText(default_text=default_path, size=size), FolderBrowse(initial_folder=initial_folder)], + [InputText(default_text=default_path, size=size, key='_INPUT_'), FolderBrowse(initial_folder=initial_folder)], [CloseButton('Ok', size=(5, 1), bind_return_key=True), CloseButton('Cancel', size=(5, 1))]] - window = Window(title=title or message, icon=icon, auto_size_text=True, button_color=button_color, + window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, background_color=background_color, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - (button, input_values) = window.Layout(layout).Read() + button, values = window.Read() + window.Close() if button != 'Ok': return None else: - path = input_values[0] + path = values['_INPUT_'] return path + # --------------------------- PopupGetFile --------------------------- def PopupGetFile(message, title=None, default_path='', default_extension='', save_as=False, file_types=(("ALL Files", "*.*"),), @@ -7902,18 +7959,19 @@ def PopupGetFile(message, title=None, default_path='', default_extension='', sav browse_button = SaveAs(file_types=file_types, initial_folder=initial_folder) if save_as else FileBrowse(file_types=file_types, initial_folder=initial_folder) layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color)], - [InputText(default_text=default_path, size=size), browse_button], + [InputText(default_text=default_path, size=size, key='_INPUT_'), browse_button], [CloseButton('Ok', size=(6, 1), bind_return_key=True), CloseButton('Cancel', size=(6, 1))]] - window = Window(title=title or message, icon=icon, auto_size_text=True, button_color=button_color, font=font, + window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, font=font, background_color=background_color, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - (button, input_values) = window.Layout(layout).Read() + button, values = window.Read() + window.Close() if button != 'Ok': return None else: - path = input_values[0] + path = values['_INPUT_'] return path @@ -7941,19 +7999,22 @@ def PopupGetText(message, title=None, default_text='', password_char='', size=(N """ layout = [[Text(message, auto_size_text=True, text_color=text_color, background_color=background_color, font=font)], - [InputText(default_text=default_text, size=size, password_char=password_char)], + [InputText(default_text=default_text, size=size, key='_INPUT_', password_char=password_char)], [CloseButton('Ok', size=(5, 1), bind_return_key=True), CloseButton('Cancel', size=(5, 1))]] - window = Window(title=title or message, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, + window = Window(title=title or message, layout=layout, icon=icon, auto_size_text=True, button_color=button_color, no_titlebar=no_titlebar, background_color=background_color, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) - (button, input_values) = window.Layout(layout).Read() - + button, values = window.Read() + window.Close() if button != 'Ok': return None else: - return input_values[0] + path = values['_INPUT_'] + return path + + # --------------------------- PopupAnimated --------------------------- @@ -8032,7 +8093,7 @@ def main(): frame3 = [ [Checkbox('Checkbox1', True), Checkbox('Checkbox1')], - [Radio('Radio Button1', 1), Radio('Radio Button2', 1, default=True)], + [Radio('Radio Button1', 1), Radio('Radio Button2', 1, default=True, tooltip='Radio 2')], [T('', size=(1, 4))], ] @@ -8057,12 +8118,12 @@ def main(): [graph_elem], ] - tab1 = Tab('Graph Number 1', frame6) + tab1 = Tab('Graph Number 1', frame6, tooltip='tab 1') tab2 = Tab('Graph Number 2', [[]]) layout1 = [ [Menu(menu_def)], - [Text('You are running the PySimpleGUI.py file itself', font='ANY 15')], + [Text('You are running the PySimpleGUI.py file itself', font='ANY 15', tooltip='My tooltip')], [Text('You should be importing it rather than running it', font='ANY 15')], [Frame('Input Text Group', frame1, title_color='red'), Image(data=DEFAULT_BASE64_LOADING_GIF, key='_IMAGE_')], @@ -8072,15 +8133,15 @@ def main(): [Frame('Structured Data Group', frame5, title_color='red'), ], # [Frame('Graphing Group', frame6)], [TabGroup([[tab1, tab2]])], - [ProgressBar(max_value=800, size=(60, 25), key='+PROGRESS+'), Button('Button'), Button('Exit')], + [ProgressBar(max_value=800, size=(60, 25), key='+PROGRESS+'), Button('Button'), Button('Exit', tooltip='Exit button')], ] layout=[[Column(layout1)]] - window = Window('Window Title', + window = Window('Window Title', layout, font=('Helvetica', 13), right_click_menu=['&Right', ['Right', '!&Click', '&Menu', 'E&xit', 'Properties']], - ).Layout(layout).Finalize() + ).Finalize() graph_elem.DrawCircle((200, 200), 50, 'blue') i = 0 while True: # Event Loop @@ -8099,6 +8160,8 @@ def main(): window.FindElement('+PROGRESS+').UpdateBar(i % 800) window.Element('_IMAGE_').UpdateAnimation(DEFAULT_BASE64_LOADING_GIF, time_between_frames=50) i += 1 + if event == 'Button': + print(window.AllKeysDict) # TimerStop() window.Close() From eddf5bc97fbc5a133388645a20362f6c19fa115b Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Tue, 14 May 2019 12:55:48 -0400 Subject: [PATCH 2/2] New Window parameter transparent_color. PopupAnimated now uses a transparent background! --- PySimpleGUI.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index c3c3f07f..80f5b782 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -6206,7 +6206,7 @@ def StartupTK(my_flex_form:Window): my_flex_form.SetIcon(my_flex_form.WindowIcon) try: - root.attributes('-alpha', my_flex_form.AlphaChannel) # Make window visible again + root.attributes('-alpha', 1 if my_flex_form.AlphaChannel is None else my_flex_form.AlphaChannel) # Make window visible again except: pass @@ -7666,7 +7666,7 @@ def PopupGetText(message, title=None, default_text='', password_char='', size=(N # --------------------------- PopupAnimated --------------------------- -def 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=.8, time_between_frames=0): +def 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): if image_source is None: for image in Window.animated_popup_dict: @@ -7676,15 +7676,15 @@ def PopupAnimated(image_source, message=None, background_color=None, text_color= return if image_source not in Window.animated_popup_dict: - if type(image_source) is bytes: + if type(image_source) is bytes or len(image_source)>200: + print('Animating data') layout = [[Image(data=image_source, background_color=background_color, key='_IMAGE_',)],] else: layout = [[Image(filename=image_source, background_color=background_color, key='_IMAGE_',)],] if message: layout.append([Text(message, background_color=background_color, text_color=text_color, font=font)]) - window = Window('Animated GIF', no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, - background_color=background_color, location=location, alpha_channel=alpha_channel, element_padding=(0,0), margins=(0,0)).Layout(layout).Finalize() + window = Window('Animated GIF', layout, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, background_color=background_color, location=location, alpha_channel=alpha_channel, element_padding=(0,0), margins=(0,0), transparent_color=transparent_color).Finalize() Window.animated_popup_dict[image_source] = window else: window = Window.animated_popup_dict[image_source]