busy — Tk 위젯을 busy 상태로 만들어 사용자 상호작용 일시 차단하기
busy — Tk 위젯을 busy 상태로 만들어 사용자 상호작용 일시 차단하기
애플리케이션이 오래 걸리는 처리를 하는 동안, 사용자가 다시 버튼을 누르지 못하게 막고 싶을 때가 많아요. 그럴 때 tk busy가 간단한 해법이에요. 마우스 포인터 이벤트를 위젯에서 막고, 위젯의 커서를 설정 가능한 busy 커서로 바꿔줘요. 이 명령어는 busy하게 만든 위젯으로 키보드 이벤트가 보내지는 건 막지 않는다는 점만 기억해두면 돼요.
출처: 문서
본문
문법
tk busy window ?options?
tk busy hold window ?options?
tk busy configure window ?option value?...
tk busy forget window ?window ?...
tk busy current ?pattern?
tk busy status window
tk busy 명령어는 Tk 위젯에서 마우스 포인터 이벤트를 막고, 위젯의 커서를 구성 가능한 busy 커서로 덮어쓰는 간단한 방법을 제공해요. 이 명령어는 busy하게 만든 위젯으로 키보드 이벤트가 보내지는 것은 막지 않는다는 점에 주의하세요.
소개
애플리케이션에서 사용자가 할 수 있는 동작을 잠시 제한하고 싶은 때가 많아요. 예를 들어 애플리케이션이 Run 버튼을 누르면 처리가 일어나는데, 처리 중에는 사용자가 Run 버튼을 다시 누르지 못하게 하고 싶죠. Print 버튼 같은 다른 작업으로 제한하고 싶을 수도 있어요.
tk busy 명령어는 Tk 위젯들을 busy하게 만들 수 있게 해줘요. 즉 버튼 클릭, 마우스 이동, 키보드 입력 같은 사용자 상호작용이 위젯에서 무시된다는 뜻이에요. 위젯의 일반 커서를 덮어쓰는 특별한 커서(예: 시계 모양)를 설정해, 애플리케이션(위젯)이 잠시 busy하다는 피드백을 줄 수 있어요.
위젯이 busy하게 되면, 그 위젯과 모든 하위 위젯은 포인터 이벤트를 무시해요. 위젯 패널 전체를 busy하게 만드는 건 쉬워요. toplevel 위젯(예: .)을 busy하게 하면 되거든요. 위젯 계층을 재귀적으로 탐색하며 각 위젯을 비활성화하고 커서를 다시 구성하는 것보다 훨씬 쉽고 효율적이에요.
종종 tk busy 명령어는 Tk의 grab 명령어 대신 쓸 수 있어요. grab은 모든 사용자 상호작용을 한 위젯으로 제한하는 반면, tk busy 명령어는 둘 이상의 위젯을 활성 상태로 둘 수 있어요(예: Cancel 대화상자와 Help 버튼).
예제
hold 연산으로 조상 위젯만 busy하게 만들면 여러 위젯을 busy하게 만들 수 있어요:
frame .top
button .top.button; canvas .top.canvas
pack .top.button .top.canvas
pack .top
# . . .
tk busy hold .top
update
이제 .top 안의 모든 위젯(.top 포함)이 busy해요. update를 쓰면 tk busy 명령어가 다른 사용자 이벤트가 발생하기 전에 효력을 발휘하도록 보장해요.
애플리케이션이 더 이상 busy하게 처리하지 않을 때, forget 연산으로 사용자 상호작용을 다시 허용하고 할당된 자원을 해제할 수 있어요:
tk busy forget .top
busy 윈도우는 구성 가능한 커서를 가져요. configure 연산으로 busy 커서를 바꿀 수 있어요:
tk busy configure .top -cursor "watch"
위젯을 파괴해도 tk busy 명령어가 할당한 자원이 정리돼요.
연산
tk busy 명령어에 사용 가능한 연산은 다음과 같아요.
tk busy window ?option value?...
tk busy hold 명령어의 단축.
tk busy cget window option
window의 tk busy 명령어 구성 옵션을 조회. window는 hold 연산으로 이전에 busy하게 만든 위젯의 경로 이름이어야 함. 지정한 옵션의 현재 값을 반환. option은 hold 연산이 받아들이는 값 중 아무거나 가질 수 있음.
tk busy configure window ?option value?...
window의 tk busy 명령어 구성 옵션을 조회하거나 수정. window는 hold 연산으로 이전에 busy하게 만든 위젯의 경로 이름이어야 함. 옵션을 지정하지 않으면 window에 사용 가능한 모든 옵션을 설명하는 리스트를 반환(Tk_ConfigureInfo 참조). option을 값 없이 지정하면 그 하나의 옵션을 설명하는 리스트를 반환(option 없이 반환된 값의 해당 서브리스트와 동일). 하나 이상의 option-value 쌍을 지정하면 주어진 위젯 옵션들을 주어진 값들로 수정하며, 이 경우 빈 문자열을 반환. option은 hold 연산이 받아들이는 값 중 아무거나 가질 수 있음.
옵션 데이터베이스는 window를 통해 참조된다는 점을 유의하세요. 예를 들어 위젯 .frame을 busy하게 만들려면, busy 커서를 다음 option 명령어 중 아무것으로나 지정할 수 있어요:
option add *frame.busyCursor gumby
option add *Frame.BusyCursor gumby
tk busy current ?pattern?
현재 busy한 모든 위젯의 경로 이름을 반환. pattern이 주어지면 pattern과 일치하는 busy 위젯의 경로 이름만 반환.
tk busy forget window ?window?...
window에 대해 tk busy 명령어가 할당한 자원(투명 윈도우 포함)을 해제. 사용자 이벤트를 다시 window가 받게 됨. window가 파괴될 때도 자원은 해제됨. window는 hold 연산에서 지정된 위젯의 이름이어야 하며, 그렇지 않으면 오류가 보고됨.
tk busy hold window ?option value?...
지정한 위젯(그리고 Tk 위젯 계층에서 그 하위 위젯들)이 busy하게 보이도록 만듦. window는 Tk 위젯의 유효한 경로 이름이어야 함. 지정한 위젯 앞에 투명 윈도우가 놓임. 이 투명 윈도우는 다음에 idle 작업이 처리될 때 매핑되고, 지정한 위젯과 하위 위젯은 사용자 상호작용에서 차단됨. 보통은 직후에 update를 호출해 hold 연산이 애플리케이션이 처리를 시작하기 전에 효력을 발휘하도록 보장해야 함. 다음 구성 옵션이 유효함:
-cursor cursorName
위젯이 busy하게 됐을 때 표시할 커서를 지정. CursorName은 Tk_GetCursor가 받아들이는 형태 중 아무거나 가능. 기본 커서는 Windows에서는 wait, 다른 플랫폼에서는 watch.
tk busy status window
위젯 window의 상태를 반환. 현재 사용자 상호작용을 받을 수 없으면 1, 그렇지 않으면 0을 반환.
이벤트 처리
BINDINGS — 이벤트 차단 기능은 위젯을 완전히 덮는 투명 윈도우를 만들어 매핑하는 방식으로 구현돼요. busy 윈도우가 매핑되면, 보내질 수 있는 모든 이벤트에서 위젯과 위젯 계층을 보이지 않게 차폐해요. Tk 위젯처럼 busy 윈도우도 Tk 위젯 계층에 위젯 이름을 가져요. 즉 bind 명령어로 busy 윈도우의 이벤트를 처리할 수 있어요:
tk busy hold .frame.canvas
bind .frame.canvas_Busy <Enter> { ... }
보통 busy 윈도우는 위젯의 형제(sibling)예요. busy 윈도우의 이름은 widget_Busy인데, 여기서 widget은 busy하게 만들 위젯의 이름이에요. 위 예에서 busy 윈도우의 경로 이름은 .frame.canvas_Busy예요. 예외는 위젯이 toplevel 위젯(예: .)일 때인데, 이때 busy 윈도우는 형제로 만들 수 없어요. 그 경우 busy 윈도우는 widget._Busy라는 이름의 위젯의 자식이 돼요. 다음 예에서 busy 윈도우의 경로 이름은 ._Busy예요.
tk busy hold .
bind ._Busy <Enter> { ... }
ENTER/LEAVE 이벤트 — busy 윈도우를 매핑·언매핑하면 그 윈도우가 덮는 모든 위젯에 Enter/Leave 이벤트가 생성돼요. 위젯에서 Enter/Leave 이벤트를 추적한다면 이 점을 유의하세요.
KEYBOARD 이벤트 — 위젯을 busy하게 만들면, busy 윈도우 때문에 사용자가 클릭으로 키보드 포커스를 얻지 못해요. 하지만 위젯이 이미 포커스를 가졌다면 여전히 키보드 이벤트를 받을 수 있어요. 위젯은 키보드 이동(traversal)으로도 여전히 포커스를 받을 수 있어요. 이를 막으려면 다른 윈도우로 포커스를 옮기고, busy하게 만든 위젯으로 포커스가 돌아갈 수 없도록 해야 해요(예: cancel 버튼에 포커스를 제한).
pack [frame .frame]
pack [text .frame.text]
tk busy hold .frame
pack [button .cancel -text "Cancel" -command exit]
focus .cancel
bind .cancel <Tab> {break}
bind .cancel <Shift-Tab> {break}
update
위 예제는 hold를 호출한 직후 .frame에서 포커스를 옮겨, 키보드 이벤트가 .frame이나 그 하위 위젯으로 보내지지 않게 해요. 또한 버튼 .cancel을 키보드로 벗어날 수 없도록 보장해요.
이식성
tk busy 명령어는 현재 Tk가 Aqua 지원으로 빌드된 macOS에서는 아무 효과가 없다는 점에 유의하세요.
더 알아보기
grab— 입력을 한 위젯으로 제한하는 명령어- 관련 키워드:
busy,keyboard events,pointer events,window