[PYTHON] I want to embed Matplotlib in PySimpleGUI

Introduction

As the name suggests, PySimpleGUI makes it very easy to create a GUI, and you can also create a surprisingly high-performance GUI. I use the PySimple GUI mainly for the purpose of creating research tools, but I often want to embed Matplotlib graphs in the GUI. This article summarizes how to do it. The content of this article is based on the official Cook Book and GitHub.

What to make in this article

image.png

A random sine wave is drawn each time the Add button is pressed, and it is a simple program that allows you to erase the canvas with the Clear button.

Installation

I'm using Python 3.8.2. If it is 3 system, it will work without any problem.

The official documentation describes how to install with pip, but you can also install with Anaconda without any problems. I use Anaconda.

pip install pysimplegui
or
conda install pysimplegui

If you can't install with conda

conda install -c conda-forge pysimplegui

Please try.

I also want to use Matplotlib, so install it.

conda install matplotlib

program

embedded-matplotlib.py


import numpy as np
import PySimpleGUI as sg
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

#Functions to prevent GUI blurring
def make_dpi_aware():
  import ctypes
  import platform
  if int(platform.release()) >= 8:
    ctypes.windll.shcore.SetProcessDpiAwareness(True)
make_dpi_aware()

#Function for drawing
def draw_figure(canvas, figure):
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
    return figure_canvas_agg

#Layout creation
layout = [[sg.Text('Embed Matplotlib Plot')],
          [sg.Canvas(key='-CANVAS-')],
          [sg.Button("Add"), sg.Button("Clear")]]

#Create a window. finalize=Must be True.
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True, element_justification='center', font='Monospace 18')

#Create a fig for embedding.
fig = plt.figure(figsize=(5, 4))
ax = fig.add_subplot(111)
ax.set_ylim(-10, 10)

#Associate fig with Canvas.
fig_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)

#Event loop
while True:
    event, values = window.read()
    print(event, values)
    # sg.Print(event, values)
    
    if event in (None, "Cancel"):
        break
    
    elif event == "Add":
        #Creating appropriate plot data
        t = np.linspace(0, 7, 100)
        afreq = np.random.randint(1, 10)
        amp = np.random.randint(1, 10)
        y = amp * np.sin(afreq * t)
        
        #plot
        ax.plot(t, y, alpha=0.4)
        
        #After making changes, fig_agg.draw()Reflect the change with.
        fig_agg.draw()

    elif event == "Clear":
        ax.cla()
        fig_agg.draw()

#close the window.
window.close()

Commentary

For the basic part of PySimpleGUI, please refer to the official document.

Rough window resolution issue

Although it has nothing to do with the main subject, when the window is displayed with PySimpleGUI, the resolution may become rough and difficult to see. The solution is to run the make_dpi_aware function at the beginning of the program. Depending on the environment, it seems to be displayed without problems even without this. I always write this process at the beginning of the PySimple GUI program. See This GitHub Issue for more information.

def make_dpi_aware():
  import ctypes
  import platform
  if int(platform.release()) >= 8:
    ctypes.windll.shcore.SetProcessDpiAwareness(True)

Embed Matplotlib plot

This is the main subject.

First, create a window. The important thing here is to use Canvas as the element for embedding the plot, and to specify finalize = True when creating the window.

#Layout creation
layout = [[sg.Text('Embed Matplotlib Plot')],
          [sg.Canvas(key='-CANVAS-')],
          [sg.Button("Add"), sg.Button("Clear")]]

#Create a window. finalize=Must be True.
window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True, element_justification='center', font='Monospace 18')

Next, create the plot you want to embed as usual.

fig = plt.figure(figsize=(5, 4))
ax = fig.add_subplot(111)
ax.set_ylim(-10, 10)

Next, link the created plot with the Canvas element. You will need the return value of the draw_figure function later.

#Associate fig with Canvas.
fig_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)

The draw_figure function used here is as follows. Basically, there is no need to change the contents of this function, and you can copy and use it as it is. To use it, you need to import FigureCanvasTkAgg as shown on the 4th line of the program.

def draw_figure(canvas, figure):
    figure_canvas_agg = FigureCanvasTkAgg(figure, canvas)
    figure_canvas_agg.draw()
    figure_canvas_agg.get_tk_widget().pack(side='top', fill='both', expand=1)
    return figure_canvas_agg

Embedding is completed up to this point.

Update the plot

In the created program, pressing the Add button will add a sine wave to the plot. To update the plot in this way, first run ʻax.plot () and then fig_agg.draw () `to reflect the plot changes.

        #Creating appropriate plot data
        t = np.linspace(0, 7, 100)
        afreq = np.random.randint(1, 10)
        amp = np.random.randint(1, 10)
        y = amp * np.sin(afreq * t)

        #plot
        ax.plot(t, y, alpha=0.4)

        #After making changes, fig_agg.draw()Reflect the change with.
        fig_agg.draw()

Recommended Posts

I want to embed Matplotlib in PySimpleGUI
I want to embed a variable in a Python string
I want to print in a comprehension
I want to make matplotlib a dark theme
I want to do Dunnett's test in Python
I want to pin Datetime.now in Django tests
I want to display multiple images with matplotlib.
I want to store DB information in list
I want to merge nested dicts in Python
I want to display the progress in Python!
I want to change the color by clicking the scatter point in matplotlib
I want to write in Python! (1) Code format check
I want to easily implement a timeout in python
I want to transition with a button in flask
I want to use self in Backpropagation (tf.custom_gradient) (tensorflow)
Embed matplotlib graphs in Tkinter
I want to write in Python! (2) Let's write a test
Even in JavaScript, I want to see Python `range ()`!
I want to randomly sample a file in Python
I want to solve Sudoku (Sudoku)
I want to work with a robot in python.
I want to write in Python! (3) Utilize the mock
I want to manually create a legend with matplotlib
I want to use the R dataset in python
I want to do something in Python when I finish
I want to manipulate strings in Kotlin like Python!
[Django] I want to log in automatically after new registration
I want to make the Dictionary type in the List unique
[Introduction to Pytorch] I want to generate sentences in news articles
I want to align the significant figures in the Numpy array
I want to be able to run Python in VS Code
I want to make input () a nice complement in python
I didn't want to write the AWS key in the program
I want to understand systemd roughly
I want to scrape images to learn
I want to do ○○ with Pandas
I want to copy yolo annotations
I want to debug with Python
[Linux] I want to know the date when the user logged in
I want to run Rails with rails s even in vagrant environment
LINEbot development, I want to check the operation in the local environment
[Python / AWS Lambda layers] I want to reuse only module in AWS Lambda Layers
I want to create a pipfile and reflect it in docker
I want to make the second line the column name in pandas
I want to pass the G test in one month Day 1
I want to know the population of each country in the world.
I want to pin Spyder to the taskbar
I tried to implement PLSA in Python
How to suppress display error in matplotlib
I want to output to the console coolly
I tried to implement permutation in Python
I want to scrape them all together.
I want to handle the rhyme part1
I want to know how LINUX works!
I want to handle the rhyme part3
I tried to implement PLSA in Python 2
I want to use jar from python
I want to analyze logs with Python
I want to play with aws with python
I tried to implement ADALINE in Python
I want to use IPython Qt Console