Gtk2Hs レイアウト管理

ホーム   目次


Gtk2Hsでは、ウィンドウにウィジェット(GUI部品)をレイアウトするために、Fixed、Alignment、Box、Tableなどの方法が用意されています。

Fixed、Alignment、Box、Tableは、コンテナウィジェットです。コンテナウィジェットとは、内部に子ウィジェットを配置することができるウィジェットです。Fixed、Alignment、Box、Tableは目に見えません。

Fixed

Fixedコンテナは、子ウィジェットを固定位置に配置します。

fixed.hs


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

Alignmentは子ウィジェットのX座標の配置を左か右か、Y座標の配置を上か下かを指定します。そして、X軸とY軸に拡大するかどうかも指定できます。

bottomleft.hs


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

Boxウィジェットには、VBoxウィジェットとHBoxウィジェットの2つがあります。
VBoxは子ウィジェットを縦に配置し、HBoxは子ウィジェットを横に配置します。
ここでは、VBoxの例を扱います。

vbox.hs


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の応用

AlignmentとBoxの応用例として、ボタンを2つ、ウィンドウの右下に配置する例を示します。

cornerbuttons.hs


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

Tableウィジェットは、子ウィジェットを行と列を指定してマス目に配置します。

table.hs


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_」を使うことによってもっと簡素に記述できます。

table1.hs


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リストから整数番目の要素を取り出します。

Tableの応用

windows.hs


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
    


18403 visits
Posted: Dec. 26, 2018
Update: Dec. 26, 2018

ホーム   目次   ページトップ