728x90
Pack 형상 관리자
- 형상 관리자는 화면에 widget을 배치
- 각 widget마다 다른 종류의 형상 관리자를 사용
- 형상 관리자는 부모 widget을 하나 사용하며 그 안에 여러 개의 자식 widget을 배치
- 부모 widget은 보통 프레임
- 하나의 widget은 한번에 하나의 형상 관리자에 의해서만 관리
- widget이 형상 관리자와 연결되지 않으면 화면에 나타나지 않음
- packer는 강력한 형상 관리자
- 각 윈도우의 정확한 위치 대신, 어떤 방식으로 배치하는지 알려주면 packer가 알아서 배치
- 본 글에서는 예제를 통해 packer 형상 관리자를 이용
모서리쪽에 붙이기
- 두개의 프레임을 생성한 후 각각을 메인 윈도우의 위쪽에 붙임
- 더 위쪽에 배치될 윈도우가 .one이며 그 아래에 .two 윈도우가 배치
- 모서리 위치는 top, right, bottom, left 중 하나
# Make the main window black
. config -bg black
# Create and pack two frames
frame .one -width 40 -height 40 -bg white
frame .two -width 100 -height 50 -bg grey50
pack .one .two -side top
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 메인 윈도우는 두 개의 자식 윈도우를 담을 크기만큼만 지정
- 기능을 해제하기 위해서 pack propagate명령을 사용
- pack propagate 명령을 부모 프레임에 사용하면 자식 윈도우의 크기에 맞추어 변경되지 않음
# Make the main window black
. config -bg black
# Create and pack two frames
frame .one -width 40 -height 40 -bg white
frame .two -width 100 -height 50 -bg grey50
pack propagate . false
pack .one .two -side top
- 위의 예제를 실행하면 아래의 화면이 만들어짐
가로 세로 쌓기
- 일반적으로 프레임 안에서 가로나 세로로 widget을 쌓을 수 있음
- 만약 한 프레임 안의 자식 widget들에 대해 left와 top을 동시에 사용하면 오작동 발생 가능성
- 이러한 경우는 자식 프레임을 만들어 다른 형태로 widget을 쌓는다
- 앞의 예제에서 위쪽 프레임을 버튼에 가로로 배열
# Make the main window black
. config -bg black
# Create two frames
frame .one -bg white
frame .two -width 100 -height 50 -bg grey50
# Create a row of buttons
foreach b {alpha beta gamma} {
button .one.$b -text $b
pack .one.$b -side left
}
pack .one .two -side top
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 좀더 복잡한 배치를 위해 프레임을 중복하여 사용
# Make the main window black
. config -bg black
# Create two frames
frame .one -bg white
frame .two -width 100 -height 50 -bg grey50
# Create a row of buttons
foreach b {alpha beta} {
button .one.$b -text $b
pack .one.$b -side left
}
# Create a frame for two more buttons
frame .one.right
foreach b {delta epsilon} {
button .one.right.$b -text $b
pack .one.right.$b -side bottom
}
pack .one.right -side right
pack .one .two -side top
- 위의 예제를 실행하면 아래의 화면이 만들어짐
Cavity 모델
- packing 알고리즘은 프레임 안의 남는 공간에 대해 cavity 모델을 사용
- 메인 윈도우가 생성될 때 메인 프레임은 비어 있으며 widget을 배치할 자리가 있음
- widget은 남은 공간의 한 면을 전부 차지
# Make the main window black
. config -bg black
# Pack two frames on the bottom
frame .one -width 100 -height 50 -bg grey50
frame .two -width 40 -height 40 -bg white
pack .one .two -side bottom
# Pack another frame to the right
frame .three -width 20 -height 20 -bg grey75
pack .three -side right
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 위의 예제에서 .three widget은 오른쪽에 배치되었지만 .two아래로는 내려가지 않음
- .two widget이 bottom 면에 배치되어 있으므로 가로방향으로 한 면을 전부 차지했기 때문
팩킹 공간과 디스플레이 공간
- packer는 팩킹 공간과 디스플레이 공간을 구분
- 디스플레이 공간은 widget을 화면에 보여주기 위해 요청되는 구역
- 팩킹 공간은 widget의 배치를 위해 허용하는 구역
- 화면 구성상의 특징 때문에 팩킹 공간은 디스플레이 공간보다 더 클 수 있음
- -fill 옵션은 디스플레이 공간이 차지하는 공간을 채우도록 만듬
#Make the main window black
. config -bg black
# pack two frames on the bottom
frame .one -width 100 -height 50 -bg grey50
frame .two -width 40 -height 40 -bg white
# Pack with fill enabled
pack .one .two -side bottom -fill x
frame .three -width 20 -height 20 -bg red
pack .three -side right -fill x
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- -fill x 옵션이 사용되면 위와 같이 자신이 차지하는 구역 전부에 꽉 채워져 화면에 나타남
- fill 옵션은 다음과 같이 메뉴바를 만드는데 많이 사용
frame .menubar -bg white
frame .body -width 150 -height 50 -bg grey50
# Create buttons at either end of the menubar
foreach b {alpha beta} {
button .menubar.$b -text $b
}
pack .menubar.alpha -side left
pack .menubar.beta -side right
# Let the menu bar fill along the top
pack .menubar -side top -fill x
pack .body
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 좀 더 많은 공간을 확보할 때는 padding을 지정한다. -ipadx 혹은 -ipady
frame .menubar -bg white
frame .body -width 150 -height 50 -bg grey50
# Create buttons at either end of the menubar
foreach b {alpha beta} {
button .menubar.$b -text $b
}
pack .menubar.alpha -side left -ipady 10
pack .menubar.beta -side right -ipadx 10
# Let the menu bar fill along the top
pack .menubar -side top -fill x -ipady 5
pack .body
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 내부 패딩의 크기를 다르게 했기에 alpha와 beta 버튼의 크기는 다름
- 버튼은 -padx와 -pady의 또다른 패딩 옵션을 제공
- -padx와 -pady 옵션은 버튼 안에 들어가는 글자가 버튼의 경계보다 안쪽에 들어가게 함
# Foo has internal padding from the packer
button .foo -text Foo -anchor e -padx 0 -pady 0
pack .foo -side right -ipadx 15 -ipady 10
#Bar has its own padding
button .bar -text Bar -anchor e -pady 15 -padx 10
pack .bar -side right -ipadx 0 -ipady 0
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 원래 -padx와 -pady 옵션은 외부 패딩을 정하기 위해 사용
- 이것은 widget의 바깥 부분에 들어가는 패딩이며 3차원 효과를 나타내는 부분
. config -borderwidth 10
# OK is the default button
frame .ok -borderwidth 2 -relief sunken
button .ok.b -text OK
pack .ok.b -padx 5 -pady 5
# Cancel is not
button .cancel -text Cancel
pack .ok .cancel -side left -padx 5 -pady 5
- 위의 예제를 실행하면 아래의 화면이 만들어짐
크기 확장과 크기 조절
- -expand true 옵션은 widget이 자기 자리가 아니지만 비어 있는 곳까지 확장하도록 함
- -expand 옵션이 사용되는 더 일반적인 예는 크기를 변경할 수 있는 윈도우
- 윈도우가 더 커지면 새로 만들어진 남는 공간을 사용하라고 widget들에게 말해야 함
- 윈도우의 크기는 사용자가 직접 변경할 수 있고 wm geometry 명령을 이용해 변경도 가능
- 기본적으로 윈도우의 크기는 변경불가능
- wm minsize나 wm maxsize 명령은 윈도우의 크기를 바꿀 수 있게 하는 부가적인 효과를 가짐
# Make the main window black
. config -bg black
# Create and pack two frames
frame .menubar -bg white
frame .body -width 150 -height 50 -bg grey50
# Create buttons at either end of the menubar
foreach b {alpha beta} {
button .menubar.$b -text $b
}
pack .menubar.alpha -side left
pack .menubar.beta -side right
#Let the menu bar fill along the top
pack .menubar -side top -fill x
pack .body
# Resize the main window to be bigger
wm geometry . 200x100
# Allow interactive resizing
wm minsize . 100 50
- 위의 예제를 실행하면 아래의 화면이 만들어짐
실행 시 뜨는 창의 크기
최소로 만들었을 때 유지되는 창의 크기
- 다음 명령을 실행하면 윈도우는 아래와 같이 바뀜
pack .body -expand true -fill both
- 그러나 하나의 부모 widget 밑에 있는 두 개 이상의 widget이 모두 -expand 옵션을 사용할 경우 각 widget이 비례적으로 남은 공간을 나누어 가짐
- 위의 pack 명령 대신 아래 명령을 실행하면 화면이 바뀜
pack .menubar -expand true -fill x
pack .body -expand true -fill both
Anchoring
- widget이 디스플레이 공간보다 더 많은 팩킹 공간이 있을 때에는 -anchor 옵션을 사용해 패킹 공간에서 위치 지정 가능
- 기본 위치는 center, 가능한 위치는 n, ne, e, se, s, sw, w, nw임
# Make the main window black
. config -bg black
# Create two frames to hold open the cavity
frame .prop -bg white -height 80 -width 20
frame .base -width 120 -height 20 -bg grey50
pack .base -side bottom
# Float a label and the prop in the cavity
label .foo -text Foo
pack .prop .foo -side right -expand true
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- .base 프레임은 바닥에 배치
- .prop와 .foo 레이블은 오른쪽에 배치되지만 fill 옵션은 선택되지 않음
- 그에 따라 .foo는 기본적으로 중앙에 배치됨
- 다음 예는 -anchor 옵션을 사용하는 예
# Make the main window black
. config -bg black
# Create two frames to hold open the cavity
frame .prop -bg white -height 80 -width 20
frame .base -width 120 -height 20 -bg grey50
pack .base -side bottom
# Float a label and the prop
# Change their position with anchors
label .foo -text Foo
pack .prop .foo -side right -expand true -anchor sw
pack .foo -side right -expand true -anchor ne
- 위의 예제를 실행하면 아래의 화면이 만들어짐
패킹 순서
- packer는 프레임에 들어가는 자식 widget들의 순서를 유지
- 기본적으로 새로 추가된 widget은 가장 마지막 팩킹 순서 뒤에 추가됨
- 팩킹 순서는 가장 높은 팩킹 순서를 가지는 widget이 모서리쪽에 가깝게 배치
- -before나 -after 팩킹 옵션을 사용하면 팩킹 순서를 바꿀 수 있음
- 이미 들어간 widget의 팩킹 순서도 변경 가능
#Create five labels in order
foreach label {one two three four five} {
label .$label -text $label
pack .$label -side left -padx 5
}
#ShuffleUp moves a widget to the beginning of the order
proc ShuffleUp { parent child } {
set first [lindex [pack slaves $parent] 0]
pack $child -in $parent -before $first
}
#ShuffleDown moves a widget to the end of the order
proc ShuffleDown { parent child } {
pack $child -in $parent
}
- 위의 예제를 실행하면 아래의 화면이 만들어짐
- 여기서 다음 명령어를 실행하면 아래와 같이 변경됨
ShuffleUp . .five
ShuffleDown . .three
- pack slaves 명령은 팩킹 순서로 자식 widget의 리스트를 반환
- 일반적으로 모든 widget은 그 부모의 자손 window에는 어디에나 포함 가능
- 예를 들어 .a.b widget은 .a, .a.c, .a.d.e.f 등의 window에 모두 포함가능
- -in 옵션은 다른 부모를 선택하게 해줌
- pack forget 명령은 포함된 widget을 끄집어 냄
728x90
728x90
'Programming > TclTk' 카테고리의 다른 글
Tcl namespace eval command (1) | 2022.09.16 |
---|---|
TK X 이벤트와 Tcl 명령의 연결 (0) | 2022.09.13 |
TK 예제로 배우는 Tk (0) | 2022.09.08 |
TK 기초 (0) | 2022.09.07 |
TCL 스크립트 라이브러리 (0) | 2022.09.06 |
댓글