Source code for crappy.blocks.dashboard

# coding: utf-8

import threading
from queue import Queue, Empty

from .block import Block
from .._global import OptionalModule

try:
  from tkinter import Tk, Label
except (ModuleNotFoundError, ImportError):
  Tk = OptionalModule("tkinter")
  Label = OptionalModule("tkinter")


[docs]class Dashboard_window: """Dashboard class created, is launched in a new thread.""" def __init__(self, labels: list, nb_digits: int, queue: Queue) -> None: self.root = Tk() self.root.title('Dashboard') self.root.resizable(width=False, height=False) self.nb_digits = nb_digits self.labels = labels self.c1 = {} self.c2 = {} self.queue = queue self.stop = False row = 0 # Creating the first and second column. Second column will be updated. for label in self.labels: self.c1[label] = Label(self.root, text=label, borderwidth=15, font=("Courier bold", 48)) self.c1[label].grid(row=row, column=0) self.c2[label] = (Label(self.root, text='', borderwidth=15, font=("Courier bold", 48))) self.c2[label].grid(row=row, column=1) row += 1 # Updating the second column until told to stop while not self.stop: self.update()
[docs] def update(self) -> None: """Method to update the output window.""" try: values = self.queue.get(timeout=0.1) except Empty: # Re-looping if nothing to display return # Stopping and closing the window if values == 'stop': self.stop = True self.root.destroy() return # Updating the display for label in self.labels: try: if isinstance(values[label], str): self.c2[label].configure(text=values[label]) else: self.c2[label].configure(text='%.{}f'.format(self.nb_digits) % values[label]) except KeyError: # If a wrong label is given it just won't be updated pass self.root.update()
[docs]class Dashboard(Block): """The Dashboard receives data from a :ref:`Link`, and prints it on a new popped window. It can only display data coming from one block. """
[docs] def __init__(self, labels: list, nb_digits: int = 2, verbose: bool = False, freq: float = 30) -> None: """Sets the args and initializes parent class. Args: labels (:obj:`list`): Values to plot on the output window. nb_digits (:obj:`int`, optional): Number of decimals to show. verbose (:obj:`bool`, optional): Display loop frequency ? freq (:obj:`float`, optional): If set, the block will loop at this frequency. """ super().__init__() self.verbose = verbose self.freq = freq self.labels = labels self.nb_digits = nb_digits # global queue self.queue = Queue()
[docs] def prepare(self) -> None: """Creates the window in a new thread.""" if len(self.inputs) == 0: raise IOError("No link pointing towards the Dashboard block !") elif len(self.inputs) > 1: raise IOError("Too many links pointing towards the Dashboard block !") self.dash_thread = threading.Thread(target=Dashboard_window, args=(self.labels, self.nb_digits, self.queue)) self.dash_thread.start()
[docs] def loop(self) -> None: """Simply transmits the received data to the thread.""" received_data = [link.recv_last() for link in self.inputs] if received_data[0] is not None: self.queue.put_nowait(received_data[0])
[docs] def finish(self) -> None: """Closes the thread.""" self.queue.put_nowait('stop') self.dash_thread.join(timeout=0.1)