Gtk2Hsでは、ウィンドウにウィジェット(GUI部品)をレイアウトするために、Fixed、Alignment、Box、Tableなどの方法が用意されています。
Fixed、Alignment、Box、Tableは、コンテナウィジェットです。コンテナウィジェットとは、内部に子ウィジェットを配置することができるウィジェットです。Fixed、Alignment、Box、Tableは目に見えません。
Fixedコンテナは、子ウィジェットを固定位置に配置します。
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowTitle := "Fixed",
windowDefaultWidth := 300,
windowDefaultHeight := 200,
windowWindowPosition := WinPosCenter]
fixed <- fixedNew
containerAdd window fixed
btn1 <- buttonNewWithLabel "ボタン"
fixedPut fixed btn1 (150, 50)
widgetSetSizeRequest btn1 80 30
btn2 <- buttonNewWithLabel "ボタン"
fixedPut fixed btn2 (15, 15)
widgetSetSizeRequest btn2 80 30
btn3 <- buttonNewWithLabel "ボタン"
fixedPut fixed btn3 (100, 100)
widgetSetSizeRequest btn3 80 30
on window objectDestroy mainQuit
widgetShowAll window
mainGUI
fixed <- fixedNew
fixedNew は、fixed ウィジェット作ります。
containerAdd window fixed
ウィンドウも内部に子ウィジェット配置できるコンテナーです。そのウィンドウーに fixed ウィジェットを子ウィジェットとして配置しています。
fixedPut fixed btn1 (150, 50)
「fixedPut」は、第1引数のfixedウィジェトに第2引数のウィジェットを第3引数の位置に配置します。第3引数は、x座標150ピクセル、y座標50ピクセルを表しています。
widgetSetSizeRequest btn1 80 30
「widgetSetSizeRequest」は、第1引数のウィジェットの横幅を第2引数で指定されたピクセル数に、高さを第3引数で指定されたピクセル数に設定します。
Alignmentは子ウィジェットのX座標の配置を左か右か、Y座標の配置を上か下かを指定します。そして、X軸とY軸に拡大するかどうかも指定できます。
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowTitle := "Alignment",
windowDefaultWidth := 300,
windowDefaultHeight := 200,
windowWindowPosition := WinPosCenter,
containerBorderWidth := 5]
align <- alignmentNew 0 1 0 0
label <- labelNew (Just "左下")
containerAdd align label
containerAdd window align
on window objectDestroy mainQuit
widgetShowAll window
mainGUI
align <- alignmentNew 0 1 0 0
「alignmentNew」はAlignmentオブジェクトを作ります。
label <- labelNew (Just "左下")
「labelNew」は、ラベルを作ります。引数でラベルに表示される文字列を指定しますが、その文字列は「Just」型でなければならない決まりになっています。
containerAdd align label
containerAdd window align
alignウィジェットにlabelウィジェットが追加され、そのalignウィジェットがwindowウィジェットに追加されます。
Boxウィジェットには、VBoxウィジェットとHBoxウィジェットの2つがあります。
VBoxは子ウィジェットを縦に配置し、HBoxは子ウィジェットを横に配置します。
ここでは、VBoxの例を扱います。
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowWindowPosition := WinPosCenter,
windowDefaultWidth := 230,
windowDefaultHeight := 250,
windowTitle := "VBox",
containerBorderWidth := 5]
vbox <- vBoxNew True 1
containerAdd window vbox
settings <- buttonNewWithLabel "据付"
accounts <- buttonNewWithLabel "口座"
loans <- buttonNewWithLabel "貸金"
cash <- buttonNewWithLabel "現金"
debts <- buttonNewWithLabel "借金"
boxPackStart vbox settings PackGrow 0
boxPackStart vbox accounts PackGrow 0
boxPackStart vbox loans PackGrow 0
boxPackStart vbox cash PackGrow 0
boxPackStart vbox debts PackGrow 0
on window objectDestroy mainQuit
widgetShowAll window
mainGUI
vbox <- vBoxNew True 1
「vBoxNew」はvBoxウィジェットを作ります。第1引数をTrueにすると、vBoxに配置される子ウィジェットがすべて同じサイズになります。第2引数は子ウィジェット間の空白のサイズです。単位はピクセルです。
boxPackStart vbox settings PackGrow 0
「boxPackStart」は、第1引数のBoxウィジェットに第2引数の子ウィジェットを配置します。第3引数の「PackGrow」は子ウィジェットが領域いっぱいに広がるように指定しています。この第3引数に「PackNatural」を指定すると、子ウィジェットは本体のサイズを保ちます。最後の引数は、ウィジェットの上下の空白を指定します。VBoxの場合は上下の空白ですが、HBoxの場合は、左右の空白を指定することになります。
「boxPackStart」をVBoxに対して使用すると、子ウィジェットを上から配置します。代わりに「boxPackEnd」を使うと子ウィジェットを下から配置します。
「boxPackStart」をHBoxに使用すると、子ウィジェットを左から配置します。代わりに「boxPackEnd」を使用すると子ウィジェットを右から配置します。
ウィンドウを最大化するとボタンも拡大されます。
AlignmentとBoxの応用例として、ボタンを2つ、ウィンドウの右下に配置する例を示します。
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowWindowPosition := WinPosCenter,
windowDefaultWidth := 350,
windowDefaultHeight := 200,
windowTitle := "Corner buttons",
containerBorderWidth := 10]
vbox <- vBoxNew False 5
valign <- alignmentNew 0 1 0 0
containerAdd vbox valign
containerAdd window vbox
hbox <- hBoxNew True 3
okBtn <- buttonNewWithLabel "了解"
widgetSetSizeRequest okBtn 70 30
containerAdd hbox okBtn
clsBtn <- buttonNewWithLabel "閉じる"
containerAdd hbox clsBtn
halign <- alignmentNew 1 0 0 0
containerAdd halign hbox
boxPackStart vbox halign PackNatural 0
on window objectDestroy mainQuit
on clsBtn buttonActivated $ do
mainQuit
widgetHide window
widgetShowAll window
mainGUI
配置についての説明は省略させていただきます。
on clsBtn buttonActivated $ do
mainQuit
widgetHide window
この行は ghc (コンパイラ)でコンパイルして実行する場合は、「on clsBtn buttonActivated mainQuit」でも大丈夫ですが、ghci (インタープリタ)で実行する場合、アプリケーションを終了しても、ウィンドウは表示されたままになります。
そこで、イベントに結びつける動作として「mainQuit」の他に「widgetHide window」を指定しています。「widgetHide」は引数のウィジェットを隠します。動作を複数にするために、「$ do」を使っています。
ウィンドウを拡大しても2つのボタンは右下に配置されます。
Tableウィジェットは、子ウィジェットを行と列を指定してマス目に配置します。
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowWindowPosition := WinPosCenter,
windowDefaultWidth := 250,
windowDefaultHeight := 180,
windowTitle := "Table"]
containerSetBorderWidth window 5
table <- tableNew 4 4 True
tableSetRowSpacings table 2
tableSetColSpacings table 2
btnSeven <- buttonNewWithLabel "7"
tableAttachDefaults table btnSeven 0 1 0 1
btnEight <- buttonNewWithLabel "8"
tableAttachDefaults table btnEight 1 2 0 1
btnNine <- buttonNewWithLabel "9"
tableAttachDefaults table btnNine 2 3 0 1
btnSlush <- buttonNewWithLabel "/"
tableAttachDefaults table btnSlush 3 4 0 1
btnFour <- buttonNewWithLabel "4"
tableAttachDefaults table btnFour 0 1 1 2
btnFive <- buttonNewWithLabel "5"
tableAttachDefaults table btnFive 1 2 1 2
btnSix <- buttonNewWithLabel "6"
tableAttachDefaults table btnSix 2 3 1 2
btnMul <- buttonNewWithLabel "*"
tableAttachDefaults table btnMul 3 4 1 2
btnOne <- buttonNewWithLabel "1"
tableAttachDefaults table btnOne 0 1 2 3
btnTwo <- buttonNewWithLabel "2"
tableAttachDefaults table btnTwo 1 2 2 3
btnThree <- buttonNewWithLabel "3"
tableAttachDefaults table btnThree 2 3 2 3
btnMinus <- buttonNewWithLabel "-"
tableAttachDefaults table btnMinus 3 4 2 3
btnZero <- buttonNewWithLabel "0"
tableAttachDefaults table btnZero 0 1 3 4
btnDot <- buttonNewWithLabel "."
tableAttachDefaults table btnDot 1 2 3 4
btnEqual <- buttonNewWithLabel "="
tableAttachDefaults table btnEqual 2 3 3 4
btnPlus <- buttonNewWithLabel "+"
tableAttachDefaults table btnPlus 3 4 3 4
containerAdd window table
on window objectDestroy mainQuit
widgetShowAll window
mainGUI
table <- tableNew 4 4 True
「tableNew」はTableウィジェットを作ります。第1引数が行の数で、第2引数が列の数です。第3引数でTrueを与えると、Tableに含まれる子ウィジェットの中で最大サイズのウィジェットのサイズが各マス目のサイズになります。
tableSetRowSpacings table 2
マス目同士の縦の空白を設定しています。
tableSetColSpacings table 2
マス目同士の横の空白を設定しています。
tableAttachDefaults table btnSeven 0 1 0 1
「tableAttachDefaults」は第1引数のテーブルに第2引数のウィジェットを配置します。第3引数は配置する列の左側、第4引数は配置する列の右側、第5引数は配置する行の上側、第6引数は配置する行の下側を指定します。
ウィンドウを拡大するとボタンも拡大されます。
このサンプルは次のように「forM_」を使うことによってもっと簡素に記述できます。
import Graphics.UI.Gtk
import Control.Monad -- for forM
main :: IO ()
main = do
let values = ["7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"]
initGUI
window <- windowNew
set window [windowWindowPosition := WinPosCenter,
windowDefaultWidth := 250,
windowDefaultHeight := 180,
windowTitle := "Table"]
containerSetBorderWidth window 5
table <- tableNew 4 4 True
tableSetRowSpacings table 2
tableSetColSpacings table 2
forM_ [0..3] $ \i -> do
let row = i * 4
forM_ [0..3] $ \j -> do
button <- buttonNewWithLabel (values!!(j+row))
tableAttachDefaults table button j (j+1) i (i+1)
containerAdd window table
on window objectDestroy mainQuit
widgetShowAll window
mainGUI
let values = ["7", "8", "9", "/",
"4", "5", "6", "*",
"1", "2", "3", "-",
"0", ".", "=", "+"]
最初に、ボタンに表示される文字のリストを作っておきます。
forM_ [0..3] $ \i -> do
let row = i * 4
「forM_」は指定されたコレクションの各要素に対して、指定した動作を繰り返します。
button <- buttonNewWithLabel (values!!(j+row))
「values!!(整数)」は、valuesリストから整数番目の要素を取り出します。
import Graphics.UI.Gtk
main :: IO ()
main = do
initGUI
window <- windowNew
set window [windowWindowPosition := WinPosCenter]
widgetSetSizeRequest window 300 250
set window [windowTitle := "Windows"]
containerSetBorderWidth window 15
table <- tableNew 6 4 False
tableSetColSpacings table 3
tableSetRowSpacing table 0 3
title <- labelNew (Just "Windows")
halign <- alignmentNew 0 0 0 0
containerAdd halign title
tableAttach table halign 0 1 0 1 [Fill] [Fill] 0 0
wins <- textViewNew
textViewSetEditable wins False
textViewSetCursorVisible wins False
tableAttach table wins 0 2 1 3 [Fill,Expand] [Fill,Expand] 1 1
actBtn <- buttonNewWithLabel "Activate"
widgetSetSizeRequest actBtn 50 30
tableAttach table actBtn 3 4 1 2 [Fill] [Shrink] 1 1
valign <- alignmentNew 0 0 0 0
clsBtn <- buttonNewWithLabel "Close"
widgetSetSizeRequest clsBtn 70 30
containerAdd valign clsBtn
tableSetRowSpacing table 1 3
tableAttach table valign 3 4 2 3 [Fill] [Fill,Expand] 1 1
halign2 <- alignmentNew 0 1 0 0
hlpBtn <- buttonNewWithLabel "Help"
containerAdd halign2 hlpBtn
widgetSetSizeRequest hlpBtn 70 30
tableSetRowSpacing table 3 5
tableAttach table halign2 0 1 4 5 [Fill] [Fill] 0 0
okBtn <- buttonNewWithLabel "OK"
widgetSetSizeRequest okBtn 70 30
tableAttach table okBtn 3 4 4 5 [Fill] [Fill] 0 0
containerAdd window table
on window objectDestroy mainQuit
widgetShowAll window
mainGUI