본문으로 바로가기

Tk의 텍스트(text)

category 카테고리 없음 2024. 4. 30. 12:57

텍스트 위젯은 이미 설명한 태그의 기능 외에도 몇 개의 중요한 기능을 갖고 있습니다.

인덱스(index)

텍스트 위젯은, 텍스트의 위치를 나타내는 인덱스 기능을 갖고 있습니다. 인덱스는 아래의 형식으로 되어 있습니다. 인덱스 수식자은 여러 개 지정할 수 있지만 생략도 가능합니다.

베이스(base) ?인덱스 수식자? ?인덱스 수식자?

베이스의 목록

베이스 설명
line.char 텍스트의 행과 컬럼의 위치. 행은 1부터, 컬럼은 0부터 시작됩니다. char이 end일때는 행의 새로운 라인(new line)의 위치를 나타냅니다.
@x,y 텍스트의 x좌표와 y좌표(픽셀 단위)의 위치
end 텍스트 끝의 뉴 라인 (new line) 위치
mark mark 라고 말한 이름의 마크 뒤의 위치
tag first tag 라고 말한 이름의 태그 선두 위치
tag last tag 라고 말한 이름의 태그의 최고 뒤의 위치
pathName pathName 으로 만들어진 위젯의 위치
imageName imageName 으로 만들어진 이미지의 위치
insert 문자가 놓여진 위치

인덱스 수식자의 목록

수식자 설명
+count chars + 만큼의 count 문자의 위치
-count chars - 만큼의 count 문자의 위치
+count lines - 만큼의 count 라인의 위치
-count lines - 만큼의 count 라인의 위치
linestart 첫 행의 위치
lineend 제일 끝 행의 라인의 위치
wordstart 워드의 선두의 위치
wordend 워드의 끝의 위치

 

아래는 베이스와 인덱스 수식자를 조합시킨 예입니다.

# 텍스트  끝의 1 문자전의 위치의 인덱스를 돌려 준다
.t index "end -1 chars"
# 워드의 처음으로부터 1 문자전의 위치의 인덱스를 돌려 준다
.t index "insert wordstart -1 c"
# 텍스트의 끝에 문자열을 삽입한다
.t insert end "Hello World\n"
# 첫 행의 1 행을 얻는다
.t get "1.0 linestart" "1.0 lineend"위젯의 삽입
텍스트 위젯 안에 위젯을 삽입할수 있습니다.
pack [text .t]
button .b -text Push -command exit
.t window create end -window .b

이미지의 삽입

텍스트 위젯 안에 이미지를 삽입할수 있습니다. 

pack [text .t]
image create photo foo -file hana.gif
.t image create end -image foo -name bar

워드의 인식

Tcl 8.3 부터 텍스트 위젯 안에서 더블 클릭 시에 워드가 선택되는 기능에 대해 선택되는 워드의 정의를 tcl_wordchars와 tcl_nowordchars 변수에 정규표현으로 설정할 수 있게 되어 있습니다. 워드의 세퍼레이터(separator)의 기본값은 공문자로 되어 있습니다. 예를 들면, 도트(.)를 구분자로 지정하고 싶은 경우는, 아래와 같이 설정을 합니다. 

set tcl_wordchars {[^ \t\n.]+}
set tcl_nonwordchars {[ \t\n.]+}

행의 끝

행의 끝을 인덱스로 지정한 때에 뉴라인을 포함한 경우와 안한 경우는 아래와 같이 하이라이트 한 경우 다릅니다. 

pack [text .t]
.t insert end "Hello World\nHello World\nHello World\n"
.t tag configure foo -background blue -foreground white
# 뉴라인을 포함하지 않는다
.t tag add foo 1.0 1.end
# 뉴라인을 포함한다
.t tag add foo 2.0 "2.end +1 chars"
# 뉴라인을 포함한다
.t tag add foo "3.0 linestart" "3.0 lineend +1 chars"

문자열의 검색

텍스트 위젯안에 텍스트를 정규표현을 사용하여 검색할 수 있습니다. search는 문자열이 발견되면 문자열 선두의 인덱스를 돌려줍니다. 

pack [text .t]
.t insert end "Hello World\n"
# 텍스트 전체로부터 문자열 검색
.t search -forwards -count length -- "World" 1.0 end
=>1.6
# 텍스트 전체로부터 정규 표현을 사용하고 문자열을 검색
.t search -forwards -count length -regexp -- "Wo.*ld" 1.0 end
=>1.6

마크(mark)

인덱스에 마크로 이름을 붙이면, 마크 이름으로 인덱스의 역할을 할수 있습니다.

# 마크로 이름을 붙인다
.t mark set foo 1.0
# 인덱스에 마크 이름을 지정한다
.t index foo
=>1.0
# 마크 이름의 목록을 얻는다
.t mark names
=>foo insert anchor current

위의 결과에서 보는바와 같이 insert는 기본 마크 이름인 것 같으며, insert, anchor, current는 예약어라고 말할 수 있습니다.

폭과 높이 얻기

텍스트 위젯의 폭과 높이는 아래와 같이 얻을수 있습니다. 기본 폭과 높이는, 80×24 문자입니다.

pack [text .t]
.t cget -width
=>80
.t cget -height
=>24

여기서 문제점이 하나 있습니다. 텍스트 위젯은 리싸이즈 후에도 80×24 를 돌려줍니다. 이것은 번거로운 일이 아닐 수 없을 것입니다. 그렇다면, 리사이즈 후의 폭과 높이를 정상적으로 얻으려면 어떻게 해야 할까요? 아래의 예는, 텍스트 위젯의 spacing을 고려하여, 윈도우 사이즈와 폰트 사이즈로부터 문자를 계산하여 폭과 높이를 구하고 있습니다. 텍스트 위젯이 -wrap none이 적용되지 않는 상황과 fixed 폰트라면 잘 될 것입니다.

# 텍스트 위젯의 폭을 돌려 주는 프로시져
proc textwidth {path} {
        set width [winfo width $path]
        set font [$path cget -font]
        set measure [font measure $font "A"]
        return [expr $width / $measure]
}

# 텍스트 위젯의 높이를 돌려 주는 프로시져
proc textheight {path} {
        set height [winfo height $path]
        set font [$path cget -font]
        set space [expr [$path cget -spacing1] + [$path cget -spacing3]]
        set metrics [font metrics $font -linespace]
        return [expr $height / ($metrics + $space)]
}

Disabled 상태

텍스트 위젯은 -state의 normal과 disabled를 지정할 수 있습니다. disabled 라면, 편집을 할수 없는 쓰기 금지 모드가 됩니다. disabled 시에는, 텍스트 위젯에 커서가 보이지 않게 되며, 문자열을 추가나 삭제를 할수 없게 됩니다. 이는 텍스트 위젯을 사용하여 자동으로 로그를 출력하고 싶을 때,

normal -> 문자열 추가 -> disabled

의 불필요한 작업을 해야만 합니다. 아래의 예는 텍스트 위젯의 바인드의 우선순위를 변경하여, 텍스트의 disabled 문제를 해결하고 있습니다. 

pack [text .t]
# bind의 우선 순위를 변경한다
bindtags .t {.t Text . all}
# 입력을 무시한다
bind .t <Any-Key> {break}
bind .t <Up> {continue}
bind .t <Down> {continue}
bind .t <Left> {continue}
bind .t <Right> {continue}
bind .t <Control-p> {continue}
bind .t <Control-n> {continue}
bind .t <Control-f> {continue}
bind .t <Control-b> {continue}