PerlでGUIプログラミング(3)
2023/03/25
ウィジェット配置はpackから
  • 今回はPerl/Tkで Geometry Management と呼ばれるウィジェットの配置を扱います。ウィジェットの配置や大きさを制御するメソッド(Geometry Manager)には下記4種があります。
    • pack
    • grid
    • place
    • form
    • :多くのケースに適用できる
      :ウイジェットを格子状に並べる場合は最適
      :Windowサイズ固定の構成に向いている
      :マイナーなのでおすすめしない

  • 前回も書いたように我々の場合「CUIにGUIを被せた」ツールを作ることが多いので、ほぼ使うのはpackメソッドになります。そこで最初はpackの使い方を、特にPODではわかりくい(*1)ところを説明します。

packの配置指定
  • packは大まかな配置指定でウィジェットが自動配置されるため使いやすいメソッドです。ですが実は少しクセがあります。

  • packは「MainWindow又はFrame(フレーム)内」で top/left/right/bottom と呼ばれる配置方法を -side の引数として指定できます。図中の矢印はウィジェットが追加されていく方向を示しています。デフォルトは top です。


    Figure 1: packの-sideで指定できるウィジェット配置指定の種類

  • 例を見てみましょう。まずはデフォルトの top です。packしたウィジェットが上から下へ追加されています。


    Figure 2: -side=>'top'(デフォルト)のウィジェット配置

  • 複数の配置指定を使うこともできます。Figure 3は top と left を利用した例です。ここまでならイメージした通りのウィジェット配置になるでしょう。


    Figure 3: -side=>'top', -side=>'left' 指定時のウィジェット配置

  • ならば、top/left/right/bottom 全部指定したらどうなるかやってみると、思ったものと違う結果になります。Figure 4では bottom が left と right の間を突き抜けちゃってます。


    Figure 4: 指定が複雑だと思い通りにいかない

  • これからわかるように -side による指定は「原則一種類」で使います(*2)。すると「えっ? 単純な配置しかできないの?」と思われるかもしれませんが、当然そんなことはありません。ここでFigure 1説明にて「しれっ」と書いた「MainWindow又はFrame(フレーム)内」が効いてきます。はい。Frame(フレーム)ウィジェットと組み合わせて使うのです。

Frameもウィジェットの一つ
  • さて、ここで唐突に出てきたFrameですが、これもButtonやEntryと同様なウィジェットの一つで、自身にウィジェットを配置できる領域(コンテナ/containers)です。

  • そして一番最初に用意するMainWindowオブジェクトですが、これもFrameの一つです。(自称)原則に則れば、MainWindowというFrameの配置指定も一種類になりますが、そこに複数のFrameウィジェットを配置した場合、その各Frameに対して別々の配置を設定することができます

  • そこで、先程失敗したFigure 4の配置をFrameによって実現してみましょう。Figure 5はイメージになりますが、黒点線がFrameウィジェットに相当します。


    Figure 5: Frameを使ってウィジェット配置再トライ

  • それでは実際にFrameを使って配置をしてみましょう。サンプルコードは [こちら] になります。Frameとウィジェット配置の流れをFigure 6に示します。

    Figure 6: Frameを使用したウィジェット配置例

  • まずstep1でFrameウィジェットを定義してMainWindow内に配置します。これは上から順に並べるのでtopを指定します。
    # ================================================
    # step1: define and pack main frames in MainWindow
    # ================================================
      my $frm;
      $frm->[0]=$mw->Frame(); $frm->[0]->pack(-side=>'top');
      $frm->[1]=$mw->Frame(); $frm->[1]->pack(-side=>'top');
      $frm->[2]=$mw->Frame(); $frm->[2]->pack(-side=>'top');

  • 次にstep2です。2段目のFrame:frm->[1]には2種類の配置設定があるので、更に内部にFrameを定義します。Frameは横方向に並べるので 'left' 指定でpackします。
    # =============================================
    # step2: define and pack sub frames in frm->[1]
    # =============================================
      my $frms;
      $frms->[0]=$frm->[1]->Frame(); $frms->[0]->pack(-side=>'left');
      $frms->[1]=$frm->[1]->Frame(); $frms->[1]->pack(-side=>'left');

  • 最後のstep3にて、作成したFrameウィジェット内に、実際にユーザの目に触れるウィジェットを定義/配置していきます。
    # ============================
    # step3: set widgets in frames
    # ============================
      my $wgt;
      $wgt->[0]=$frm->[0]->Button(-text=>'widget0');  $wgt->[0]->pack(-side=>'top');
      
      $wgt->[1]=$frms->[0]->Button(-text=>'widget1'); $wgt->[1]->pack(-side=>'left');
      
      $wgt->[2]=$frms->[1]->Button(-text=>'widget2'); $wgt->[2]->pack(-side=>'right');
      $wgt->[3]=$frms->[1]->Button(-text=>'widget3'); $wgt->[3]->pack(-side=>'right');
      
      $wgt->[4]=$frm->[2]->Button(-text=>'widget4');  $wgt->[4]->pack(-side=>'bottom');
      $wgt->[5]=$frm->[2]->Button(-text=>'widget5');  $wgt->[5]->pack(-side=>'bottom');

次回はもう少し細かい設定など
  • 今回は、ウィジェット配置をイメージ通りに行うため最初に必要なFrameとpackの関係を説明しました。次回はもう少し細かい点を扱う予定です。
Notes
  • PODサイトは図が貼れないようで、ジオメトリの説明が言葉(英語)だけ。圧倒的イメージ不足っ...!
  • これは私見ですが、この原則を守ると配置検討しやすくなります。
Copyright(C) 2023 Altmo
本HPについて