@@ -305,6 +305,181 @@ def set_value(self, value):
305305
306306 self ._redraw ()
307307
308+ # Gauge2 : modifications from Gauge
309+ # ************************
310+ # 3 numeric values added : min, center, max,
311+ # and meter a bit flatter to accept center value
312+ # small correction of the rate for green yellow red zones
313+ # now 80% gives 2 red among 10 divisions
314+ # now yellow and red zone size can change
315+ # yellow and red zone also for too small values
316+ # readout still active with RED BG if values OFF limits
317+ # suppressed (commented) : create second half part
318+ # suppressed integer conversion on extend to not accumulate decimal loss errors
319+ # idem on value
320+ # math correction now min_value can be different from 0 or negative
321+
322+
323+ class Gauge2 (ttk .Frame ):
324+ """
325+ Shows a gauge, much like the RotaryGauge::
326+ gauge = tk_tools.Gauge(root, max_value=100.0,
327+ label='speed', unit='km/h')
328+ gauge.grid()
329+ gauge.set_value(10)
330+ :param parent: tkinter parent frame
331+ :param width: canvas width
332+ :param height: canvas height
333+ :param min_value: the minimum value
334+ :param max_value: the maximum value
335+ :param label: the label on the scale
336+ :param unit: the unit to show on the scale
337+ :param divisions: the number of divisions on the scale
338+ :parm yellow: the beginning of the yellow (warning) zone in percent
339+ :parm red: the beginning of the red (danger) zone in percent
340+ :parm yellow_low: in percent warning for low values
341+ :parm red_low: in percent if very low values are a danger
342+ :param bg: background
343+ """
344+ def __init__ (self , parent , width = 200 , height = 100 ,
345+ min_value = 0.0 , max_value = 100.0 , label = '' , unit = '' ,
346+ divisions = 8 , yellow = 50 , red = 80 , yellow_low = 0 ,
347+ red_low = 0 , bg = 'lightgrey' ):
348+ self ._parent = parent
349+ self ._width = width
350+ self ._height = height
351+ self ._label = label
352+ self ._unit = unit
353+ self ._divisions = divisions
354+ self ._min_value = EngNumber (min_value )
355+ self ._max_value = EngNumber (max_value )
356+ self ._average_value = EngNumber ((max_value + min_value ) / 2 )
357+ self ._yellow = yellow * 0.01
358+ self ._red = red * 0.01
359+ self ._yellow_low = yellow_low * 0.01
360+ self ._red_low = red_low * 0.01
361+
362+ super ().__init__ (self ._parent )
363+
364+ self ._canvas = tk .Canvas (self , width = self ._width ,
365+ height = self ._height , bg = bg )
366+ self ._canvas .grid (row = 0 , column = 0 , sticky = 'news' )
367+ self ._min_value = EngNumber (min_value )
368+ self ._max_value = EngNumber (max_value )
369+ self ._value = self ._min_value
370+ self ._redraw ()
371+ # ----------------------------------------------------------------------
372+
373+ def _redraw (self ):
374+ self ._canvas .delete ('all' )
375+ max_angle = 120.0
376+ value_as_percent = ((self ._value - self ._min_value ) /
377+ (self ._max_value - self ._min_value ))
378+ value = float (max_angle * value_as_percent )
379+ # no int() => accuracy
380+ # create the tick marks and colors across the top
381+ for i in range (self ._divisions ):
382+ extent = (max_angle / self ._divisions )
383+ start = (150.0 - i * extent )
384+ rate = (i + 1 )/ (self ._divisions + 1 )
385+ if rate < self ._red_low :
386+ bg_color = 'red'
387+ elif rate <= self ._yellow_low :
388+ bg_color = 'yellow'
389+ elif rate <= self ._yellow :
390+ bg_color = 'green'
391+ elif rate <= self ._red :
392+ bg_color = 'yellow'
393+ else :
394+ bg_color = 'red'
395+
396+ self ._canvas .create_arc (
397+ 0 , int (self ._height * 0.15 ),
398+ self ._width , int (self ._height * 1.8 ),
399+ start = start , extent = - extent , width = 2 ,
400+ fill = bg_color , style = 'pie'
401+ )
402+ bg_color = 'white'
403+ red = '#c21807'
404+ ratio = 0.06
405+ self ._canvas .create_arc (self ._width * ratio ,
406+ int (self ._height * 0.25 ),
407+ self ._width * (1.0 - ratio ),
408+ int (self ._height * 1.8 * (1.0 - ratio * 1.1 )),
409+ start = 150 , extent = - 120 , width = 2 ,
410+ fill = bg_color , style = 'pie' )
411+ # readout & title
412+ self .readout (self ._value , 'black' ) # BG black if OK
413+
414+ # display lowest value
415+ value_text = '{}' .format (self ._min_value )
416+ self ._canvas .create_text (
417+ self ._width * 0.1 , self ._height * 0.7 ,
418+ font = ('Courier New' , 10 ), text = value_text )
419+ # display greatest value
420+ value_text = '{}' .format (self ._max_value )
421+ self ._canvas .create_text (
422+ self ._width * 0.9 , self ._height * 0.7 ,
423+ font = ('Courier New' , 10 ), text = value_text )
424+ # display center value
425+ value_text = '{}' .format (self ._average_value )
426+ self ._canvas .create_text (
427+ self ._width * 0.5 , self ._height * 0.1 ,
428+ font = ('Courier New' , 10 ), text = value_text )
429+ # create first half (red needle)
430+ self ._canvas .create_arc (0 , int (self ._height * 0.15 ),
431+ self ._width , int (self ._height * 1.8 ),
432+ start = 150 , extent = - value , width = 3 ,
433+ outline = red )
434+
435+ # create second half
436+ '''self._canvas.create_arc(0, int(self._height * 0.15),
437+ self._width, int(self._height * 1.8),
438+ start=30, extent=120-value, width=3,
439+ outline=red)'''
440+ # create inset red
441+ self ._canvas .create_arc (self ._width * 0.35 , int (self ._height * 0.7 ),
442+ self ._width * 0.65 , int (self ._height * 1.2 ),
443+ start = 150 , extent = - 120 , width = 1 ,
444+ outline = 'grey' , fill = red , style = 'pie' )
445+
446+ # create the overlapping black border
447+ self ._canvas .create_arc (0 , int (self ._height * 0.15 ),
448+ self ._width , int (self ._height * 1.8 ),
449+ start = 150 , extent = - 120 , width = 3 ,
450+ outline = '#343434' )
451+ # ----------------------------------------------------------------------
452+
453+ def readout (self , value , bg ): # value, BG color
454+ # draw the black behind the readout
455+ r_width = 95
456+ r_height = 20
457+ r_offset = 8
458+ self ._canvas .create_rectangle (
459+ self ._width / 2.0 - r_width / 2.0 ,
460+ self ._height / 2.0 - r_height / 2.0 + r_offset ,
461+ self ._width / 2.0 + r_width / 2.0 ,
462+ self ._height / 2.0 + r_height / 2.0 + r_offset ,
463+ fill = bg , outline = 'grey'
464+ )
465+ # the digital readout
466+ self ._canvas .create_text (
467+ self ._width * 0.5 , self ._height * 0.5 - r_offset ,
468+ font = ('Courier New' , 10 ), text = self ._label )
469+
470+ value_text = '{}{}' .format (self ._value , self ._unit )
471+ self ._canvas .create_text (
472+ self ._width * 0.5 , self ._height * 0.5 + r_offset ,
473+ font = ('Courier New' , 10 ), text = value_text , fill = 'white' )
474+ # ----------------------------------------------------------------------
475+
476+ def set_value (self , value ):
477+ self ._value = EngNumber (value )
478+ if self ._min_value * 1.02 < value < self ._max_value * 0.98 :
479+ self ._redraw () # refresh all
480+ else : # OFF limits refresh only readout
481+ self .readout (self ._value , 'red' ) # on RED BackGround
482+
308483
309484class Graph (ttk .Frame ):
310485 """
0 commit comments