127 lines
3.5 KiB
Python
127 lines
3.5 KiB
Python
import logging
|
|
import random
|
|
import tkinter as tk
|
|
from tkinter import ttk
|
|
|
|
import numpy as np
|
|
from matplotlib.animation import FuncAnimation
|
|
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg, NavigationToolbar2Tk
|
|
from matplotlib.figure import Figure
|
|
|
|
from core.gui.dialogs.dialog import Dialog
|
|
from core.gui.themes import PADY
|
|
|
|
|
|
class GraphDialog(Dialog):
|
|
def __init__(self, app, title, live=False):
|
|
super().__init__(app, title, modal=False)
|
|
self.fig = None
|
|
self.plot = None
|
|
self.canvas = None
|
|
self.toolbar = None
|
|
self.animation = None
|
|
self.live = live
|
|
|
|
def draw(self):
|
|
self.top.columnconfigure(0, weight=1)
|
|
self.top.rowconfigure(0, weight=1)
|
|
|
|
# create figure and plot
|
|
frame = ttk.Frame(self.top)
|
|
frame.grid(sticky="nsew", pady=PADY)
|
|
|
|
self.fig = Figure(figsize=(6, 5), dpi=100)
|
|
self.plot = self.fig.add_subplot(111)
|
|
|
|
# create and draw figure canvas
|
|
self.canvas = FigureCanvasTkAgg(self.fig, master=frame)
|
|
self.canvas.draw()
|
|
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
|
|
|
|
# create and draw toolbar
|
|
self.toolbar = NavigationToolbar2Tk(self.canvas, frame)
|
|
self.toolbar.update()
|
|
self.canvas.get_tk_widget().pack(side=tk.TOP, fill=tk.BOTH, expand=1)
|
|
|
|
# initialize graph artists
|
|
self.init_artists()
|
|
|
|
def run(self):
|
|
logging.info("live graph")
|
|
self.animation = FuncAnimation(
|
|
fig=self.fig, func=self.animate, interval=1000, repeat_delay=5000
|
|
)
|
|
|
|
def show(self):
|
|
self.draw()
|
|
if self.live:
|
|
self.run()
|
|
super().show()
|
|
|
|
def init_artists(self):
|
|
raise NotImplementedError
|
|
|
|
def animate(self, frame, *fargs):
|
|
raise NotImplementedError
|
|
|
|
|
|
class GraphLineDialog(GraphDialog):
|
|
def __init__(self, app, title, live=False):
|
|
super().__init__(app, title, live)
|
|
self.x_data = []
|
|
self.y_data = []
|
|
self.line = None
|
|
self.background = None
|
|
|
|
def init_artists(self):
|
|
self.plot.set_ylim(0, 10)
|
|
self.line, = self.plot.plot(self.x_data, self.y_data)
|
|
if self.live:
|
|
self.background = self.canvas.copy_from_bbox(self.plot.bbox)
|
|
|
|
def animate(self, frame, *fargs):
|
|
logging.info("blit graph counter: %s - %s", frame, fargs)
|
|
x = frame
|
|
y = random.randint(1, 10)
|
|
self.x_data.append(x)
|
|
self.y_data.append(y)
|
|
self.line.set_data(self.x_data, self.y_data)
|
|
|
|
# restore background
|
|
self.plot.relim()
|
|
self.plot.axes.autoscale_view(True, True, True)
|
|
self.canvas.restore_region(self.background)
|
|
self.plot.draw_artist(self.line)
|
|
self.canvas.blit(self.plot.bbox)
|
|
|
|
|
|
class GraphBarDialog(GraphDialog):
|
|
def __init__(self, app, title):
|
|
super().__init__(app, title)
|
|
|
|
def init_artists(self):
|
|
data = (20, 35, 30, 35, 27)
|
|
ind = np.arange(5)
|
|
width = 0.5
|
|
return self.plot.bar(ind, data, width)
|
|
|
|
def animate(self, frame, *fargs):
|
|
pass
|
|
|
|
def animate_blit(self, frame, *fargs):
|
|
pass
|
|
|
|
|
|
class GraphScatterDialog(GraphDialog):
|
|
def __init__(self, app, title):
|
|
super().__init__(app, title)
|
|
|
|
def init_artists(self):
|
|
t = np.arange(0, 3, 0.01)
|
|
return self.plot.scatter(t, 2 * np.sin(2 * np.pi * t))
|
|
|
|
def animate(self, frame, *fargs):
|
|
pass
|
|
|
|
def animate_blit(self, frame, *fargs):
|
|
pass
|