2016-11-23 2 views
0

Ich arbeite an einem Programm, wo ich zwei verschiedene Grafiken benötigt, um animiert zu werden. Ich habe Schwierigkeiten, mit der Struktur, die ich benutze, zu verfahren. Ich werde meinen Code unten einfügen, damit Sie es ausprobieren können. Ich habe es so weit wie möglich abgespeckt und gleichzeitig die Kernfunktionalität beibehalten, so dass es hoffentlich nicht zu schwer zu verstehen ist. In ihrem momentanen Zustand machen die Animationslinien nichts, also lass mich wissen, wo ich falsch gelaufen bin.Tkinter/Matplotlib Animation Hilfe

from Tkinter import *    #Used for GUI elements 
import time       #Used for timing elements 
import matplotlib     #Used for graphing 
matplotlib.use("TkAgg") 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 
import matplotlib.animation as animation 
import numpy as np     #Used for arrays to find min/max of float array 
import random      #Only used for fake data input 


class tkgui: 
    def __init__(self, parent): 
     #--------------The following are variables that need to be accessed by other functions---------------------- 
     #Raw input values 
     self.x = 209500 
     self.y = 0 
     self.timeElapsed = 0 

     #State values 
     self.curFrame = 1 

     #List Values 
     self.timeList = np.array([]) 
     self.yList = np.array([]) 
     self.xList = np.array([]) 

     self.lastX = 0 
     #---------------------------------------------------------------------------------------------------------- 

     #Make Tkinter fullscreen 
     w, h = 320,240 #int(str(root.winfo_screenwidth())), int(str(root.winfo_screenheight())) #320, 240 is the RPiTFT 

     #The base layer of the GUI 
     topLevelContainer = Frame(parent) 
     topLevelContainer.pack() 

     #The two 'screens' to switch between. They contain everything on the GUI 
     self.buttonsFrame = Frame(topLevelContainer) 
     self.graphFrame = Frame(topLevelContainer) 

     #Stack the frames so that they are switchable 
     for frame in self.buttonsFrame, self.graphFrame: 
      frame.grid(row=0, column=0, sticky='news', padx=5, pady=(10, 10)) 

     buttonsFrameButtons = Frame(self.buttonsFrame) 
     buttonsFrameButtons.pack(side=LEFT, padx=(0, 50)) 

     #X button 
     self.xButton = Button(buttonsFrameButtons, command=self.xButtonClick) 
     self.xButton.configure(text="X", background="#C8C8C8", width=6, padx=35, pady=35) 
     self.xButton.pack(side=TOP, pady=10) 

     #Y button 
     self.yButton = Button(buttonsFrameButtons, command=self.yButtonClick) 
     self.yButton.configure(text="Y", background="#C8C8C8", width=6, padx=35, pady=35) 
     self.yButton.pack(side=TOP, pady=10) 

     #Bar graph 
     buttonsFrameBar = Frame(self.buttonsFrame) 
     buttonsFrameBar.pack(side=LEFT) 

     self.fBar = Figure(figsize=(2, 4), dpi=50) 
     aBar = self.fBar.add_subplot(111) 
     self.xBar = aBar.bar([0, 1], [0, 0], width=1) 

     lAxes = self.fBar.gca() 
     lAxes.axes.get_xaxis().set_ticklabels([]) 

     aBar.set_ylim([-30000, 30000]) 
     self.fBar.tight_layout() 

     self.buttonsFrame.tkraise()   

     #Setup the matplotlib graph 
     self.fGraph = Figure(figsize=(5, 3), dpi=50) 
     #Create the Y axis 
     aGraph = self.fGraph.add_subplot(111) 
     aGraph.set_xlabel("Time (s)") 
     aGraph.set_ylabel("Y") 
     self.yLine, = aGraph.plot([],[], "r-") 

     #Create the X axis 
     a2Graph = aGraph.twinx() 
     self.xLine, = a2Graph.plot([], []) 
     a2Graph.set_ylabel("X") 

     #Final matplotlib/Tkinter setup 
     self.canvasGraph = FigureCanvasTkAgg(self.fGraph, master=self.graphFrame) 
     self.canvasGraph.show() 
     self.canvasGraph.get_tk_widget().pack(side=LEFT, fill=BOTH, expand=1) 

     self.canvasBar = FigureCanvasTkAgg(self.fBar, master=buttonsFrameBar) 
     self.canvasBar.show() 
     self.canvasBar.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=1) 

     #Resize the plot to fit all of the labels in 
     self.fGraph.subplots_adjust(bottom=0.13, left=0.15, right=0.87)  

    def refreshGraph(self, frameno):  #Redraw the graph with the updated arrays and resize it accordingly 
     #Update data 
     self.yLine.set_data(self.timeList, self.yList) 
     self.xLine.set_data(self.timeList, self.xList) 

     #Update y axis 
     ax = self.canvasGraph.figure.axes[0] 
     ax.set_xlim(self.timeList.min(), self.timeList.max()) 
     ax.set_ylim(self.yList.min(), self.yList.max()) 

     #Update x axis 
     ax2 = self.canvasGraph.figure.axes[1] 
     ax2.set_xlim(self.timeList.min(), self.timeList.max()) 
     ax2.set_ylim(self.xList.min(), self.xList.max()) 

     #Redraw 
     self.canvasGraph.draw() 


    def refreshBar(self, frameno): 
     curX = self.x 
     dif = curX - self.lastX 
     i = [dif] 
     for rect, h in zip(self.xBar, i): 
      rect.set_height(h) 
      if dif > 0: 
       rect.set_color('b') 
      else: 
       rect.set_color('r') 

     self.canvasBar.draw() 
     self.lastX=curX 

    def switchFrame(self):  #Switch the current screen. Either x/y buttons or graph 
     if self.curFrame: 
      self.graphFrame.tkraise() 
      self.curFrame = 0 
     else: 
      self.buttonsFrame.tkraise() 
      self.curFrame = 1 

    def xButtonClick(self): 
     self.switchFrame() 

    def yButtonClick(self): 
     self.close() 

    def close(e):    #Exit the program 
     sys.exit() 

#Initialisation of global variables 
lastTime = 0  #Used for the 'last time' iterated 
yState = 0  

def updateNumbers():  #Used to generate fake input variables. Will be replaced by ADC values 
    global lastTime 
    global yState 

    curTime = time.time()           #Update the time each time the function is called 
    if curTime - lastTime > 0.5:         #Only update numbers every 0.5 seconds 
     gui.x = random.randrange(200000, 230000)     #Generates x 
     if yState: 
      gui.y = gui.y - 20        #Decrease y 
      if gui.y < 1: 
       yState = 0          #Until it gets to a minimum of 0 
     else: 
      gui.y = gui.y + 20        #Increase y 
      if gui.y > 1300: 
       yState = 1          #Until it reaches a maximum of 1300 
     gui.yList = np.append(gui.yList, gui.y)   #Add the new y values to the array 
     gui.xList = np.append(gui.xList, gui.x/10000.0)   #Add the new x values to the array 
     lastTime = time.time()          #Record the last time iterated for timing purposes 
     gui.timeElapsed += 0.5          
     gui.timeList = np.append(gui.timeList, gui.timeElapsed)  #Add the latest time to the array 
##  gui.refreshGraph()           #Call the function that will redraw the graph with the new figures 

if __name__ == "__main__": 
    root = Tk()   #Root Tkinter setup 
    gui = tkgui(root) #Setup the gui class 

    updateNumbers() 
    aniGraph = animation.FuncAnimation(gui.fGraph,gui.refreshGraph,interval=500,frames=100,repeat=True) 
    aniBar = animation.FuncAnimation(gui.fBar,gui.refreshBar,interval=500,frames=100,repeat=True) 

    while(1):     #Main loop 
     updateNumbers()   #Update fake values 

     root.update()   #Update the gui loop 

    root.mainloop()    #Tkinter main loop 

Um klar zu sein, frage ich nur, wie man die Animation für diesen Code funktioniert.

+0

wenn Sie 'while (1):' 'dann root.mainloop () 'wird nie benutzt werden. Am Ende von 'updateNumber' können Sie' root.after (500, updateNumber) 'verwenden und nach 500ms (0.5s) wird' updateNumber' erneut ausgeführt, so dass Sie keine while (1) 'Schleife benötigen. – furas

+0

Beim Start sehe ich Balkenanimation und nachdem ich auf X geklickt habe, sehe ich Linienanimation - es funktioniert. Ich weiß nicht, welches Problem ist. – furas

+0

Es ist nicht in dieser Version des Codes gezeigt, aber ich brauche die konstante Schleife aus anderen Gründen. Ich hatte den Eindruck, dass root.update() innerhalb der while (1) dieses Problem behoben hat? Und hast du irgendwas geändert, denn wenn ich denselben Code laufe, sehe ich keine Animationen. –

Antwort

1

Ihr Code funktioniert für mich - ich sehe alle Animation - aber wenn Sie was ohne While(1): (oder mehr pythonic While True:) ausführen, dann können Sie root.after(milliseconds, function_name) verwenden. Sie können das Ereignis anstelle von FuncAnimation verwenden.

Und es können Sie die Funktion steuern - starten/stoppen Sie es.

if self.run_bar: 
    root.after(100, self.refreshBar) 

Sie verwenden es starten (oder neu starten)

self.run_bar = True 
self.refreshBar() 

und Sie können es

self.run_bar = False 

alle # <-- in Code anzeigen stoppen.

from Tkinter import *    #Used for GUI elements 
import time       #Used for timing elements 
import matplotlib     #Used for graphing 
matplotlib.use("TkAgg") 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 
import matplotlib.animation as animation 
import numpy as np     #Used for arrays to find min/max of float array 
import random      #Only used for fake data input 


class TkGUI: # <-- CamelCase names for classes 
      # <-- empty line for readabelity 
    def __init__(self, parent): 
     #--- The following are variables that need to be accessed by other functions---------------------- 
     #Raw input values 
     self.x = 209500 
     self.y = 0 
     self.timeElapsed = 0 

     #State values 
     self.curFrame = 1 

     #List Values 
     self.timeList = np.array([]) 
     self.yList = np.array([]) 
     self.xList = np.array([]) 

     self.lastX = 0 
     #----------------------------------------------------------- 

     #Make Tkinter fullscreen 
     w, h = 320,240 #int(str(root.winfo_screenwidth())), int(str(root.winfo_screenheight())) #320, 240 is the RPiTFT 

     #The base layer of the GUI 
     topLevelContainer = Frame(parent) 
     topLevelContainer.pack() 

     #The two 'screens' to switch between. They contain everything on the GUI 
     self.buttonsFrame = Frame(topLevelContainer) 
     self.graphFrame = Frame(topLevelContainer) 

     #Stack the frames so that they are switchable 
     for frame in self.buttonsFrame, self.graphFrame: 
      frame.grid(row=0, column=0, sticky='news', padx=5, pady=(10, 10)) 

     buttonsFrameButtons = Frame(self.buttonsFrame) 
     buttonsFrameButtons.pack(side=LEFT, padx=(0, 50)) 

     #X button 
     self.xButton = Button(buttonsFrameButtons, command=self.xButtonClick) 
     self.xButton.configure(text="X", background="#C8C8C8", width=6, padx=35, pady=35) 
     self.xButton.pack(side=TOP, pady=10) 

     #Y button 
     self.yButton = Button(buttonsFrameButtons, command=self.yButtonClick) 
     self.yButton.configure(text="Y", background="#C8C8C8", width=6, padx=35, pady=35) 
     self.yButton.pack(side=TOP, pady=10) 

     #Bar graph 
     buttonsFrameBar = Frame(self.buttonsFrame) 
     buttonsFrameBar.pack(side=LEFT) 

     self.fBar = Figure(figsize=(2, 4), dpi=50) 
     aBar = self.fBar.add_subplot(111) 
     self.xBar = aBar.bar([0, 1], [0, 0], width=1) 

     lAxes = self.fBar.gca() 
     lAxes.axes.get_xaxis().set_ticklabels([]) 

     aBar.set_ylim([-30000, 30000]) 
     self.fBar.tight_layout() 

     self.buttonsFrame.tkraise()   

     #Setup the matplotlib graph 
     self.fGraph = Figure(figsize=(5, 3), dpi=50) 
     #Create the Y axis 
     aGraph = self.fGraph.add_subplot(111) 
     aGraph.set_xlabel("Time (s)") 
     aGraph.set_ylabel("Y") 
     self.yLine, = aGraph.plot([],[], "r-") 

     #Create the X axis 
     a2Graph = aGraph.twinx() 
     self.xLine, = a2Graph.plot([], []) 
     a2Graph.set_ylabel("X") 

     #Final matplotlib/Tkinter setup 
     self.canvasGraph = FigureCanvasTkAgg(self.fGraph, master=self.graphFrame) 
     self.canvasGraph.show() 
     self.canvasGraph.get_tk_widget().pack(side=LEFT, fill=BOTH, expand=1) 

     self.canvasBar = FigureCanvasTkAgg(self.fBar, master=buttonsFrameBar) 
     self.canvasBar.show() 
     self.canvasBar.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=1) 

     #Resize the plot to fit all of the labels in 
     self.fGraph.subplots_adjust(bottom=0.13, left=0.15, right=0.87)  

    def refreshGraph(self): # <-- without argument 
     '''Redraw the graph with the updated arrays and resize it accordingly''' # <-- docstring used by documentation generator and IDE as help 

     #Update data 
     self.yLine.set_data(self.timeList, self.yList) 
     self.xLine.set_data(self.timeList, self.xList) 

     #Update y axis 
     ax = self.canvasGraph.figure.axes[0] 
     ax.set_xlim(self.timeList.min(), self.timeList.max()) 
     ax.set_ylim(self.yList.min(), self.yList.max()) 

     #Update x axis 
     ax2 = self.canvasGraph.figure.axes[1] 
     ax2.set_xlim(self.timeList.min(), self.timeList.max()) 
     ax2.set_ylim(self.xList.min(), self.xList.max()) 

     #Redraw 
     self.canvasGraph.draw() 

     # run again after 100ms (0.1s) 
     root.after(100, self.refreshGraph) # <-- run again like in loop 

    def refreshBar(self): # <-- without argument 
     curX = self.x 
     dif = curX - self.lastX 
     i = [dif] 
     for rect, h in zip(self.xBar, i): 
      rect.set_height(h) 
      if dif > 0: 
       rect.set_color('b') 
      else: 
       rect.set_color('r') 

     self.canvasBar.draw() 
     self.lastX=curX 
     # run again after 100ms (0.1s) 
     root.after(100, self.refreshBar) # <-- run again like in loop 

    def switchFrame(self):  #Switch the current screen. Either x/y buttons or graph 
     if self.curFrame: 
      self.graphFrame.tkraise() 
      self.curFrame = 0 
     else: 
      self.buttonsFrame.tkraise() 
      self.curFrame = 1 

    def xButtonClick(self): 
     self.switchFrame() 

    def yButtonClick(self): 
     self.close() 

    def close(e): # Exit the program 
     sys.exit() 

#Initialisation of global variables 
lastTime = 0  #Used for the 'last time' iterated 
yState = 0  

def updateNumbers():  #Used to generate fake input variables. Will be replaced by ADC values 
    global lastTime 
    global yState 

    curTime = time.time()           #Update the time each time the function is called 
    if curTime - lastTime > 0.5:         #Only update numbers every 0.5 seconds 
     gui.x = random.randrange(200000, 230000)     #Generates x 
     if yState: 
      gui.y = gui.y - 20        #Decrease y 
      if gui.y < 1: 
       yState = 0          #Until it gets to a minimum of 0 
     else: 
      gui.y = gui.y + 20        #Increase y 
      if gui.y > 1300: 
       yState = 1          #Until it reaches a maximum of 1300 
     gui.yList = np.append(gui.yList, gui.y)   #Add the new y values to the array 
     gui.xList = np.append(gui.xList, gui.x/10000.0)   #Add the new x values to the array 
     lastTime = time.time()          #Record the last time iterated for timing purposes 
     gui.timeElapsed += 0.5          
     gui.timeList = np.append(gui.timeList, gui.timeElapsed)  #Add the latest time to the array 

    # run again after 100ms (0.1s) 
    root.after(100, updateNumbers) # <-- run again like in loop  

if __name__ == "__main__": 
    root = Tk() 
    gui = TkGUI(root) 

    # <-- vvv - without While and without FuncAnimation - vvv 

    updateNumbers()  # run first time 

    gui.refreshBar() # run first time 
    gui.refreshGraph() # run first time 

    # <-- ^^^ - without While and without FuncAnimation - ^^^ 

    root.mainloop()  # Tkinter main loop 

EDIT: Natürlich können Sie FuncAnimation ohne after halten und after verwenden nur in updateNumbers

from Tkinter import *    #Used for GUI elements 
import time       #Used for timing elements 
import matplotlib     #Used for graphing 
matplotlib.use("TkAgg") 
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2TkAgg 
from matplotlib.figure import Figure 
import matplotlib.animation as animation 
import numpy as np     #Used for arrays to find min/max of float array 
import random      #Only used for fake data input 


class TkGUI: # <-- CamelCase names for classes 
      # <-- empty line for readabelity 
    def __init__(self, parent): 
     #--- The following are variables that need to be accessed by other functions---------------------- 
     #Raw input values 
     self.x = 209500 
     self.y = 0 
     self.timeElapsed = 0 

     #State values 
     self.curFrame = 1 

     #List Values 
     self.timeList = np.array([]) 
     self.yList = np.array([]) 
     self.xList = np.array([]) 

     self.lastX = 0 
     #----------------------------------------------------------- 

     #Make Tkinter fullscreen 
     w, h = 320,240 #int(str(root.winfo_screenwidth())), int(str(root.winfo_screenheight())) #320, 240 is the RPiTFT 

     #The base layer of the GUI 
     topLevelContainer = Frame(parent) 
     topLevelContainer.pack() 

     #The two 'screens' to switch between. They contain everything on the GUI 
     self.buttonsFrame = Frame(topLevelContainer) 
     self.graphFrame = Frame(topLevelContainer) 

     #Stack the frames so that they are switchable 
     for frame in self.buttonsFrame, self.graphFrame: 
      frame.grid(row=0, column=0, sticky='news', padx=5, pady=(10, 10)) 

     buttonsFrameButtons = Frame(self.buttonsFrame) 
     buttonsFrameButtons.pack(side=LEFT, padx=(0, 50)) 

     #X button 
     self.xButton = Button(buttonsFrameButtons, command=self.xButtonClick) 
     self.xButton.configure(text="X", background="#C8C8C8", width=6, padx=35, pady=35) 
     self.xButton.pack(side=TOP, pady=10) 

     #Y button 
     self.yButton = Button(buttonsFrameButtons, command=self.yButtonClick) 
     self.yButton.configure(text="Y", background="#C8C8C8", width=6, padx=35, pady=35) 
     self.yButton.pack(side=TOP, pady=10) 

     #Bar graph 
     buttonsFrameBar = Frame(self.buttonsFrame) 
     buttonsFrameBar.pack(side=LEFT) 

     self.fBar = Figure(figsize=(2, 4), dpi=50) 
     aBar = self.fBar.add_subplot(111) 
     self.xBar = aBar.bar([0, 1], [0, 0], width=1) 

     lAxes = self.fBar.gca() 
     lAxes.axes.get_xaxis().set_ticklabels([]) 

     aBar.set_ylim([-30000, 30000]) 
     self.fBar.tight_layout() 

     self.buttonsFrame.tkraise()   

     #Setup the matplotlib graph 
     self.fGraph = Figure(figsize=(5, 3), dpi=50) 
     #Create the Y axis 
     aGraph = self.fGraph.add_subplot(111) 
     aGraph.set_xlabel("Time (s)") 
     aGraph.set_ylabel("Y") 
     self.yLine, = aGraph.plot([],[], "r-") 

     #Create the X axis 
     a2Graph = aGraph.twinx() 
     self.xLine, = a2Graph.plot([], []) 
     a2Graph.set_ylabel("X") 

     #Final matplotlib/Tkinter setup 
     self.canvasGraph = FigureCanvasTkAgg(self.fGraph, master=self.graphFrame) 
     self.canvasGraph.show() 
     self.canvasGraph.get_tk_widget().pack(side=LEFT, fill=BOTH, expand=1) 

     self.canvasBar = FigureCanvasTkAgg(self.fBar, master=buttonsFrameBar) 
     self.canvasBar.show() 
     self.canvasBar.get_tk_widget().pack(side=BOTTOM, fill=BOTH, expand=1) 

     #Resize the plot to fit all of the labels in 
     self.fGraph.subplots_adjust(bottom=0.13, left=0.15, right=0.87)  

    def refreshGraph(self, i): 
     '''Redraw the graph with the updated arrays and resize it accordingly''' # <-- docstring used by documentation generator and IDE as help 

     #Update data 
     self.yLine.set_data(self.timeList, self.yList) 
     self.xLine.set_data(self.timeList, self.xList) 

     #Update y axis 
     ax = self.canvasGraph.figure.axes[0] 
     ax.set_xlim(self.timeList.min(), self.timeList.max()) 
     ax.set_ylim(self.yList.min(), self.yList.max()) 

     #Update x axis 
     ax2 = self.canvasGraph.figure.axes[1] 
     ax2.set_xlim(self.timeList.min(), self.timeList.max()) 
     ax2.set_ylim(self.xList.min(), self.xList.max()) 

     #Redraw 
     self.canvasGraph.draw() 

    def refreshBar(self, i): 
     curX = self.x 
     dif = curX - self.lastX 
     i = [dif] 
     for rect, h in zip(self.xBar, i): 
      rect.set_height(h) 
      if dif > 0: 
       rect.set_color('b') 
      else: 
       rect.set_color('r') 

     self.canvasBar.draw() 
     self.lastX=curX 

    def switchFrame(self): 
     '''Switch the current screen. Either x/y buttons or graph''' 

     if self.curFrame: 
      self.graphFrame.tkraise() 
      self.curFrame = 0 
     else: 
      self.buttonsFrame.tkraise() 
      self.curFrame = 1 

    def xButtonClick(self): 
     self.switchFrame() 

    def yButtonClick(self): 
     self.close() 

    def close(e): # Exit the program 
     sys.exit() 

#Initialisation of global variables 
lastTime = 0  #Used for the 'last time' iterated 
yState = 0  

def updateNumbers():  #Used to generate fake input variables. Will be replaced by ADC values 
    global lastTime 
    global yState 

    curTime = time.time()           #Update the time each time the function is called 
    if curTime - lastTime > 0.5:         #Only update numbers every 0.5 seconds 
     gui.x = random.randrange(200000, 230000)     #Generates x 
     if yState: 
      gui.y = gui.y - 20        #Decrease y 
      if gui.y < 1: 
       yState = 0          #Until it gets to a minimum of 0 
     else: 
      gui.y = gui.y + 20        #Increase y 
      if gui.y > 1300: 
       yState = 1          #Until it reaches a maximum of 1300 
     gui.yList = np.append(gui.yList, gui.y)   #Add the new y values to the array 
     gui.xList = np.append(gui.xList, gui.x/10000.0)   #Add the new x values to the array 
     lastTime = time.time()          #Record the last time iterated for timing purposes 
     gui.timeElapsed += 0.5          
     gui.timeList = np.append(gui.timeList, gui.timeElapsed)  #Add the latest time to the array 

    # run again after 100ms (0.1s) 
    root.after(100, updateNumbers) # <-- run again like in loop  

if __name__ == "__main__": 
    root = Tk() 
    gui = TkGUI(root) 

    aniGraph = animation.FuncAnimation(gui.fGraph,gui.refreshGraph,interval=500,frames=100,repeat=True) 
    aniBar = animation.FuncAnimation(gui.fBar,gui.refreshBar,interval=500,frames=100,repeat=True) 

    # <-- vvv - without While - vvv 

    updateNumbers()  # run first time 

    # <-- ^^^ - without While - ^^^ 

    root.mainloop()  # Tkinter main loop 
+0

Danke, das wird funktionieren. Ich habe mich jedoch gefragt, ob die Verwendung der Matplotlib-Animation besser ist als nur das Neuzeichnen. Ich sage das, weil in meinem Hauptcode, wenn ich anfange, große Datensätze und lange Graphen zu bekommen, oder wenn ich es schneller aktualisiere, würden Dinge anfangen, ein bisschen langsam zu laufen. –

+0

Ich überprüfe niemals die Geschwindigkeit beider Methoden, aber ich habe nichts in 'refreshBar' und' refreshGraph' geändert, also sollten beide Methoden genauso funktionieren, mit der gleichen Geschwindigkeit. Vielleicht, wenn Sie FuncAnimation Quellcode überprüfen, dann sehen Sie vielleicht 'after()' too :) 'matplotlib/FuncAnimation', um mit' tkinter' zu arbeiten, muss 'tkinter' Funktionen verwenden. – furas

+0

BTW: Sie können 'FuncAnimation' ohne' after' beibehalten und 'after' nur in' updateNumbers' verwenden - es funktioniert auch. – furas