【问题标题】:Why are my plots not appearing with set_data using Tkinter?为什么我的情节没有出现在使用 Tkinter 的 set_data 中?
【发布时间】:2020-08-28 16:35:09
【问题描述】:

我正在尝试改进我的绘图功能。我想使用来自脑电图板的plotGraph 函数实时 绘制数据,从 LSL @ 250Hz 中提取样本。以前,我有一个使用常规self.ax.plot(x,y) 的功能版本,每次需要刷新绘图时都会使用self.ax.clear() 清除数据。尽管如此,一些分析表明,与其他部分相比,我的代码花费了太多时间来绘制。

我得到的一个建议是使用 set_data 而不是 plot and clear。我有多行数据要同时绘制,所以我尝试关注Matplotlib multiple animate multiple lines,您可以在下面看到(改编代码)。另外,有人告诉我使用self.figure.canvas.draw_idle(),我试过了,但我不确定我是否正确。

不幸的是,它不起作用,图表没有更新,我似乎找不到原因。我知道我刚才提到的来源使用animation.FuncAnimation,但我不确定这会是问题所在。是吗?

关于为什么我的画布图表中没有显示我的线条有什么想法吗?

import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
class AppWindow:
   def plotGraph(self, x, y):
        for lnum,line in enumerate(self.lines):
            line.set_data(x[:], y[:, lnum])
        self.figure.canvas.draw_idle()
        plt.ylabel('Magnitude', fontsize = 9, color = tx_color)
        plt.xlabel('Freq', fontsize = 9, color = tx_color)
        self.figure.canvas.draw()

   def __init__(self):
      self.root = tk.Tk() #start of application
      self.canvas = tk.Canvas(self.root, height = 420, width = 780, bg = 
   bg_color, highlightthickness=0)
      self.canvas.pack(fill = 'both', expand = True)
      self.figure = plt.figure(figsize = (5,6), dpi = 100)
      self.figure.patch.set_facecolor(sc_color)
      self.ax = self.figure.add_subplot(111)
      self.ax.clear()
      self.line, = self.ax.plot([], [], lw=1, color = tx_color)
      self.line.set_data([],[])

      #place graph
      self.chart_type = FigureCanvasTkAgg(self.figure, self.canvas)
      self.chart_type.get_tk_widget().pack()

      self.lines = []
      numchan = 8 #let's say I have 8 channels
      for index in range(numchan):
          lobj = self.ax.plot([],[], lw=2, color=tx_color)[0]
          self.lines.append(lobj)
      for line in self.lines:
      line.set_data([],[])
  
def start(self):
   self.root.mainloop()

【问题讨论】:

  • 这可能是因为缺少 draw 语句。我相信在更新之一之后添加self.figure.canvas.draw() 可能会奏效!
  • 嘿@zwep,感谢您的评论。我尝试在更新后添加self.figure.canvas.draw(),但它仍然不起作用。

标签: python performance matplotlib tkinter


【解决方案1】:

您的图表是空的,因为您正在绘制空数组:

line.set_data([],[])

如果填写线阵,图表绘制正确。

试试这个代码。它每秒用新的随机数据更新图表。

import tkinter as tk
import matplotlib
import matplotlib.pyplot as plt
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import numpy as np
import random

bg_color='grey'
tx_color='green'
sc_color='linen'

numchan = 8
chlen = 100
xvals=[(x-40)/20 for x in range(chlen)]  # X coordinates
chcolors= ['gold','blue','green','maroon','red','brown','purple','cyan']


class AppWindow:
   def plotGraph(self):
      self.figure.canvas.draw_idle()
      plt.ylabel('Magnitude', fontsize = 9, color = tx_color)
      plt.xlabel('Freq', fontsize = 9, color = tx_color)
      self.figure.canvas.draw()
        
   def UpdateChannelData(self):  # callback with new data
      # fake random data
      for i,ch in enumerate(self.chdata):
         for p in range(len(ch)):
            ch[p] += (random.random()-.5)/100
         self.lines[i].set_data(xvals, ch)
         
      self.plotGraph()
      self.root.after(100, self.UpdateChannelData)  # simulate next call

   def __init__(self):
      global chzero
      self.root = tk.Tk() #start of application
      self.canvas = tk.Canvas(self.root, height = 420, width = 780, bg = bg_color, highlightthickness=0)
      self.canvas.pack(fill = 'both', expand = True)
      self.figure = plt.figure(figsize = (5,6), dpi = 100)
      self.figure.patch.set_facecolor(sc_color)
      self.ax = self.figure.add_subplot(111)
      self.ax.clear()
      self.line, = self.ax.plot([], [], lw=1, color = tx_color)
      self.line.set_data([],[])

      #place graph
      self.chart_type = FigureCanvasTkAgg(self.figure, self.canvas)
      self.chart_type.get_tk_widget().pack()

      self.lines = []
      #numchan = 8 #let's say I have 8 channels
      for index in range(numchan):
          lobj = self.ax.plot([],[], lw=1, color=chcolors[index])[0]
          self.lines.append(lobj)
      # set flat data
      self.chdata = [[0 for x in range(chlen)] for ch in range(numchan)]
      self.root.after(1000, self.UpdateChannelData) # start data read
  
   def start(self):
       self.root.mainloop()
       
AppWindow().start()

输出:

【讨论】:

  • 您好@Mike67,感谢您的回答。问题是,在调整你的方式时,我失去了反复调用我的函数来绘制新样本的能力。有没有可以更新函数内绘图的解决方案?
  • 您想以递归方式或循环方式调用plotGraph?还是应该在对plotGraph 的一次调用中设置数据?
  • 在一个while循环中。当样本通过 LSL 进入时,我想绘制它们。
  • 答案已更新。您需要调整缩放比例并插入 EEG 回调机制。
  • 谢谢,迈克。但不幸的是,它仍然没有工作......
猜你喜欢
  • 1970-01-01
  • 2021-09-01
  • 2013-02-16
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多