即使图 window 已关闭,当您在调用 show() 之前打开和关闭 PySimpleGui window 时,Matplotlib show() 函数也会阻塞

Matplotlib's show() function blocks even though figure window is closed, when you open and close a PySimpleGui window before you call show()


当我 运行 遇到 PySimpleGui window 关闭后来自 matplotlib 的 show() 函数被阻止的问题时,我想用 PySimpleGui 为我的小程序提供一个漂亮的 GUI,即使 window图的关闭。
这是一个不确定的示例代码:

import PySimpleGUI as sg
import matplotlib.pyplot as plt

sg.theme('DarkAmber')   

layout = [  [sg.Text('Some text on Row 1')],
        [sg.Text('Enter something on Row 2'), sg.InputText()],
        [sg.Button('Ok'), sg.Button('Cancel')] ]

window = sg.Window('Window Title', layout)

while True:
    event, values = window.read()
    if event == sg.WIN_CLOSED or event == 'Cancel': # if user closes window or clicks cancel
        break
    print('You entered ', values[0])

window.close()

plt.plot([1,2,3,4,5,6])
plt.show() 

你的代码在我的机器上运行良好。在 GUI 上按取消后,绘图显示:

是的,它也适用于我的平台。

WIN10, Python 3.9.5, PySimpleGUI 4.40.0.4, tkinter 8.6.9, Matplotlib 3.4.2

以下代码展示了我如何将 Matplotlib 嵌入到 PySimpleGUI.

import math

from matplotlib import use as use_agg
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib.pyplot as plt
import PySimpleGUI as sg

def pack_figure(graph, figure):
    canvas = FigureCanvasTkAgg(figure, graph.Widget)
    plot_widget = canvas.get_tk_widget()
    plot_widget.pack(side='top', fill='both', expand=1)
    return plot_widget

def plot_figure(index, theta):
    fig = plt.figure(index)         # Active an existing figure
    ax = plt.gca()                  # Get the current axes
    x = [degree for degree in range(1080)]
    y = [math.sin((degree+theta)/180*math.pi) for degree in range(1080)]
    ax.cla()                        # Clear the current axes
    ax.set_title("Sensor Data")
    ax.set_xlabel("X axis")
    ax.set_ylabel("Y axis")
    ax.set_xscale('log')
    ax.grid()
    plt.plot(x, y)                  # Plot y versus x as lines and/or markers
    fig.canvas.draw()               # Rendor figure into canvas

# Use Tkinter Agg
use_agg('TkAgg')

Firsttab    = [[sg.Graph((640, 480), (0, 0), (640, 480),key='Graph1')]]
Secondtab   = [[sg.Graph((640, 480), (0, 0), (640, 480),key='Graph2')]]

tab_group_layout = [
    [sg.Tab('test', Firsttab,font='Courier 15', key='FirstTAB')],
    [sg.Tab('test2', Secondtab,font='Courier 15', key='SecondTAB')],
]

column_layout= [[sg.TabGroup(tab_group_layout, enable_events=True,key='TABGROUP')]]

# PySimplGUI window
layout = [[sg.Column(column_layout, visible = True, key='GRAPHPANEL')],
          [sg.Button(button_text = 'Graph', key='Start')]]

window = sg.Window('Matplotlib', layout, finalize=True)
# Set Button to repeat
window['Start'].Widget.configure(repeatdelay=50, repeatinterval=50)

# Initial
graph1 = window['Graph1']
graph2 = window['Graph2']
plt.ioff()                          # Turn the interactive mode off
fig1 = plt.figure(1)                # Create a new figure
ax1 = plt.subplot(111)              # Add a subplot to the current figure.
fig2 = plt.figure(2)                # Create a new figure
ax2 = plt.subplot(111)              # Add a subplot to the current figure.
pack_figure(graph1, fig1)           # Pack figure under graph
pack_figure(graph2, fig2)
theta1 = 0                          # theta for fig1
theta2 = 0                          # theta for fig2
index = 1                           # Current Tab
plot_figure(1, theta1)
plot_figure(2, theta2)
flag1, flag2 = False, False
while True:

    event, values = window.read(timeout=100)

    if event == sg.WINDOW_CLOSED:
        break
    elif event == sg.TIMEOUT_KEY:
        if index == 1 and flag1:
            theta1 = (theta1 + 10) % 360
            plot_figure(index, theta1)
        elif index == 2 and flag2:
            theta2 = (theta2 + 10) % 260
            plot_figure(index, theta2)
    elif event == 'Start':
        print('Start', index)
        if index == 1:
            flag1 = not flag1
        elif index == 2:
            flag2 = not flag2
        print(flag1, flag2)
    elif event == 'TABGROUP':
        index = 1 if values[event].startswith('First') else 2

window.close()