【问题标题】:Sluggish performance in matplotlib funcAnimation and Tkintermatplotlib funcAnimation 和 Tkinter 的性能缓慢
【发布时间】:2017-05-10 21:22:06
【问题描述】:

我在我的 Tkinter 应用程序中使用 Matplotlib 动画(来自 Arduino 的串行端口数据)在高性能桌面以外的任何设备上获得不错的性能时遇到了一些麻烦,这让我觉得我在做一些低效的事情。

该应用程序按我的意愿运行,并且一切都正确显示,只是相当滞后。根据测试,这似乎是 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

函数动画的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');
}

【问题讨论】:

  • “性能缓慢”不是一个很好的问题描述。尝试找出代码的哪一部分花费的时间最多,然后将您的问题集中在该部分上。
  • 很抱歉,我已经对此进行了一些改进,它似乎是funcanimation的实现。当它处于活动状态时,动画本身和 Tkinter 都会减慢并变得非常无响应。分开时,每个组件都运行良好。好像每个组件都在争夺处理时间。
  • 请添加运行代码所需的所有“导入”...此外,不久前我使用 matplotlib 绘制了一个滞后的 3D 图。当我切换到myavi 时,性能得到了很大的提升;如果你换了,也许你的表现会提高? (需要 python 2.7。)
  • 我已经为此添加了所有导入。我没有听说过 myavi,但我会检查一下。您是否将其与 Tkinter 集成?

标签: python matplotlib tkinter


【解决方案1】:

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

在 run 函数中调用 update_idletasks 显着提高了我的性能。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 2021-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    相关资源
    最近更新 更多