matplotlib funcAnimation和Tkinter的性能低迷

时间:2017-05-10 21:22:07

标签: python matplotlib tkinter

我在使用Matplotlib动画(来自Arduino的串行端口数据)的Tkinter应用程序中获得不错的性能时遇到了一些问题,除了高性能桌面以外我认为我做的事情效率低下。

该应用程序按我想要的方式工作,一切正常显示,它只是相当滞后。基于测试,这似乎是matplotlib实现的一个问题,当动画运行时,一切都会慢下来。我曾试图在funcanimation中打开blitting,但这似乎没有什么区别。当它只是Tkinter没有图表时,它的时髦。

另一方面,当我只运行图表时(即没有用gui包裹),一切似乎都相对顺利。这可能是TkAgg的后端吗?或者是Tkinter与资源竞争,图形正在消耗更新线?

import matplotlib
import Tkinter as tk
import ttk
import tkFileDialog
import serial
import io
import os
import matplotlib.animation as animation
import numpy as np

from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure 
from matplotlib import style
from serialFunctions import findArduino #custom function to identify arduino from com port address

用于funcanimation的matplotlib代码:

fig = Figure()
ax = fig.add_subplot(111)
line, = ax.plot(np.random.rand(10), color = 'red', label = 'Velocity (cm/s)')
sio = io.TextIOWrapper(io.BufferedRWPair(arduino, arduino, 1))

#Data Update
tmin = 0.0
tmax = 10.0

def init():
    line.set_data([], [])
    return line,

def run(data):
    t, y = data
    #print t , y
    xdata.append(t)
    ydata.append(y)
    line.set_data(xdata, ydata)

    if t >= tmax- 1.00:
        line.axes.set_xlim(t - tmax + 1.0, t + 1.0)

    return line,

def data_gen():
    '''Generator to pass data to the run function via funcanimation'''
    t = 0
    while True:
        t+=0.1
        try:
            dat = float(sio.readline())
            # print dat
        except:
            dat = 0
        yield t, dat

ani = animation.FuncAnimation(fig, run, data_gen, init_func = init, interval=20, blit=False)

Tkinter相关代码:

matplotlib.use('TkAgg')

class StreamPage(tk.Frame):

    def __init__(self, parent, controller):
        tk.Frame.__init__(self, parent, {'bg': '#020b19'})

        label = tk.Label(self, text = 'Begin Streaming', font = LARGE_FONT)
        label.pack(pady = 10, padx = 10)

        backButton = ttk.Button(self, text = 'Back', 
                                command = lambda: 
                                controller.show_frame(StartPage))
        backButton.pack()

        canvas = FigureCanvasTkAgg(fig, self)

        canvas.show()

        canvas.get_tk_widget().pack(side = tk.TOP, fill = tk.BOTH, expand = True)

        #toolbar = NavigationToolbar2TkAgg(canvas, self)

        #toolbar.update()

        canvas._tkcanvas.pack(side = tk.TOP, fill = tk.BOTH, expand = True)

Arduino代码

int const potPin = A0;
int potVal;

void setup() {
  // put your setup code here, to run once:
  analogReference(DEFAULT); //EXTERNAL NO MORE THAN 5V!
  Serial.begin(1200);
}

void loop() {
  // put your main code here, to run repeatedly:

  potVal = analogRead(potPin);

  float voltage = potVal * (5.0/1024.0); 
  Serial.print(voltage);
  Serial.print('\n');
}

1 个答案:

答案 0 :(得分:0)

我在同样的性能问题上苦苦挣扎,并在这里找到了很好的建议: http://effbot.org/zone/tkinter-performance.htm

在run函数中调用update_idletasks对我来说大大提高了性能。