首页 > 解决方案 > 如何在 tkinter 中删除 matplot 行?

问题描述

我正在尝试制作绘制熊猫数据框(tkinter,matplotlib)的GUI程序

但是分配按钮命令有一些问题

我想要的是在单击按钮时使一行可见/不可见,

起初我尝试使用 for 循环分配按钮,这样我就不需要关心行数

但是当我单击按钮时,只有最后一行会切换状态

所以我打破了循环并在没有循环的情况下分配,并检查了它是否有效。

我怎样才能使第一种方法有效?

import numpy as np
import matplotlib.pyplot as plt
import tkinter as tk
from tkinter import ttk

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

# Sample Data
x = np.arange(100)
y1 = np.sin(x)
y2 = np.cos(x)

data = pd.DataFrame()
data['time'] = x
data['sin'] = y1
data['cos'] = y2


class graph():
    def __init__(self):
        self.win = tk.Tk()
        # Graph region
        self.frame1 = ttk.LabelFrame(self.win,text='Figure')
        self.frame1.grid(row=0,column=0,columnspan=2)

        self.fig,self.ax = plt.subplots()

        self.canvas = FigureCanvasTkAgg(self.fig,master=self.frame1)
        self.canvas.get_tk_widget().grid(row=0,column=0)
        self._read_data(data)

        # Make buttons using for loop
        # it doesn't work!!
        self.frame2= ttk.LabelFrame(self.win,text='graph handle')
        self.frame2.grid(row=1,column=0)

        for i,col in enumerate(self.pic_dic.keys()):
            ttk.Label(self.frame2,text=col).grid(row=i,column=0)
            ttk.Button(self.frame2,text='on/off Graph',command=lambda:self._onoff_pic(col)).grid(row=i,column=1)

        # Make buttons using without loop
        # but it works!!
        self.frame3= ttk.LabelFrame(self.win,text='graph handle (without for loop)')
        self.frame3.grid(row=1,column=1)
        ttk.Label(self.frame3,text='time').grid(row=0,column=0)
        ttk.Button(self.frame3,text='on/off',command=lambda:self._onoff_pic('time')).grid(row=0,column=1)
        ttk.Label(self.frame3,text='sin').grid(row=1,column=0)
        ttk.Button(self.frame3,text='on/off',command=lambda:self._onoff_pic('sin')).grid(row=1,column=1)
        ttk.Label(self.frame3,text='cos').grid(row=2,column=0)
        ttk.Button(self.frame3,text='on/off',command=lambda:self._onoff_pic('cos')).grid(row=2,column=1)

        self.canvas.draw()

    def _read_data(self,data):
        self.pic_dic = {}
        for col in data.columns:
            self.pic_dic[col] = {}
            self.pic_dic[col]['line'], = self.ax.plot(data['time'],data[col])
    def _onoff_pic(self,col):
        tmp = self.pic_dic[col]['line'].get_visible()   
        self.pic_dic[col]['line'].set_visible(not tmp)
        self.canvas.draw()        

a = graph()
a.win.mainloop()
a.win.quit()

感谢!

标签: pythonmatplotlibtkinter

解决方案


在您的代码中:

for i,col in enumerate(self.pic_dic.keys()):
    ttk.Label(self.frame2,text=col).grid(row=i,column=0)
    ttk.Button(self.frame2,text='on/off Graph',command=lambda:self._onoff_pic(col)).grid(row=i,column=1)

的值col将被赋予 for 循环后最后一次迭代的值。因此,当单击按钮时调用 lambda 时,col将使用最终值。

您需要在 lambda 中使用参数的默认值:

for i, col in enumerate(self.pic_dic.keys()):
    ttk.Label(self.frame2, text=col).grid(row=i, column=0)
    ttk.Button(self.frame2, text='on/off Graph', command=lambda c=col: self._onoff_pic(c)).grid(row=i,column=1)

参数的默认值将在创建 lambda 时初始化。


推荐阅读