# clock.tcl proc every {ms body} { eval $body after $ms [list every $ms $body] } pack [label .l -textvar time -font {Tahoma 24}] pack [button .b -text X -command exit] every 1000 {set ::time [clock format [clock sec] -format %H:%M:%S]} ---- [LV] It probably would be best for whoever added the above to add a name and a [EULA] type statement indicating the code is allowed to be reused. - [RS]: I put it here in order to test whether pages with .tcl titles are still delivered as plain text (they aren't), and trying to have my XDA execute it somehow - but it didn't work :( And re licensing: doesn't [Who owns the content of this Wiki] tell it clearly enough? Well, it certainly sets a general expectation. However, applications having the licensing spelled out explicitly ensures there is no confusion when the application is reaped from the wiki into a distribution. ---- [EKB] Here's a version that has a task timer as well as a clock. It lacks the elegant simplicity of the code above, but it adds some functionality that I was looking for. It's also set to be [always on top], at least on Windows. I've updated this with a new and improved version (July 25, 2005). I've actually ended up using it a ''lot'' for keeping track of my billed time. Here's what it looks like: [http://www.kb-creative.net/screenshots/Timer.gif] wm attributes . -topmost 1 wm resizable . 0 0 image create photo resetclock16 -data { R0lGODlhEAAQAIUAAAT+BHy+/HS6/Gy2/ITC/Pz+/Fyu/FSm/Pz6/PT6/Eye 9PzmhPzqnPzurOTy/OTu/ESW7PzmjPzqpAR2/PzyxPz2xPz2zNTm/ARy/Pzy zPz23Mzi/Lza/DyK3PzutPzyvPz67Pz63DyO5LTW/DSC3Pz21JzK/DSC1CR6 zPz+9IS+/FSq/PwWFPxmZIy+/LRypPwCBPT2/PyWlKwuVLRunOz2/HxKfMTe /IS6/Kx6rKzS/JTG/JyS1PQKFNQaLDSG1CH5BAEAAAAALAAAAAAQABAAAAa7 QIBQGAgIBIPBcAkgBArQqOHAJESRA0MBkVAMrYXjgsFoHA6OB4QYXkQYkgml YlFc1s/wu4yhZDQQGxwdTwJvEh4fExYgISAiIyQCBQNkDR4TGCUaICAdJieT A4gYmROdIAWfKAMFBpcUJZudKQUnKqxQKxV/jiAsLScuLzAABjEHGSWoKTIw MzQwxSs1DwoQnVAkNtIzQwoPGzciJ+U4OdLFQxAQOjomOyo8PT7STAAdPyQo KPYA0n6CAAAh/mhDcmVhdGVkIGJ5IEJNUFRvR0lGIFBybyB2ZXJzaW9uIDIu NQ0KqSBEZXZlbENvciAxOTk3LDE5OTguIEFsbCByaWdodHMgcmVzZXJ2ZWQu DQpodHRwOi8vd3d3LmRldmVsY29yLmNvbQA7 } image create photo appclock16 -data { R0lGODlhEAAQAIUAAPwCBHy+/HS6/Gy2/ITC/Pz+/Fyu/FSm/Pz6/ESW7Pzm hPzqnPzurOz2/OTu/PzmjPzqpAR2/PzyxPz2xPz2zEye9NTm/ARy/Pz21Mzi /Lza/DyK3PzutPzyvPzyzPz63Pz67DyO5KzS/Pz23KTO/DSC1DSC3JzK/CR6 zPz+9Iy+/FSq/IS6/BxyxPT2/Hy2/HSy/MTe/Gyu/CRyxJTG/IS+/DSG1AAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAEAAAAALAAAAAAQABAAAAaz QIBQGAgIBIPBcAkgBArQqOHAJESRA0MBgUgMrYWjYrFgHA4NhxfwFCgeC0hE MqFULN5nGF6+SDAYCRkaG21wEBwdER4fICAhIhsCBQNkDBwRFxgjjhskJZMD iBeZF44gBSYnKAMFBpd/m44pKSUqrFArE4yNqKkqLC0ABi4HHhinBSkFLS/C ACtpFQmOUCYlLDDPABUOGTEhJeIvLzIzTAkJIiInNDXO20wbNiYoKOdLfkEA If5oQ3JlYXRlZCBieSBCTVBUb0dJRiBQcm8gdmVyc2lvbiAyLjUNCqkgRGV2 ZWxDb3IgMTk5NywxOTk4LiBBbGwgcmlnaHRzIHJlc2VydmVkLg0KaHR0cDov L3d3dy5kZXZlbGNvci5jb20AOw== } proc every {ms body} { eval $body after $ms [list every $ms $body] } proc timeElapsed {sec} { set hours [expr {$sec / 3600}] set mins [expr {($sec / 60) % 60}] return [format "%02d:%02d" $hours $mins] } # Are we timing, or not? set timerstate 0 # Has the timer been reset? set reset 1 # Store previous time elapsed set prevtime 0 proc toggleTimer {b} { if {$::timerstate} { $b config -relief flat set ::timerstate 0 set ::prevtime [expr {$::prevtime + [clock sec] - $::t0}] } else { $b config -relief sunken if {$::reset} { set ::reset 0 } set ::t0 [clock sec] set ::timerstate 1 } } proc resetTimer {b} { set ::reset 1 set ::telapsed "00:00" set ::t0 [clock sec] set ::prevtime 0 } ## -- Top frame pack [frame .top] -side top pack [label .top.l -textvar time -font {Tahoma 18}] -side left # Buttons pack [frame .top.buttons] -side right set clockbutton [button .top.buttons.t -image appclock16 -relief flat] pack $clockbutton -side left set resetbutton [button .top.buttons.close -image resetclock16 -relief flat] pack $resetbutton -side left ## -- Bottom frame pack [frame .bottom] -side bottom pack [label .bottom.l -textvar telapsed -font {Tahoma 10}] $clockbutton config -command "toggleTimer $clockbutton" $resetbutton config -command "resetTimer $clockbutton" ## -- Start! set telapsed "00:00" every 1000 { set ::time [clock format [clock sec] -format %H:%M] if {$::timerstate} {set ::telapsed [timeElapsed [expr {$::prevtime + [clock sec] - $::t0}]]} } ---- ''[escargo] 19 Jul 2005'' - Here is a variation that I created so that the time would show even if the application was reduced to the Windows Taskbar. However, there is some behavior that I found quite curious. So, here is a slight change from the original code, primarily to set the time into the applications title and the iconname. proc every {ms body} { eval $body after $ms [list every $ms $body] } proc update {} { set ::time [clock format [clock sec] -format %H:%M:%S] wm title . $::time wm iconname . $::time } pack [label .l -textvar time -font {Tahoma 24}] pack [button .b -text Exit -command exit] every 1000 {update} Now, here is the curious behavior. If this app is run (on Windows XP Pro with ActiveTcl 8.4.9), if the app is minimized so that it's on the task bar, the timer updates. (It's only advantage over the taskbar clock is that it counts the seconds.) '''But''' if there are two Tcl apps running at the same time, the taskbar shows "2 Wish Application" (because of stacking of the two apps because the taskbar is full). If you click on the taskbar icon for the two apps the iconnames show but '''the iconnames don't update'''! Even more amusing is that the iconnames appear in tooltips when you roll over the iconnames with the updated values that are not shown in the iconnames. It's not clear what the expected behavior ought to be; I thought that the iconnames should update just as well when the iconnames are stacked as when they are sitting on the taskbar, but apparently some graphical update threads are not being called when they are stacked. ---- [Category Application] | [Category GUI] | [Category Date and Time]