PySimpleGUI中的交互式matplotlib绘图

PySimpleGUI中的交互式matplotlib绘图,matplotlib,pysimplegui,matplotlib-widget,Matplotlib,Pysimplegui,Matplotlib Widget,我正在尝试让矩形选择器表单matplotlib.widgets与PySimpleGUI一起工作。 我的测试代码基于公认答案中显示的矩形选择器演示 我将在PySimpleGUI中显示情节,但它不是交互式的。在PySimpleGUI中是否可能有交互式matplotlib小部件 import PySimpleGUI as sg import numpy as np import matplotlib.pyplot as plt from matplotlib.backends.backend_tkag

我正在尝试让矩形选择器表单matplotlib.widgets与PySimpleGUI一起工作。 我的测试代码基于公认答案中显示的矩形选择器演示

我将在PySimpleGUI中显示情节,但它不是交互式的。在PySimpleGUI中是否可能有交互式matplotlib小部件

import PySimpleGUI as sg
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.widgets  import RectangleSelector
import matplotlib
matplotlib.use('TkAgg')

xdata = np.linspace(0,9*np.pi, num=301)
ydata = np.sin(xdata)

fig, ax = plt.subplots()
line, = ax.plot(xdata, ydata)


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


def line_select_callback(eclick, erelease):
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata

    rect = plt.Rectangle( (min(x1,x2),min(y1,y2)), np.abs(x1-x2), np.abs(y1-y2) )
    ax.add_patch(rect)


rs = RectangleSelector(ax, line_select_callback,
                       drawtype='box', useblit=False, button=[1],
                       minspanx=5, minspany=5, spancoords='pixels',
                       interactive=True)
                       

layout = [[sg.Canvas(key="-CANVAS-")]]

window = sg.Window('test', layout, finalize=True, element_justification='center', font='Helvetica 16')
draw_figure(window["-CANVAS-"].TKCanvas, fig)
event, values = window.read()
编辑:多亏了MikeyB的指针,我现在有了下面的代码,它显示了一个交互式绘图,但仍然无法绘制矩形。回调函数似乎没有启动。新代码如下:

import PySimpleGUI as sg
import numpy as np
from matplotlib.widgets  import RectangleSelector
import matplotlib.figure as figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk

# instantiate matplotlib figure
fig = figure.Figure()
ax = fig.add_subplot(111)
DPI = fig.get_dpi()
fig.set_size_inches(505 * 2 / float(DPI), 707 / float(DPI))

# ------------------------------- This is to include a matplotlib figure in a Tkinter canvas
def draw_figure_w_toolbar(canvas, fig, canvas_toolbar):
    if canvas.children:
        for child in canvas.winfo_children():
            child.destroy()
    if canvas_toolbar.children:
        for child in canvas_toolbar.winfo_children():
            child.destroy()
    figure_canvas_agg = FigureCanvasTkAgg(fig, master=canvas)
    figure_canvas_agg.draw()
    toolbar = Toolbar(figure_canvas_agg, canvas_toolbar)
    toolbar.update()
    figure_canvas_agg.get_tk_widget().pack(side='right', fill='both', expand=1)


def line_select_callback(eclick, erelease):
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata

    rect = plt.Rectangle( (min(x1,x2),min(y1,y2)), np.abs(x1-x2), np.abs(y1-y2) )
    print(rect)
    ax.add_patch(rect)


class Toolbar(NavigationToolbar2Tk):
    def __init__(self, *args, **kwargs):
        super(Toolbar, self).__init__(*args, **kwargs)


# ------------------------------- PySimpleGUI CODE

layout = [
    [sg.B('start', key='start')],
    [sg.Canvas(key='controls_cv')],
    [sg.Column(
        layout=[
            [sg.Canvas(key='fig_cv',
                       # it's important that you set this size
                       size=(500 * 2, 700)
                       )]
        ],
        background_color='#DAE0E6',
        pad=(0, 0)
    )],
]

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

while True:
    event, values = window.read()
    print(event, values)
    if event == sg.WIN_CLOSED:
        break
    elif event == 'start':
        x = np.linspace(0, 2 * np.pi)
        y = np.sin(x)
        line, = ax.plot(x, y)
        rs = RectangleSelector(ax, line_select_callback,
                       drawtype='box', useblit=False, button=[1],
                       minspanx=5, minspany=5, spancoords='pixels',
                       interactive=True)
        draw_figure_w_toolbar(window['fig_cv'].TKCanvas, fig, window['controls_cv'].TKCanvas)

window.close()
在PySimpleGUI中是否可能有交互式matplotlib小部件

import PySimpleGUI as sg
import numpy as np
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.widgets  import RectangleSelector
import matplotlib
matplotlib.use('TkAgg')

xdata = np.linspace(0,9*np.pi, num=301)
ydata = np.sin(xdata)

fig, ax = plt.subplots()
line, = ax.plot(xdata, ydata)


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


def line_select_callback(eclick, erelease):
    x1, y1 = eclick.xdata, eclick.ydata
    x2, y2 = erelease.xdata, erelease.ydata

    rect = plt.Rectangle( (min(x1,x2),min(y1,y2)), np.abs(x1-x2), np.abs(y1-y2) )
    ax.add_patch(rect)


rs = RectangleSelector(ax, line_select_callback,
                       drawtype='box', useblit=False, button=[1],
                       minspanx=5, minspany=5, spancoords='pixels',
                       interactive=True)
                       

layout = [[sg.Canvas(key="-CANVAS-")]]

window = sg.Window('test', layout, finalize=True, element_justification='center', font='Helvetica 16')
draw_figure(window["-CANVAS-"].TKCanvas, fig)
event, values = window.read()

项目GitHub上的演示程序显示了如何制作交互式Matplotlib图形

您需要将控件嵌入窗口。

您需要添加

fig.canvas.draw()
如果您希望在触发回调后更新绘图,请转到回调函数

以下是代码的更新版本,运行良好:

将PySimpleGUI导入为sg
将numpy作为np导入
从matplotlib.widgets导入矩形选择器
将matplotlib.figure导入为figure
从matplotlib.backends.backend_tkagg导入图CAVASTKAGG,导航工具栏2TK
将matplotlib.pyplot作为plt导入
#实例化matplotlib图形
图=图。图()
ax=图添加_子批次(111)
DPI=图get_DPI()
图设置尺寸英寸(505*2/浮子(DPI),707/浮子(DPI))
#------------------------------------这是在Tkinter画布中包含matplotlib图形
def draw_figure_w_工具栏(画布、fig、画布工具栏):
如果是儿童:
对于画布中的子对象。winfo_children():
child.destroy()
如果canvas_toolbar.children:
对于canvas_工具栏中的子对象。winfo_子对象():
child.destroy()
figure_canvas_agg=FigureCanvasTkAgg(图,主视图=画布)
图_canvas_agg.draw()
工具栏=工具栏(图\u画布\u agg,画布\u工具栏)
toolbar.update()
图\u canvas\u agg.get\u tk\u widget().pack(side='right',fill='both',expand=1)
def line_select_回调(电子单击,轻松):
x1,y1=eclick.xdata,eclick.ydata
x2,y2=release.xdata,release.ydata
矩形=plt.矩形((最小(x1,x2),最小(y1,y2)),np.abs(x1-x2),np.abs(y1-y2))
打印(矩形)
ax.add_补丁(rect)
图canvas.draw()
类工具栏(导航工具栏2TK):
定义初始化(self,*args,**kwargs):
超级(工具栏,自我)。\uuuuuuuuuuuuuuuuuu初始(*args,**kwargs)
#------------------------------------PySimpleGUI代码
布局=[
[sg.B('start',key='start')],
[sg.Canvas(key='controls_cv')],
[sg.Column](
布局=[
[sg.Canvas(图例='fig_cv',
#设置这个尺寸很重要
尺寸=(500*2700)
)]
],
背景颜色='#DAE0E6',
pad=(0,0)
)],
]
窗口=sg.窗口(“测试”,布局)
尽管如此:
事件,值=window.read()
打印(事件、值)
如果事件==sg.WIN\u关闭:
打破
elif事件=='开始':
x=np.linspace(0,2*np.pi)
y=np.sin(x)
直线,=轴图(x,y)
rs=矩形选择器(ax,行选择回调,
drawtype='box',useblit=False,button=[1],
minspanx=5,minspany=5,spancoords='pixels',
交互式=真)
绘图工具条(窗口['fig_cv'].TKCanvas,fig,窗口['controls_cv'].TKCanvas)
window.close()

谢谢!我现在使用这个演示作为起点,并更新了问题中的代码,但仍然没有得到任何东西。