From 6bf5b0df6f10e5db1384703de650ed32cf41eeed Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Thu, 4 Oct 2018 19:25:28 -0400 Subject: [PATCH 1/4] NEW Demo - second Pyplot Bar Chart example --- Demo_Pyploy_Bar_Chart2.py | 94 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) create mode 100644 Demo_Pyploy_Bar_Chart2.py diff --git a/Demo_Pyploy_Bar_Chart2.py b/Demo_Pyploy_Bar_Chart2.py new file mode 100644 index 00000000..37c9339c --- /dev/null +++ b/Demo_Pyploy_Bar_Chart2.py @@ -0,0 +1,94 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUI as sg +else: + import PySimpleGUI27 as sg + +import matplotlib +matplotlib.use('TkAgg') +from matplotlib.backends.backend_tkagg import FigureCanvasAgg +import matplotlib.backends.tkagg as tkagg +import tkinter as Tk + +""" +Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. + +Paste your Pyplot code into the section marked below. + +Do all of your plotting as you normally would, but do NOT call plt.show(). +Stop just short of calling plt.show() and let the GUI do the rest. + +The remainder of the program will convert your plot and display it in the GUI. +If you want to change the GUI, make changes to the GUI portion marked below. + +""" + +#------------------------------- PASTE YOUR MATPLOTLIB CODE HERE ------------------------------- +import matplotlib.pyplot as plt +import numpy as np +label = ['Adventure', 'Action', 'Drama', 'Comedy', 'Thriller/Suspense', 'Horror', 'Romantic Comedy', 'Musical', + 'Documentary', 'Black Comedy', 'Western', 'Concert/Performance', 'Multiple Genres', 'Reality'] +no_movies = [ + 941, + 854, + 4595, + 2125, + 942, + 509, + 548, + 149, + 1952, + 161, + 64, + 61, + 35, + 5 +] + +index = np.arange(len(label)) +plt.bar(index, no_movies) +plt.xlabel('Genre', fontsize=5) +plt.ylabel('No of Movies', fontsize=5) +plt.xticks(index, label, fontsize=5, rotation=30) +plt.title('Market Share for Each Genre 1995-2017') + +#------------------------------- END OF YOUR MATPLOTLIB CODE ------------------------------- + +#------------------------------- Beginning of Matplotlib helper code ----------------------- + + +def draw_figure(canvas, figure, loc=(0, 0)): + """ Draw a matplotlib figure onto a Tk canvas + + loc: location of top-left corner of figure on canvas in pixels. + + Inspired by matplotlib source: lib/matplotlib/backends/backend_tkagg.py + """ + figure_canvas_agg = FigureCanvasAgg(figure) + figure_canvas_agg.draw() + figure_x, figure_y, figure_w, figure_h = figure.bbox.bounds + figure_w, figure_h = int(figure_w), int(figure_h) + photo = Tk.PhotoImage(master=canvas, width=figure_w, height=figure_h) + canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) + tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) + return photo + +#------------------------------- Beginning of GUI CODE ------------------------------- + +fig = plt.gcf() # if using Pyplot then get the figure from the plot +figure_x, figure_y, figure_w, figure_h = fig.bbox.bounds + +# define the window layout +layout = [[sg.Text('Plot test', font='Any 18')], + [sg.Canvas(size=(figure_w, figure_h), key='canvas')], + [sg.OK(pad=((figure_w / 2, 0), 3), size=(4, 2))]] + +# create the form and show it without the plot +window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', force_toplevel=True).Layout(layout).Finalize() + +# add the plot to the window +fig_photo = draw_figure(window.FindElement('canvas').TKCanvas, fig) + +# show it all again and get buttons +button, values = window.Read() From 66aed4c838f7de0b299362ab962ba9cec0432267 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Thu, 4 Oct 2018 19:26:49 -0400 Subject: [PATCH 2/4] New Topanga look and feel. Improved Popup code by removing Text as spacers --- PySimpleGUI.py | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index 5ffe562b..d0772238 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -3939,7 +3939,7 @@ class DebugWin(): self.output_element = Output(size=win_size) self.form_rows = [[Text('EasyPrint Output')], [self.output_element], - [Quit()]] + [DummyButton('Quit')]] self.form.AddRows(self.form_rows) self.form.Show(non_blocking=True) # Show a ;non-blocking form, returns immediately return @@ -4353,6 +4353,10 @@ def ChangeLookAndFeel(index): # look and feel table look_and_feel = {'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}, + # ∩(^-^)∩ + '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}, '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}, @@ -4519,7 +4523,7 @@ def Popup(*args, button_color=None, background_color=None, text_color=None, butt else: local_line_width = MESSAGE_BOX_LINE_WIDTH title = args_to_print[0] if args_to_print[0] is not None else 'None' - form = Window(title, auto_size_text=True, background_color=background_color, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) + window = Window(title, auto_size_text=True, background_color=background_color, button_color=button_color, auto_close=auto_close, auto_close_duration=auto_close_duration, icon=icon, font=font, no_titlebar=no_titlebar, grab_anywhere=grab_anywhere, keep_on_top=keep_on_top, location=location) max_line_total, total_lines = 0,0 for message in args_to_print: # fancy code to check if string and convert if not is not need. Just always convert to string :-) @@ -4535,34 +4539,32 @@ def Popup(*args, button_color=None, background_color=None, text_color=None, butt max_line_total = max(max_line_total, width_used) # height = _GetNumLinesNeeded(message, width_used) height = message_wrapped_lines - form.AddRow(Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) + window.AddRow(Text(message_wrapped, auto_size_text=True, text_color=text_color, background_color=background_color)) total_lines += height - pad = max_line_total-15 if max_line_total > 15 else 1 - pad =1 if non_blocking: - PopupButton = DummyButton + PopupButton = DummyButton # important to use or else button will close other windows too! else: - PopupButton = SimpleButton + PopupButton = Button # show either an OK or Yes/No depending on paramater if button_type is POPUP_BUTTONS_YES_NO: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True), PopupButton('No', button_color=button_color)) + window.AddRow(PopupButton('Yes', button_color=button_color, focus=True, bind_return_key=True, pad=((20,5),3)), PopupButton('No', button_color=button_color)) elif button_type is POPUP_BUTTONS_CANCELLED: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True)) + window.AddRow(PopupButton('Cancelled', button_color=button_color, focus=True, bind_return_key=True, pad=((20,0),3))) elif button_type is POPUP_BUTTONS_ERROR: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('Error', size=(6, 1), button_color=button_color, focus=True, bind_return_key=True)) + window.AddRow(PopupButton('Error', size=(6,1), button_color=button_color, focus=True, bind_return_key=True, pad=((20,0),3))) elif button_type is POPUP_BUTTONS_OK_CANCEL: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False, text_color=text_color, background_color=background_color), PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True), - PopupButton('Cancel', size=(5, 1), button_color=button_color)) + window.AddRow(PopupButton('OK', size=(5,1), button_color=button_color, focus=True, bind_return_key=True), + PopupButton('Cancel', size=(5,1), button_color=button_color)) elif button_type is POPUP_BUTTONS_NO_BUTTONS: pass else: - form.AddRow(Text('', size=(pad, 1), auto_size_text=False, background_color=background_color), PopupButton('OK', size=(5, 1), button_color=button_color, focus=True, bind_return_key=True)) + window.AddRow(PopupButton('OK', size=(5,1), button_color=button_color, focus=True, bind_return_key=True, pad=((20,0),3))) if non_blocking: - button, values = form.ReadNonBlocking() + button, values = window.ReadNonBlocking() else: - button, values = form.Show() + button, values = window.Show() return button From 6913afd771ce7aea98db3bf18b59da069ef67d41 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Thu, 4 Oct 2018 19:42:25 -0400 Subject: [PATCH 3/4] New Demo - Simple Tabs, Demo Tabs now shows many of the locations tabs can live --- Demo_Tabs.py | 35 ++++++++++++++++++++++++++++------- Demo_Tabs_Simple.py | 26 ++++++++++++++++++++++++++ 2 files changed, 54 insertions(+), 7 deletions(-) create mode 100644 Demo_Tabs_Simple.py diff --git a/Demo_Tabs.py b/Demo_Tabs.py index 142f42f2..9a8e30be 100644 --- a/Demo_Tabs.py +++ b/Demo_Tabs.py @@ -5,26 +5,47 @@ if sys.version_info[0] >= 3: else: import PySimpleGUI27 as sg -tab1_layout = [[sg.T('This is inside tab 1')]] +sg.SetOptions(background_color='cornsilk4', element_background_color='cornsilk2', input_elements_background_color='cornsilk2') -tab2_layout = [[sg.T('This is inside tab 2')], +tab1_layout = [[sg.T('This is inside tab 1', background_color='darkslateblue', text_color='white')], + [sg.In(key='_in0_')]] + +tab2_layout = [[sg.T('This is inside tab 2', background_color='tan1')], [sg.In(key='_in2_')]] + tab3_layout = [[sg.T('This is inside tab 3')], + [sg.In(key='_in2_')]] + +tab4_layout = [[sg.T('This is inside tab 4', background_color='darkseagreen')], [sg.In(key='_in3_')]] -tab4_layout = [[sg.T('This is inside tab 4')], +tab5_layout = [[sg.T('This is inside tab 5')], [sg.In(key='_in4_')]] -layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, key='_mykey_'), sg.Tab('Tab 2', tab2_layout)]], key='_group2_', background_color='green', tab_location='top')], -[sg.TabGroup([[sg.Tab('Tab 3', tab3_layout, key='_mykey_'), sg.Tab('Tab 4', tab4_layout)]], key='_group1_', tab_location='right')], - [sg.RButton('Read')]] +layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='_mykey_'), + sg.Tab('Tab 2', tab2_layout, background_color='tan1'), + sg.Tab('Tab 3', tab3_layout)]], + key='_group2_', title_color='red', + selected_title_color='green', tab_location='right'), + sg.TabGroup([[sg.Tab('Tab 4', tab4_layout,background_color='darkseagreen', key='_mykey_'), + sg.Tab('Tab 5', tab5_layout)]], key='_group1_', tab_location='top', selected_title_color='purple')], + [sg.TabGroup([[sg.Tab('Tab 1', tab1_layout, background_color='darkslateblue', key='_mykey_'), + sg.Tab('Tab 2', tab2_layout, background_color='tan1'), + sg.Tab('Tab 3', tab3_layout)]], + key='_group3_', title_color='red', + selected_title_color='green', tab_location='left'), + sg.TabGroup([[sg.Tab('Tab 4', tab4_layout,background_color='darkseagreen', key='_mykey_'), + sg.Tab('Tab 5', tab5_layout)]], key='_group4_', tab_location='bottom', selected_title_color='purple')], + [sg.RButton('Read')]] window = sg.Window('My window with tabs', default_element_size=(12,1)).Layout(layout) + while True: b, v = window.Read() + sg.PopupNonBlocking(b,v) print(b,v) if b is None: # always, always give a way out! - break \ No newline at end of file + break diff --git a/Demo_Tabs_Simple.py b/Demo_Tabs_Simple.py new file mode 100644 index 00000000..0e687e31 --- /dev/null +++ b/Demo_Tabs_Simple.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python +import sys +if sys.version_info[0] >= 3: + import PySimpleGUI as sg +else: + import PySimpleGUI27 as sg + +tab1_layout = [[sg.T('Tab 1')], + [sg.T('Put your layout in here')], + [sg.T('Input something'),sg.In(key='_in0_')]] + +tab2_layout = [[sg.T('Tab2')]] + + +layout = [[sg.TabGroup([[sg.Tab('Tab 1', tab1_layout), sg.Tab('Tab 2', tab2_layout)]])], + [sg.RButton('Read')]] + +window = sg.Window('My window with tabs', default_element_size=(12,1)).Layout(layout) + + +while True: + b, v = window.Read() + sg.PopupNonBlocking('button = %s'%b,'Values dictionary', v) + print(b,v) + if b is None: # always, always give a way out! + break From 2596c0cc457245b07dc213f9605df8a0ea0999c7 Mon Sep 17 00:00:00 2001 From: MikeTheWatchGuy Date: Fri, 5 Oct 2018 02:37:40 -0400 Subject: [PATCH 4/4] New tab feature - Enabled / Disable tab --- PySimpleGUI.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/PySimpleGUI.py b/PySimpleGUI.py index d0772238..3dc89358 100644 --- a/PySimpleGUI.py +++ b/PySimpleGUI.py @@ -1142,8 +1142,7 @@ class Button(Element): self.ParentForm.LastButtonClicked = self.ButtonText self.ParentForm.FormRemainedOpen = True self.ParentForm.TKroot.quit() # kick the users out of the mainloop - elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # this is a return type button so GET RESULTS and destroy window - # if the form is tabbed, must collect all form's results and destroy all forms + elif self.BType == BUTTON_TYPE_CLOSES_WIN_ONLY: # special kind of button that does not exit main loop self.ParentForm._Close() if self.ParentForm.NonBlocking: self.ParentForm.TKroot.destroy() @@ -1482,7 +1481,7 @@ class Frame(Element): # Tab # # ---------------------------------------------------------------------- # class Tab(Element): - def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, border_width=None, key=None, tooltip=None): + def __init__(self, title, layout, title_color=None, background_color=None, font=None, pad=None, disabled=False, border_width=None, key=None, tooltip=None): self.UseDictionary = False self.ReturnValues = None @@ -1494,6 +1493,9 @@ class Tab(Element): self.TKFrame = None self.Title = title self.BorderWidth = border_width + self.Disabled = disabled + self.ParentNotebook = None + self.TabID = None self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.Layout(layout) @@ -1519,6 +1521,15 @@ class Tab(Element): def Layout(self, rows): for row in rows: self.AddRow(*row) + return self + + def Update(self, disabled = None): # TODO Disable / enable of tabs is not complete + if disabled is None: + return + self.Disabled = disabled + state = 'disabled' if disabled is True else 'normal' + self.ParentNotebook.tab(self.TabID, state=state) + return self def _GetElementAtLocation(self, location): (row_num,col_num) = location @@ -1550,6 +1561,7 @@ class TabGroup(Element): self.SelectedTitleColor = selected_title_color self.Rows = [] self.TKNotebook = None + self.TabCount = 0 self.BorderWidth = border_width self.BackgroundColor = background_color if background_color is not None else DEFAULT_BACKGROUND_COLOR self.ChangeSubmits = change_submits @@ -3372,9 +3384,14 @@ def PackFormIntoFrame(form, containing_frame, toplevel_form): elif element_type == ELEM_TYPE_TAB: element.TKFrame = tk.Frame(form.TKNotebook) PackFormIntoFrame(element, element.TKFrame, toplevel_form) - form.TKNotebook.add(element.TKFrame, text=element.Title) + if element.Disabled: + form.TKNotebook.add(element.TKFrame, text=element.Title, state='disabled') + else: + form.TKNotebook.add(element.TKFrame, text=element.Title) form.TKNotebook.pack(side=tk.LEFT, padx=element.Pad[0], pady=element.Pad[1]) - + element.ParentNotebook = form.TKNotebook + element.TabID = form.TabCount + form.TabCount += 1 if element.BackgroundColor != COLOR_SYSTEM_DEFAULT and element.BackgroundColor is not None: element.TKFrame.configure(background=element.BackgroundColor, highlightbackground=element.BackgroundColor,