bonkora 님이 제공해 주신 글 입니다.
프로그램을 만들면서 일정한 시간 간격으로 특정작업을 하게 만들어야 할 때가 있을 것입니다. 어떤 작업을 수행하면서 몇 초가 경과했는지를 매 초마다 표시하는 것을 예로 들 수 있겠습니다. 여기 소개하는 synctimer 확장패키지가 바로 그 일을 해 줍니다.
synctimer 패키지를 다운로드하여서 Tcl이 설치되어 있는 디렉터리의 아래에 있는 lib 디렉토리에 압축을 풀어 넣습니다. 그러면 lib 디렉토리 아래에 synctimer1.1 디렉터리가 생깁니다. 이 확장패키지를 사용하기 위해서 두 가지의 명령만 알면 됩니다. 타이머를 세팅하는 명령은 이렇습니다.
SyncTimer::every _interval_ _basetime_ _script_ ?_script_ ...?
_interval_은 시간 간격을 지정해 주는 옵션입니다. 예를 들면 "1 hour", "20 minutes", "2 minutes 30 seconds" 이렇게 표시합니다. 가장 작게는 1초를 지정할 수 있고 최대 2**31 msec(약 24 일 20 시간)까지 지정할 수 있습니다. _basetime_은 타이머를 시스템클럭과 맞추는 옵션입니다. 보통은 "00:00:00"를 사용합니다. 만약 SyncTimer::every "5 minutes" "00:00:10" .... 이렇게 하면 시스템클럭이 5분을 친 후 10초가 경과할 때마다 타이머가 작동한다는 뜻입니다. 즉 시점 hh:00:10, hh:05:10, hh:10:10, hh:15:10 ... hh:55:10에 타이머가 작동하게 됩니다. _script_는 타이머가 작동할 때 실행시킬 스크립트입니다. SyncTimer::every 명령은 나중에 타이머를 중단시킬 때 사용할 이름을 돌려줍니다. 타이머를 중단시키는 명령은 이것입니다.
::SyncTimer::cancel _id_
SyncTimer::every 명령으로 만든 _id_ 타이머를 중단시킵니다. 이 타이머를 사용한 가장 간단한 예는 아래와 같습니다.
proc mycmd {} {
puts "[clock format [clock seconds] -format "%Y-%m-%d %T"]"
}
package require SyncTimer
set t [SyncTimer::every "1 secs" "00:00:00" {mycmd}]
타이머를 중단시키려면 "SyncTimer::cancel $t"라고 명령하면 됩니다. 또 하나의 예로 아래에 1초마다 특정 메시지를 갱신하는 예가 있습니다.
proc mycmd {} {
incr ::mytime 1
.e delete 0 end
.e insert end "$::mytime 초 경과"
}
package require SyncTimer
# 경과된 시간(초)을 세기위한 변수
set mytime 0
# 변수 running은 타이머가 작동중이면 1, 아니면 0
set running 0
entry .e -width 12
.e delete 0 end
.e insert end "대기 중"
button .b -text "시작/중지" -width 8 -command {
# 타이머가 작동중일 때는 중단시키고
# 타이머가 작동하지 않을 때는 작동시킴
if {$running} {
SyncTimer::cancel $timer
.e delete 0 end
.e insert end "대기 중"
set mytime 0
set running 0
} else {
set timer [SyncTimer::every "1 secs" "00:00:00" {mycmd}]
set running 1
}
}
pack .e .b -side left
메시지 대신 프로그래스 바를 사용해 보았습니다.
proc mycmd {} {
incr ::cnttime 1
if {$::cnttime > 10} {set ::cnttime 0}
}
package require SyncTimer
package require BWidget
set cnttime 0
set running 0
ProgressBar .p -maximum 10 -variable cnttime
button .b -text "시작/중지" -width 8 -command {
if {$running} {
SyncTimer::cancel $timer
set cnttime 0
set running 0
} else {
set timer [SyncTimer::every "1 secs" "00:00:00" {mycmd}]
set running 1
}
}
pack .p .b -side left