From bdaf9503ee4f1ef91f5faf3e72b2a1cf799ddfc2 Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Mon, 13 May 2019 22:32:29 +0200 Subject: [PATCH 1/8] Fix memory leak due to Images of Graph - Graph used a list self.Images to which new images where appended on DrawImage. Neither in DeleteFigure nor in Erase were any elements removed from that list. Thus any added image was kept in memory as long as the corresponding Graph was; even if it wasn't used anymore. - Even though self.Images is not referred to in any other way, removing the list completely does not work; the result is that no images are drawn on the Graph. - The implemented solution uses a dictionary (id -> image) to keep only used images in self.Images. --- PySimpleGUI.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index c1ec3a2f..05e97abb 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -2029,7 +2029,7 @@ class Graph(Element): self.DragSubmits = drag_submits self.ClickPosition = (None, None) self.MouseButtonDown = False - self.Images = [] + self.Images = {} self.RightClickMenu = right_click_menu super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key, @@ -2184,9 +2184,9 @@ class Graph(Element): print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') print('Call Window.Finalize() prior to this operation') return None - self.Images.append(image) try: # in case closed with X id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW) + self.Images[id] = image except: id = None return id @@ -2198,6 +2198,7 @@ class Graph(Element): print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') print('Call Window.Finalize() prior to this operation') return None + self.Images = {} try: # in case window was closed with X self._TKCanvas2.delete('all') except: @@ -2206,6 +2207,7 @@ class Graph(Element): def DeleteFigure(self, id): try: + del self.Images[id] self._TKCanvas2.delete(id) except: print('DeleteFigure - bad ID {}'.format(id)) From 78c84b9f8fb391470cd7a475f4ad2c0bbafa6ece Mon Sep 17 00:00:00 2001 From: Daniel Jour Date: Mon, 13 May 2019 22:51:23 +0200 Subject: [PATCH 2/8] Fix memory leak due to Images of Graph (PySimpleGui27) - Graph used a list self.Images to which new images where appended on DrawImage. Neither in DeleteFigure nor in Erase were any elements removed from that list. Thus any added image was kept in memory as long as the corresponding Graph was; even if it wasn't used anymore. - Even though self.Images is not referred to in any other way, removing the list completely does not work; the result is that no images are drawn on the Graph. - The implemented solution uses a dictionary (id -> image) to keep only used images in self.Images. --- PySimpleGUI27.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/PySimpleGUI27.py b/PySimpleGUI27.py index 6e09fab3..6995f2a3 100644 --- a/PySimpleGUI27.py +++ b/PySimpleGUI27.py @@ -2031,7 +2031,7 @@ class Graph(Element): self.DragSubmits = drag_submits self.ClickPosition = (None, None) self.MouseButtonDown = False - self.Images = [] + self.Images = {} self.RightClickMenu = right_click_menu super().__init__(ELEM_TYPE_GRAPH, background_color=background_color, size=canvas_size, pad=pad, key=key, @@ -2186,9 +2186,9 @@ class Graph(Element): print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') print('Call Window.Finalize() prior to this operation') return None - self.Images.append(image) try: # in case closed with X id = self._TKCanvas2.create_image(converted_point, image=image, anchor=tk.NW) + self.Images[id] = image except: id = None return id @@ -2200,6 +2200,7 @@ class Graph(Element): print('*** WARNING - The Graph element has not been finalized and cannot be drawn upon ***') print('Call Window.Finalize() prior to this operation') return None + self.Images = {} try: # in case window was closed with X self._TKCanvas2.delete('all') except: @@ -2208,6 +2209,7 @@ class Graph(Element): def DeleteFigure(self, id): try: + del self.Images[id] self._TKCanvas2.delete(id) except: print('DeleteFigure - bad ID {}'.format(id)) From e35fdd851871524fa515bdd748c0512bbb0b61dd Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 17 May 2019 12:12:38 +0200 Subject: [PATCH 3/8] Allow calendar button locale Fixes half of #977 --- PySimpleGUI.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 26f23d62..95873295 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1632,7 +1632,7 @@ class Button(Element): root = tk.Toplevel() root.title('Calendar Chooser') root.wm_attributes("-topmost", 1) - self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y ) + self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y, locale=self.CalendarLocale) self.TKCal.pack(expand=1, fill='both') root.update() @@ -4425,9 +4425,10 @@ def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True image_filename=image_filename, image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, locale=None) button.CalendarCloseWhenChosen = close_when_date_chosen button.DefaultDate_M_D_Y = default_date_m_d_y + button.CalendarLocale = locale return button From 7aa110b1fe1066fda37cd4f95b60e04b318fb903 Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 17 May 2019 13:11:55 +0200 Subject: [PATCH 4/8] Multiple improvements on CalendarButton Allow passing optional format argument (as of datetime.strftime() format given https://docs.python.org/3.6/library/datetime.html?highlight=strftime#strftime-strptime-behavior) Also use current timestamp when updating calendar instead of 00:00:00 --- PySimpleGUI.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 95873295..2e3e4944 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1632,7 +1632,7 @@ class Button(Element): root = tk.Toplevel() root.title('Calendar Chooser') root.wm_attributes("-topmost", 1) - self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y, locale=self.CalendarLocale) + self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y, locale=self.CalendarLocale, format=self.CalendarFormat) self.TKCal.pack(expand=1, fill='both') root.update() @@ -2944,6 +2944,9 @@ class TKCalendar(ttk.Frame): locale = kw.pop('locale', None) sel_bg = kw.pop('selectbackground', '#ecffc4') sel_fg = kw.pop('selectforeground', '#05640e') + self.format = kw.pop('format') + if self.format is None: + self.format = '%Y-%m-%d %H:%M:%S' self._date = self.datetime(year, month, default_day or 1) self._selection = None # no date selected @@ -3097,8 +3100,9 @@ class TKCalendar(ttk.Frame): self._selection = (text, item, column) self._show_selection(text, bbox) year, month = self._date.year, self._date.month + now = self.datetime.now() try: - self._TargetElement.Update(self.datetime(year, month, int(self._selection[0]))) + self._TargetElement.Update(self.datetime(year, month, int(self._selection[0]), now.hour, now.minute, now.second).strftime(self.format)) if self._TargetElement.ChangeSubmits: self._TargetElement.ParentForm.LastButtonClicked = self._TargetElement.Key self._TargetElement.ParentForm.FormRemainedOpen = True @@ -4420,15 +4424,16 @@ def DummyButton(button_text, image_filename=None, image_data=None, image_size=(N def CalendarButton(button_text, target=(None, None), close_when_date_chosen=True, default_date_m_d_y=(None,None,None), image_filename=None, image_data=None, image_size=(None, None), image_subsample=None, tooltip=None, border_width=None, size=(None, None), auto_size_button=None, button_color=None, disabled=False, font=None, bind_return_key=False, focus=False, pad=None, - key=None): + key=None, locale=None, format=None): button = Button(button_text=button_text, button_type=BUTTON_TYPE_CALENDAR_CHOOSER, target=target, image_filename=image_filename, image_data=image_data, image_size=image_size, image_subsample=image_subsample, border_width=border_width, tooltip=tooltip, size=size, auto_size_button=auto_size_button, button_color=button_color, font=font, disabled=disabled, - bind_return_key=bind_return_key, focus=focus, pad=pad, key=key, locale=None) + bind_return_key=bind_return_key, focus=focus, pad=pad, key=key) button.CalendarCloseWhenChosen = close_when_date_chosen button.DefaultDate_M_D_Y = default_date_m_d_y button.CalendarLocale = locale + button.CalendarFormat = format return button From 4d137e19c42ac85aecdd72e94cfbbe0f8d0242cb Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 17 May 2019 13:17:24 +0200 Subject: [PATCH 5/8] Merge PR #1433 to avoid conflicts as same lines affected --- PySimpleGUI.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 2e3e4944..a81f0bc9 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1635,6 +1635,15 @@ class Button(Element): self.TKCal = TKCalendar(master=root, firstweekday=calendar.SUNDAY, target_element=target_element, close_when_chosen=self.CalendarCloseWhenChosen, default_date=self.DefaultDate_M_D_Y, locale=self.CalendarLocale, format=self.CalendarFormat) self.TKCal.pack(expand=1, fill='both') root.update() + + if type(Window.user_defined_icon) is bytes: + calendar_icon = tkinter.PhotoImage(data=Window.user_defined_icon) + else: + calendar_icon = DEFAULT_BASE64_ICON + try: + root.tk.call('wm', 'iconphoto', root._w, calendar_icon) + except: + pass if should_submit_window: self.ParentForm.LastButtonClicked = target_element.Key From f563f01ed8363c48a6a38ba3e575984105383c3d Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Fri, 17 May 2019 13:18:30 +0200 Subject: [PATCH 6/8] Fix indentation error while merging PRs --- PySimpleGUI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index a81f0bc9..3851fe1f 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1636,7 +1636,7 @@ class Button(Element): self.TKCal.pack(expand=1, fill='both') root.update() - if type(Window.user_defined_icon) is bytes: + if type(Window.user_defined_icon) is bytes: calendar_icon = tkinter.PhotoImage(data=Window.user_defined_icon) else: calendar_icon = DEFAULT_BASE64_ICON From 28eed8751c643a586b25bd0f3a6e95a9794e84cb Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Sat, 18 May 2019 15:13:47 -0400 Subject: [PATCH 7/8] Overhaul to correctly handle tooltips, buttons, etc. Cleanup in a major way --- .../Demo Programs/Web_Color_Names.py | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py b/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py index 22dfb77d..8b8d41c0 100644 --- a/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py +++ b/PySimpleGUIWeb/Demo Programs/Web_Color_Names.py @@ -1,16 +1,17 @@ #!/usr/bin/env python import PySimpleGUIWeb as sg +# import PySimpleGUI as sg """ - Shows a big chart of colors... give it a few seconds to create it + Shows a big chart of colors... Once large window is shown, you can click on any color and another window will popup showing both white and black text on that color Uses TOOLTIPS to show the hex values for the colors. Hover over a color and a tooltip will show you the RGB You will find the list of tkinter colors here: http://www.tcl.tk/man/tcl8.5/TkCmd/colors.htm - + Really shows off the PySimpleGUIWeb capabilities """ color_map = { @@ -667,11 +668,19 @@ color_map = { } +def detailed_view(window): + layout2 = [[sg.Button(event, button_color=('white', color_map[event]), key=event, tooltip=color_map[color]), + sg.Button(event, button_color=('black', color_map[event]), key=event+'1', tooltip=color_map[color])], + [sg.Txt('Hover over button to see color value. Click to clocse and return to main interface.')], ] + sg.Window('Buttons with white and black text', layout2, keep_on_top=True).Read() + window.Close() + return + sg.SetOptions(button_element_size=(16,1), auto_size_buttons=False, border_width=0, tooltip_time=100) #start layout with the tittle -layout = [[sg.Text('Hover mouse to see RGB value', +layout = [[sg.Text('Hover mouse to see RGB value. Click to see Button with White or Black text.', text_color='blue', font=('Hevletica', 20), relief=sg.RELIEF_SUNKEN, @@ -692,12 +701,9 @@ for rows in range(40): pass layout.append(row) -window = sg.Window('Color Viewer', font=('any 12'), default_button_element_size=(12,1), element_padding=(0,0)).Layout(layout) - -# -- Event loop -- while True: + window = sg.Window('Color Viewer', layout, font=('any 12'), default_button_element_size=(12,1), element_padding=(0,0)) event, values = window.Read() if event is None: break - -window.Close() \ No newline at end of file + detailed_view(window) From 8ff3c80f23fc9fa5a65a25ee5d91884f26ac6d82 Mon Sep 17 00:00:00 2001 From: Orsiris de Jong Date: Sun, 19 May 2019 14:18:58 +0200 Subject: [PATCH 8/8] Fix default PySimpleGUI icon never used in CalendarButton --- PySimpleGUI.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 3851fe1f..37cfa4ac 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1639,7 +1639,7 @@ class Button(Element): if type(Window.user_defined_icon) is bytes: calendar_icon = tkinter.PhotoImage(data=Window.user_defined_icon) else: - calendar_icon = DEFAULT_BASE64_ICON + calendar_icon = tkinter.PhotoImage(data=DEFAULT_BASE64_ICON) try: root.tk.call('wm', 'iconphoto', root._w, calendar_icon) except: