Version 3 of A simple voltmeter

Updated 2005-04-19 20:26:53 by dkf

From a news:comp.lang.tcl posting by Bob Techentin:

I'm looking more for an analog style meter. Kinda like those old volt meter.

Well, if you just want to display, why not write one into a canvas? It's pretty easy, and fun too. Try this:

    # example volt-meter like display
    package require Tk

    grid [canvas .c -width 200 -height 110 -borderwidth 2 -relief sunken]
    grid [scale .s -orient h -from 0 -to 100 -variable v]

    .c create line 100 100 10 100 -tag meter

    trace variable v w updateMeter

    proc updateMeter {name1 name2 op} {
        upvar #0 $name1 v
        set min [.s cget -from]
        set max [.s cget -to]
        set pos [expr {$v / abs($max - $min)}]
        set x [expr {100.0 - 90.0*(cos($pos*3.14))}]
        set y [expr {100.0 - 90.0*(sin($pos*3.14))}]
        .c coords meter 100 100 $x $y
    }

DKF: Here is a slightly more complex version which shows a little bit of history and fades nicely. Isn't Tk wonderful?

 package require Tk
 set ::pi 3.1415927 ;# Good enough accuracy for gfx...

 # Create a meter 'enabled' canvas
 proc makeMeter {w} {
     global meter angle
     canvas $w -width 200 -height 110 -borderwidth 2 -relief sunken -bg white
     for {set i 70;set j 0} {$i<100} {incr i 2;incr j} {
         set meter($j) [$w create line 100 100 10 100 \
                 -fill grey$i -width 3 -arrow last]
         set angle($j) 0
         $w lower $meter($j)
         updateMeterLine $w 0.2 $j
     }
     $w create arc 10 10 190 190 -extent 108 -start 36 -style arc -outline red
     return $w
 }

 # Draw a meter line (and recurse for lighter ones...)
 proc updateMeterLine {w a {l 0}} {
     global meter angle pi
     set oldangle $angle($l)
     set angle($l) $a
     set x [expr {100.0 - 90.0*cos($a * $pi)}]
     set y [expr {100.0 - 90.0*sin($a * $pi)}]
     $w coords $meter($l) 100 100 $x $y
     incr l
     if {[info exist meter($l)]} {updateMeterLine $w $oldangle $l}
 }

 # Convert variable to angle on trace
 proc updateMeter {name1 name2 op} {
     upvar #0 $name1 v
     set min [.s cget -from]
     set max [.s cget -to]
     set pos [expr {($v - $min) / ($max - $min)}]
     updateMeterLine .c [expr {$pos*0.6+0.2}]
 }

 grid [makeMeter .c]
 grid [scale .s -orient h -from 0 -to 100 -variable v]
 trace variable v w updateMeter

 # Fade over time
 proc updateMeterTimer {} {
     set ::v $::v
     after 20 updateMeterTimer
 }
 updateMeterTimer



vu has a dial widget.


Category Widget