O
O
oventarb2015-04-23 11:14:51
Python
oventarb, 2015-04-23 11:14:51

How to make an analogue of TChart (from Delphi) on tkinter?

How to make an analogue of TChart (from Delphi) on tkinter?

Answer the question

In order to leave comments, you need to log in

2 answer(s)
B
bobrovskyserg, 2015-04-23
@oventarb

No.
TChart is graphics rendered in VCL,
and tkinter is just GUI OS widget wrappers.
UPDATE

from collections import OrderedDict
import tkinter as tk
from time import sleep

class StripChart(tk.Frame):
    def __init__(self, parent, scale, historySize, trackColors, *args, **opts):
        # Initialize
        super().__init__(parent, *args, **opts)
        self._trackHist = OrderedDict()  # Map: TrackName -> list of canvas objID
        self._trackColor = trackColors  # Map: Track Name -> color

        self._chartHeight = scale + 1
        self._chartLength = historySize * 2  # Stretch for readability

        self._canvas = tk.Canvas(self, height=self._chartHeight + 17,
                                 width=self._chartLength, background='black')
        self._canvas.grid(sticky=tk.N + tk.S + tk.E + tk.W)

        # Draw horizontal to divide plot from tick labels
        x, y = 0, self._chartHeight + 2
        x2, y2 = self._chartLength, y
        self._baseLine = self._canvas.create_line(x, y, x2, y2, fill='white')

        # Init track def and histories lists
        self._trackColor.update({'tick': 'white', 'tickline': 'white',
                                 'ticklabel': 'white'})
        for trackName in self._trackColor.keys():
            self._trackHist[trackName] = [None for x in range(historySize)]

    def plotValues(self, **vals):
        for trackName, trackHistory in self._trackHist.items():
            # Scroll left-wards
            self._canvas.delete(trackHistory.pop(0))
            # Remove left-most canvas objs
            self._canvas.move(trackName, -2, 0)
            # Scroll canvas objs 2 pixels left

            # Plot the new values
            try:
                val = vals[trackName]
                x = self._chartLength
                y = self._chartHeight - val
                color = self._trackColor[trackName]

                objId = self._canvas.create_line(x, y, x + 1, y, fill=color,
                                                 width=3, tags=trackName)
                trackHistory.append(objId)
            except:
                trackHistory.append(None)

    def drawTick(self, text=None, **lineOpts):
        # draw vertical tick line
        x = self._chartLength
        y = 1
        x2 = x
        y2 = self._chartHeight
        color = self._trackColor['tickline']

        objId = self._canvas.create_line(x, y, x2, y2, fill=color,
                                         tags='tick', **lineOpts)
        self._trackHist['tickline'].append(objId)

        # draw tick label
        if text is not None:
            x = self._chartLength
            y = self._chartHeight + 10
            color = self._trackColor['ticklabel']

            objId = self._canvas.create_text(x, y, text=text,
                                             fill=color, tags='tick')
            self._trackHist['ticklabel'].append(objId)

    def configTrackColors(self, **trackColors):
        # Change plotted data color
        for trackName, colorName in trackColors.items():
            self._canvas.itemconfigure(trackName, fill=colorName)

        # Change settings so future data has the new color
        self._trackColor.update(trackColors)


if __name__ == '__main__':
    top = tk.Tk()
    graph = StripChart(top, 100, 300, {'A': 'blue', 'B': 'green', 'C': 'red'})
    graph.grid()

    val_A = val_B = val_C = 0
    delta = [-3, -2, -1, 0, 1, 2, 3]  # randomly vary the values by one of these
    tickCount = 0

    def nextVal(current, lowerBound, upperBound):
        from random import choice

        current += choice(delta)
        if current < lowerBound:
            return lowerBound
        elif current > upperBound:
            return upperBound
        else:
            return current

    def plotNextVals():
        global val_A, val_B, val_C, tickCount

        if tickCount % 50 == 0:
            graph.drawTick(text=str(tickCount), dash=(1, 4))
        tickCount += 1
        sleep(0.05)


        val_A = nextVal(val_A, 0, 99)
        val_B = nextVal(val_B, 0, 99)
        val_C = nextVal(val_C, 0, 99)
        graph.plotValues(A=val_A, B=val_B, C=val_C)

        # changeColor = { 800: 'black',
        # 1200: 'yellow',
        # 1600: 'orange',
        # 2000: 'white',
        # 2400: 'brown',
        # 2800: 'blue' }
        # if tickCount in changeColor:
        # graph.configTrackColors( A=changeColor[tickCount] )

        top.after(1, plotNextVals)

    top.after(1, plotNextVals)

    top.mainloop()

A
Alexander, 2015-04-23
@Avernial

If you need to build plots, you can embed matplotlib into your tk application. Example: embedding_in_tk

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question