From ec78bd33273db3f3be097c1f2949039edf2ba35f Mon Sep 17 00:00:00 2001 From: PySimpleGUI Date: Thu, 19 Sep 2019 11:24:40 -0400 Subject: [PATCH] Updated to work with 3.1.1 --- DemoPrograms/Demo_Matplotlib_Browser.py | 94 +++++++++---------------- 1 file changed, 33 insertions(+), 61 deletions(-) diff --git a/DemoPrograms/Demo_Matplotlib_Browser.py b/DemoPrograms/Demo_Matplotlib_Browser.py index 00b7ca5a..10653f7a 100644 --- a/DemoPrograms/Demo_Matplotlib_Browser.py +++ b/DemoPrograms/Demo_Matplotlib_Browser.py @@ -1,16 +1,11 @@ #!/usr/bin/env python -import sys -if sys.version_info[0] >= 3: - import PySimpleGUI as sg -else: - import PySimpleGUI27 as sg +import PySimpleGUI as sg import matplotlib matplotlib.use('TkAgg') -from matplotlib.backends.backend_tkagg import FigureCanvasAgg -import matplotlib.backends.tkagg as tkagg -import tkinter as Tk import inspect +from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg + """ Demonstrates one way of embedding Matplotlib figures into a PySimpleGUI window. @@ -20,10 +15,10 @@ Basic steps are: * Display form (NON BLOCKING) * Draw plots onto convas * Display form (BLOCKING) + +Each plotting function, complete with imports, was copied directly from Matplot examples page """ - - import numpy as np import matplotlib.pyplot as plt @@ -825,39 +820,24 @@ def AxesGrid(): plt.draw() return plt.gcf() + + # The magic function that makes it possible.... glues together tkinter and pyplot using Canvas Widget 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 = FigureCanvasTkAgg(figure, canvas) 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) - - # Position: convert from top-left anchor to center anchor - canvas.create_image(loc[0] + figure_w/2, loc[1] + figure_h/2, image=photo) - - # Unfortunately, there's no accessor for the pointer to the native renderer - tkagg.blit(photo, figure_canvas_agg.get_renderer()._renderer, colormode=2) - - # Return a handle which contains a reference to the photo object - # which must be kept live or else the picture disappears - return photo + figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1) + return figure_canvas_agg +def delete_figure_agg(figure_agg): + figure_agg.get_tk_widget().forget() + plt.close('all') # -------------------------------- GUI Starts Here -------------------------------# # fig = your figure you want to display. Assumption is that 'fig' holds the # # information to display. # # --------------------------------------------------------------------------------# -# print(inspect.getsource(PyplotSimple)) - - fig_dict = {'Pyplot Simple':PyplotSimple, 'Pyplot Formatstr':PyplotFormatstr,'PyPlot Three':Subplot3d, 'Unicode Minus': UnicodeMinus, 'Pyplot Scales' : PyplotScales, 'Axes Grid' : AxesGrid, 'Exploring Normalizations' : ExploringNormalizations, 'Different Scales' : DifferentScales, @@ -866,41 +846,33 @@ fig_dict = {'Pyplot Simple':PyplotSimple, 'Pyplot Formatstr':PyplotFormatstr,'Py 'Pyplot Scatter With Legend' :PyplotScatterWithLegend, 'Artist Customized Box Plots' : PyplotArtistBoxPlots, 'Artist Customized Box Plots 2' : ArtistBoxplot2, 'Pyplot Histogram' : PyplotHistogram} - sg.ChangeLookAndFeel('LightGreen') + figure_w, figure_h = 650, 650 # define the form layout -listbox_values = [key for key in fig_dict.keys()] -col_listbox = [[sg.Listbox(values=listbox_values, change_submits=True, size=(28, len(listbox_values)), key='func')], +listbox_values = list(fig_dict) +col_listbox = [[sg.Listbox(values=listbox_values, change_submits=True, size=(28, len(listbox_values)), key='-LISTBOX-')], [sg.T(' ' * 12), sg.Exit(size=(5, 2))]] layout = [[sg.Text('Matplotlib Plot Test', font=('current 18'))], - [sg.Column(col_listbox, pad=(5, (3, 330))), sg.Canvas(size=(figure_w, figure_h), key='canvas') , - sg.Multiline(size=(70, 35), pad=(5, (3, 90)), key='multiline')],] + [sg.Column(col_listbox, pad=(5, (3, 330))), sg.Canvas(size=(figure_w, figure_h), key='-CANVAS-') , + sg.Multiline(size=(70, 35), pad=(5, (3, 90)), key='-MULTILINE-')],] # create the form and show it without the plot -window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', grab_anywhere=False).Layout(layout) -window.Finalize() - -canvas_elem = window.FindElement('canvas') -multiline_elem= window.FindElement('multiline') - +window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, grab_anywhere=False, finalize=True) +figure_agg = None +# The GUI Event Loop while True: - event, values = window.Read() - print(event) - # show it all again and get buttons - if event in (None, 'Exit'): + event, values = window.read() + # print(event, values) # helps greatly when debugging + if event in (None, 'Exit'): # if user closed window or clicked Exit button break - - try: - choice = values['func'][0] - func = fig_dict[choice] - except: - pass - - multiline_elem.Update(inspect.getsource(func)) - plt.clf() - fig = func() - fig_photo = draw_figure(canvas_elem.TKCanvas, fig) - - + if figure_agg: + # ** IMPORTANT ** Clean up previous drawing before drawing again + delete_figure_agg(figure_agg) + choice = values['-LISTBOX-'][0] # get first listbox item chosen (returned as a list) + func = fig_dict[choice] # get function to call from the dictionary + window['-MULTILINE-'].Update(inspect.getsource(func)) # show source code to function in multiline + fig = func() # call function to get the figure + figure_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig) # draw the figure +window.close() \ No newline at end of file