Embedding multiple real-time graphs in one Python Tkinter GUI

Question:

I am new with Tkinter. I am trying to plot two real-time animated graphs in a window, but two realtime data overlaps onto the same graph after a while. I want them to be displayed on separate graphs. I put a gif to show my output.
I want to plot the other data to left graph. Is there any way to fix this? If I can make it I will try to plot three graphs instead of two. Can you help me with my code below?

from matplotlib.backends.backend_tkagg import (
    FigureCanvasTkAgg, NavigationToolbar2Tk)
import tkinter as Tk
from matplotlib.figure import Figure
import random
from itertools import count
import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
import numpy as np
from pandas import DataFrame

plt.style.use('fivethirtyeight')
# values for first graph
x_vals = []
y_vals = []
# values for second graph
x_vals2 = []
y_vals2 = []

index = count()
index2 = count()


def animate(i):
    x_vals.append(next(index))
    y_vals.append(random.randint(0, 5))
    plt.cla()  # clear the current axes
    plt.plot(x_vals, y_vals)


def animate2(j):
    x_vals2.append(next(index2))
    y_vals2.append(random.randint(0, 5))
    plt.cla()  # clear the current axes
    plt.plot(x_vals2, y_vals2)


# GUI

root = Tk.Tk()
label = Tk.Label(root, text="Realtime Animated Graphs").grid(column=0, row=0)

# graph 1
canvas = FigureCanvasTkAgg(plt.gcf(), master=root)
canvas.get_tk_widget().grid(column=0, row=1)
ani = FuncAnimation(plt.gcf(), animate, interval=1000, blit=False)

# graph 2
canvas2 = FigureCanvasTkAgg(plt.gcf(), master=root)
canvas2.get_tk_widget().grid(column=1, row=1)
ax2 = plt.gcf().add_subplot(111)
line2, = ax2.plot(x_vals2, y_vals2)
ani2 = FuncAnimation(plt.gcf(), animate2, interval=1000, blit=False)

Tk.mainloop()



Asked By: limewmint

||

Answers:

If You don’t specifically need canvas1 and 2, You can create two subplots for one figure / canvas.
Then You will get 2 axes: ax1 and ax2.

You can use just one FuncAnimation with same x.
If You need separate animations for ax1 and ax2, You can do that as well and just update either ax1 or ax2 in respective animation.

Here is code snippet:

import random
import tkinter as Tk
from itertools import count

import matplotlib.pyplot as plt
from matplotlib.animation import FuncAnimation
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

plt.style.use('fivethirtyeight')
# values for first graph
x_vals = []
y_vals = []
# values for second graph
y_vals2 = []

index = count()
index2 = count()

def animate(i):
    # Generate values
    x_vals.append(next(index))
    y_vals.append(random.randint(0, 5))
    y_vals2.append(random.randint(0, 5))
    # Get all axes of figure
    ax1, ax2 = plt.gcf().get_axes()
    # Clear current data
    ax1.cla()
    ax2.cla()
    # Plot new data
    ax1.plot(x_vals, y_vals)
    ax2.plot(x_vals, y_vals2)


# GUI
root = Tk.Tk()
label = Tk.Label(root, text="Realtime Animated Graphs").grid(column=0, row=0)

# graph 1
canvas = FigureCanvasTkAgg(plt.gcf(), master=root)
canvas.get_tk_widget().grid(column=0, row=1)
# Create two subplots in row 1 and column 1, 2
plt.gcf().subplots(1, 2)
ani = FuncAnimation(plt.gcf(), animate, interval=1000, blit=False)

Tk.mainloop()

This is the output:

figure animation

Answered By: Domarm
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.