こんにちは、高木です。

今回はTkのジオメトリーマネージャーについて考えることにします。Tkのジオメトリーマネージャーには次の3種類があります。

packerはウィジェットを上下左右にどんどん積めていきます。placerはX, Y座標を指定してウィジェットを配置します。gridderは行と列を指定して格子状にウィジェットを配置します。Tkではこれらのジオメトリーマネージャーを使ってウィジェットをトップレベルのウィンドウに配置していきます。

それぞれのジオメトリーマネージャーを比べてみると、共通部分が多いことに気付きます。できれば、そうした共通部分は基底クラスにまとめてあげたいものです。ところが、一番基本的なコマンド(configureやforgetなどがなく、pack, place, gridのあとにパラメーターを並べるタイプのコマンド)がplaceだけちょっと違っています。

packとgridは次の形式です。

これに対して、placeは次のような形式になっています。

こういうときは落ち着いてよく見ると、共通部分が見えてくるはずです。

packやgridのoptionsも、option valueの並びだということがわかるはずです。たとえば、-anchor nwのようにです。また、placeはwindowを1個しか指定できませんが、1個以上のwindowを指定できると考えれば同じ形式になります。

よって、次のようにまとめることができるはずです。

このうちoptionとvalueは、widgetクラスのコンストラクターなどで指定するオプションと同じ形式ですのでobj型で渡せばOKです。windowはwidgetクラスを渡したいところですが、それだと派生クラスを渡した際にスライスが起きてしまいます。しかたがないので、windowクラスを別途用意して、const widget&からのコンストラクターを持たせてあげることにします。

それではgeometry_managerクラスのコードを見ていきましょう。

こんな感じで最低限のコマンドを実現することができます。これだけだとoptionsを必ず指定しないといけないので、optionsを省略したバージョンも多重定義しておくといいかもしれませんね。windowsに関しても1個だけのバージョンを用意しておくとよさそうです。無駄に長くなるので、いずれも今回は割愛します。

次に、このgeometry_managerクラスを派生してpackerクラスを作ってみます。placerやgridderも同じですので今回は省略します。

ここまでできれば、何とかウィジェットを配置できるようになります。

ほぼTcl/Tkのイメージ通りのコードでジオメトリーマネージャーが実現できました。

次回はジオメトリーマネージャーについてもう少し深掘りしてみましょう。