Skip to content

Commit

Permalink
Merge pull request #38 from naejgz/master
Browse files Browse the repository at this point in the history
Adding Gauge2
  • Loading branch information
slightlynybbled committed Jun 11, 2018
2 parents e6af77e + 258d0a6 commit b7db195
Show file tree
Hide file tree
Showing 7 changed files with 276 additions and 20 deletions.
5 changes: 5 additions & 0 deletions .directory
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[Dolphin]
SortRole=modificationtime
Timestamp=2018,6,9,11,51,23
Version=4
ViewMode=1
Binary file added docs/img/gauge2doc.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/img/gauges2.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
71 changes: 71 additions & 0 deletions examples/gauge2.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import tkinter as tk
import tk_tools


root = tk.Tk()

max_speed = 20000

speed_gauge = tk_tools.Gauge2(root,
max_value=max_speed,
label='speed', unit=' m/h',bg='grey')
speed_gauge.grid(row=0, column=0, sticky='news')


tach_gauge = tk_tools.Gauge2(root,
max_value=8000,
label='tach', unit=' RPM',
divisions=10)
tach_gauge.grid(row=1, column=0, sticky='news')

strange_gauge = tk_tools.Gauge2(root,
max_value=30000,
label='strange', unit=' blah',
divisions=10, red=90, yellow=60)
strange_gauge.grid(row=2, column=0, sticky='news')

batV_gauge = tk_tools.Gauge2(root, height=120, width=250,
max_value=16, min_value=8,
label='Bat voltage', unit='V',
divisions=8, yellow=60, red=75,
red_low=30, yellow_low=40)
batV_gauge.grid(row=0, column=1, sticky='news')

batI_gauge = tk_tools.Gauge2(root, height=120, width=250,
max_value=6, min_value=-8,
label='Bat current', unit='A',
divisions=14, yellow=80, red=90,
red_low=20, yellow_low=30,bg='lavender')
batI_gauge.grid(row=1, column=1, sticky='news')

count = 0
up = True


def update_gauge():
global count, up

increment = 30

if up:
count += increment
if count > max_speed:
up = False
else:
count -= increment

if count <= 0.0:
up = True

speed_gauge.set_value(count)
tach_gauge.set_value(count)
strange_gauge.set_value(count)
batV_gauge.set_value(count/1000)
batI_gauge.set_value((count-10000)/1000)

root.after(50, update_gauge)


root.after(100, update_gauge)

root.mainloop()
5 changes: 5 additions & 0 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,11 @@ Here are some examples screenshots of the widgets you can create:

![Gauges](docs/img/gauges.png)

#### Gauge2

![Gauges2](docs/img/gauges2.png)
![Gauges2doc](docs/img/gauge2doc.png)

#### Rotary-Scale: (Tachymeter)

![Rotary-Scale](docs/img/rotary-scale.png)
Expand Down
40 changes: 20 additions & 20 deletions tk_tools/__init__.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
from tk_tools.canvas import RotaryScale, Gauge, Graph, Led
from tk_tools.groups import EntryGrid, LabelGrid, \
KeyValueEntry, SpreadSheetReader, ButtonGrid, \
Calendar, MultiSlotFrame, SevenSegment, SevenSegmentDigits
from tk_tools.widgets import SmartOptionMenu, SmartSpinBox, \
SmartCheckbutton, BinaryLabel, ByteLabel
from tk_tools.tooltips import ToolTip

from tk_tools.version import __version__


__all__ = [
'RotaryScale', 'Gauge', 'Graph', 'Led',
'EntryGrid', 'LabelGrid', 'ButtonGrid', 'KeyValueEntry',
'SpreadSheetReader', 'SmartOptionMenu', 'SmartSpinBox',
'SmartCheckbutton', 'Calendar', 'MultiSlotFrame',
'SevenSegment', 'SevenSegmentDigits',
'BinaryLabel', 'ByteLabel', 'ToolTip',
'__version__'
]
from tk_tools.canvas import RotaryScale, Gauge, Graph, Led, Gauge2
from tk_tools.groups import EntryGrid, LabelGrid, \
KeyValueEntry, SpreadSheetReader, ButtonGrid, \
Calendar, MultiSlotFrame, SevenSegment, SevenSegmentDigits
from tk_tools.widgets import SmartOptionMenu, SmartSpinBox, \
SmartCheckbutton, BinaryLabel, ByteLabel
from tk_tools.tooltips import ToolTip

from tk_tools.version import __version__


__all__ = [
'RotaryScale', 'Gauge', 'Graph', 'Led', 'Gauge2',
'EntryGrid', 'LabelGrid', 'ButtonGrid', 'KeyValueEntry',
'SpreadSheetReader', 'SmartOptionMenu', 'SmartSpinBox',
'SmartCheckbutton', 'Calendar', 'MultiSlotFrame',
'SevenSegment', 'SevenSegmentDigits',
'BinaryLabel', 'ByteLabel', 'ToolTip',
'__version__'
]
175 changes: 175 additions & 0 deletions tk_tools/canvas.py
Original file line number Diff line number Diff line change
Expand Up @@ -305,6 +305,181 @@ def set_value(self, value):

self._redraw()

# Gauge2 : modifications from Gauge
# ************************
# 3 numeric values added : min, center, max,
# and meter a bit flatter to accept center value
# small correction of the rate for green yellow red zones
# now 80% gives 2 red among 10 divisions
# now yellow and red zone size can change
# yellow and red zone also for too small values
# readout still active with RED BG if values OFF limits
# suppressed (commented) : create second half part
# suppressed integer conversion on extend to not accumulate decimal loss errors
# idem on value
# math correction now min_value can be different from 0 or negative


class Gauge2(ttk.Frame):
"""
Shows a gauge, much like the RotaryGauge::
gauge = tk_tools.Gauge(root, max_value=100.0,
label='speed', unit='km/h')
gauge.grid()
gauge.set_value(10)
:param parent: tkinter parent frame
:param width: canvas width
:param height: canvas height
:param min_value: the minimum value
:param max_value: the maximum value
:param label: the label on the scale
:param unit: the unit to show on the scale
:param divisions: the number of divisions on the scale
:parm yellow: the beginning of the yellow (warning) zone in percent
:parm red: the beginning of the red (danger) zone in percent
:parm yellow_low: in percent warning for low values
:parm red_low: in percent if very low values are a danger
:param bg: background
"""
def __init__(self, parent, width=200, height=100,
min_value=0.0, max_value=100.0, label='', unit='',
divisions=8, yellow=50, red=80, yellow_low=0,
red_low=0, bg='lightgrey'):
self._parent = parent
self._width = width
self._height = height
self._label = label
self._unit = unit
self._divisions = divisions
self._min_value = EngNumber(min_value)
self._max_value = EngNumber(max_value)
self._average_value = EngNumber((max_value + min_value) / 2)
self._yellow = yellow * 0.01
self._red = red * 0.01
self._yellow_low = yellow_low * 0.01
self._red_low = red_low * 0.01

super().__init__(self._parent)

self._canvas = tk.Canvas(self, width=self._width,
height=self._height, bg=bg)
self._canvas.grid(row=0, column=0, sticky='news')
self._min_value = EngNumber(min_value)
self._max_value = EngNumber(max_value)
self._value = self._min_value
self._redraw()
# ----------------------------------------------------------------------

def _redraw(self):
self._canvas.delete('all')
max_angle = 120.0
value_as_percent = ((self._value - self._min_value) /
(self._max_value - self._min_value))
value = float(max_angle * value_as_percent)
# no int() => accuracy
# create the tick marks and colors across the top
for i in range(self._divisions):
extent = (max_angle / self._divisions)
start = (150.0 - i * extent)
rate = (i+1)/(self._divisions+1)
if rate < self._red_low:
bg_color = 'red'
elif rate <= self._yellow_low:
bg_color = 'yellow'
elif rate <= self._yellow:
bg_color = 'green'
elif rate <= self._red:
bg_color = 'yellow'
else:
bg_color = 'red'

self._canvas.create_arc(
0, int(self._height * 0.15),
self._width, int(self._height * 1.8),
start=start, extent=-extent, width=2,
fill=bg_color, style='pie'
)
bg_color = 'white'
red = '#c21807'
ratio = 0.06
self._canvas.create_arc(self._width * ratio,
int(self._height * 0.25),
self._width * (1.0 - ratio),
int(self._height * 1.8 * (1.0 - ratio * 1.1)),
start=150, extent=-120, width=2,
fill=bg_color, style='pie')
# readout & title
self.readout(self._value, 'black') # BG black if OK

# display lowest value
value_text = '{}'.format(self._min_value)
self._canvas.create_text(
self._width * 0.1, self._height * 0.7,
font=('Courier New', 10), text=value_text)
# display greatest value
value_text = '{}'.format(self._max_value)
self._canvas.create_text(
self._width * 0.9, self._height * 0.7,
font=('Courier New', 10), text=value_text)
# display center value
value_text = '{}'.format(self._average_value)
self._canvas.create_text(
self._width * 0.5, self._height * 0.1,
font=('Courier New', 10), text=value_text)
# create first half (red needle)
self._canvas.create_arc(0, int(self._height * 0.15),
self._width, int(self._height * 1.8),
start=150, extent=-value, width=3,
outline=red)

# create second half
'''self._canvas.create_arc(0, int(self._height * 0.15),
self._width, int(self._height * 1.8),
start=30, extent=120-value, width=3,
outline=red)'''
# create inset red
self._canvas.create_arc(self._width * 0.35, int(self._height * 0.7),
self._width * 0.65, int(self._height * 1.2),
start=150, extent=-120, width=1,
outline='grey', fill=red, style='pie')

# create the overlapping black border
self._canvas.create_arc(0, int(self._height * 0.15),
self._width, int(self._height * 1.8),
start=150, extent=-120, width=3,
outline='#343434')
# ----------------------------------------------------------------------

def readout(self, value, bg): # value, BG color
# draw the black behind the readout
r_width = 95
r_height = 20
r_offset = 8
self._canvas.create_rectangle(
self._width/2.0 - r_width / 2.0,
self._height/2.0 - r_height/2.0 + r_offset,
self._width/2.0 + r_width / 2.0,
self._height/2.0 + r_height/2.0 + r_offset,
fill=bg, outline='grey'
)
# the digital readout
self._canvas.create_text(
self._width * 0.5, self._height * 0.5 - r_offset,
font=('Courier New', 10), text=self._label)

value_text = '{}{}'.format(self._value, self._unit)
self._canvas.create_text(
self._width * 0.5, self._height * 0.5 + r_offset,
font=('Courier New', 10), text=value_text, fill='white')
# ----------------------------------------------------------------------

def set_value(self, value):
self._value = EngNumber(value)
if self._min_value * 1.02 < value < self._max_value * 0.98:
self._redraw() # refresh all
else: # OFF limits refresh only readout
self.readout(self._value, 'red') # on RED BackGround


class Graph(ttk.Frame):
"""
Expand Down

0 comments on commit b7db195

Please sign in to comment.