PySimpleGUI에 Matplotlib을 포함하고 싶습니다.

소개



PySimpleGUI는 이름 그대로 매우 간단하게 GUI를 작성할 수 있어 게다가 의외로 고기능인 GUI를 만들 수 있습니다. 저는 주로 연구용 도구를 만드는 목적으로 PySimpleGUI를 사용하고 있습니다만, GUI에 Matplotlib의 그래프를 임베드하고 싶은 경우가 자주 있습니다. 이 기사에서는 그 방법을 정리하고 있습니다.
이 기사의 내용은 공식 Cook Book과 GitHub를 참고로 하고 있습니다.
  • PySimpleGUI GitHub
  • PySimpleGUI Document
  • PySimpleGUI Cook Book

  • 이 기사에서 만드는 것





    Add 버튼을 누를 때마다 임의의 sin 파가 그려지고 Clear 버튼으로 캔버스를 지울 수있는 단순한 프로그램입니다.

    설치



    파이썬 3.8.2를 사용하고 있습니다. 3계이면 문제 없게 움직인다고 생각합니다.

    공식 문서에서는 pip에서의 설치 방법이 쓰여져 있습니다만, Anaconda에서도 문제없이 설치할 수 있습니다. 나는 Anaconda를 사용하고 있습니다.
    pip install pysimplegui
    or
    conda install pysimplegui
    

    conda로 설치할 수 없다면
    conda install -c conda-forge pysimplegui
    

    시도해보십시오.

    Matplotlib도 사용하고 싶기 때문에 설치합니다.
    conda install matplotlib
    

    프로그램



    embedded-matplotlib.py
    import numpy as np
    import PySimpleGUI as sg
    import matplotlib.pyplot as plt
    from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
    
    # GUIがぼやける現象を防ぐための関数
    def make_dpi_aware():
      import ctypes
      import platform
      if int(platform.release()) >= 8:
        ctypes.windll.shcore.SetProcessDpiAwareness(True)
    make_dpi_aware()
    
    # 描画用の関数
    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 = [[sg.Text('Embed Matplotlib Plot')],
              [sg.Canvas(key='-CANVAS-')],
              [sg.Button("Add"), sg.Button("Clear")]]
    
    # windowを作成する.finalize=Trueにする必要がある.
    window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True, element_justification='center', font='Monospace 18')
    
    # 埋め込む用のfigを作成する.
    fig = plt.figure(figsize=(5, 4))
    ax = fig.add_subplot(111)
    ax.set_ylim(-10, 10)
    
    # figとCanvasを関連付ける.
    fig_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)
    
    # イベントループ
    while True:
        event, values = window.read()
        print(event, values)
        # sg.Print(event, values)
    
        if event in (None, "Cancel"):
            break
    
        elif event == "Add":
            # 適当なプロット用データ作成
            t = np.linspace(0, 7, 100)
            afreq = np.random.randint(1, 10)
            amp = np.random.randint(1, 10)
            y = amp * np.sin(afreq * t)
    
            # プロット
            ax.plot(t, y, alpha=0.4)
    
            # 変更を加えたあと,fig_agg.draw()で変更を反映させる.
            fig_agg.draw()
    
        elif event == "Clear":
            ax.cla()
            fig_agg.draw()
    
    # ウィンドウを閉じる.
    window.close()
    

    해설



    PySimpleGUI의 기본 부분은 공식 문서 등을 참조하십시오.

    창 해상도가 거친 문제



    본제와는 관계 없습니다만, PySimpleGUI로 윈도우를 표시했을 때, 해상도가 거칠어져 보이지 않게 되는 일이 있습니다. 그 해결책으로서 make_dpi_aware 함수를 프로그램의 최초로 실행하고 있습니다. 환경에 따라서는 이것이 없어도 문제 없게 표시되는 것 같습니다. 나는 PySimpleGUI 프로그램의 시작 부분에 항상이 프로세스를 작성하려고합니다. 자세한 내용은 이 GitHub Issue을 참조하십시오.
    def make_dpi_aware():
      import ctypes
      import platform
      if int(platform.release()) >= 8:
        ctypes.windll.shcore.SetProcessDpiAwareness(True)
    

    Matplotlib 플롯 포함



    이쪽이 본제입니다.

    먼저 창을 만듭니다. 여기서 중요한 것은 플롯 포함을위한 요소로 Canvas를 사용하고 창을 만들 때 finalize=True를 지정하는 것입니다.
    # レイアウト作成
    layout = [[sg.Text('Embed Matplotlib Plot')],
              [sg.Canvas(key='-CANVAS-')],
              [sg.Button("Add"), sg.Button("Clear")]]
    
    # windowを作成する.finalize=Trueにする必要がある.
    window = sg.Window('Demo Application - Embedding Matplotlib In PySimpleGUI', layout, finalize=True, element_justification='center', font='Monospace 18')
    

    다음에 매입하고 싶은 플롯을 평상시대로 작성합니다.
    fig = plt.figure(figsize=(5, 4))
    ax = fig.add_subplot(111)
    ax.set_ylim(-10, 10)
    

    그런 다음 생성 된 플롯과 Canvas 요소를 연결합니다. draw_figure 나중에 함수 반환 값이 필요합니다.
    # figとCanvasを関連付ける.
    fig_agg = draw_figure(window['-CANVAS-'].TKCanvas, fig)
    

    여기에서 사용되는 draw_figure 함수는 다음과 같습니다. 기본적으로이 함수의 내용을 바꿀 필요는 없으며, 그대로 복사하여 사용할 수 있습니다. 사용시에는 프로그램의 4행째에 있도록FigureCanvasTkAgg의 임포트가 필요합니다.
    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
    

    여기까지 임베드는 완료입니다.

    플롯 업데이트



    작성한 프로그램에서는 Add 버튼을 누르면 플롯에 sin파가 추가됩니다. 이 방법으로 플롯을 업데이트하려면 먼저 ax.plot()를 실행하고 플롯 변경을 반영하기 위해 fig_agg.draw()를 실행합니다.
            # 適当なプロット用データ作成
            t = np.linspace(0, 7, 100)
            afreq = np.random.randint(1, 10)
            amp = np.random.randint(1, 10)
            y = amp * np.sin(afreq * t)
    
            # プロット
            ax.plot(t, y, alpha=0.4)
    
            # 変更を加えたあと,fig_agg.draw()で変更を反映させる.
            fig_agg.draw()
    

    좋은 웹페이지 즐겨찾기