試験運用中なLinux備忘録・旧記事

はてなダイアリーで公開していた2007年5月-2015年3月の記事を保存しています。

PyGTKでGUI部品を自前で描画する(前半)

GTK+ではDrawingAreaというGUI部品を用いることにより、その中に自由に描画を行うことができる。
GUI部品の描画はウィンドウのサイズ変更時や最小化後の最小化解除といった場面で描き直しがされるようになっているが、これもうまく処理されるようにできる。
ここではPyGTKでDrawingAreaを用いる上でのメモを扱う。

流れ

DrawingAreaを用いたときの大まかな流れは決まっている。

  1. gtk.DrawingAreaクラス(もしくはこれを継承したもの)のオブジェクトを作成し、他のGUI部品と同様にウィンドウに配置する
  2. size-allocate,realize(GDK使用時のみ),expose-eventのシグナルをハンドラに関連付ける
  3. GDK使用時にはrealizeシグナルのハンドラでgtk.gdk.GCオブジェクトを作成し、色などの属性を設定する
  4. expose-eventシグナルのハンドラで描画処理を記述

描画にはGTK+の下位にあるGDKライブラリの描画命令かCairoライブラリが利用できる。バージョン2.8以上のPyGTKがCairoに対応している。Cairoのほうが図形の描画は(アンチエイリアスにより)綺麗にできる他、環境に依存せず色々なところで使えるライブラリとしての(習得と利用における)メリットもある。

描画

描画に関する処理はgtk.DrawingAreaクラスのメンバwindowに対するメンバ関数で行う。この「window」というメンバはgtk.gdk.Windowオブジェクトで、gtk.gdk.Drawableクラスから派生したものとなり、このクラスのメンバ関数も利用できる。

GDKを用いた描画

GDKを用いた描画についてはgtk.gdk.Drawableクラスメンバ関数を主に用いる。同じ領域に描画がかぶる場合は後から描かれたものが優先して表示される。
色などを引数に指定するためにはあらかじめ用意したgtk.gdk.GCオブジェクト(メンバ関数new_gc()で生成)が必要となり、他にも座標などを指定するのに多くの引数を渡すことになる。
詳しくは触れないが、線や四角/多角形,Pixbuf(画像データ),円(の一部)など、色々なものが描画できる。
文字列を描画するにはGUI部品(ここではDrawingArea)のメンバ関数create_pango_layout()にて文字列描画用のpango.Layoutオブジェクトを作成し、引数に文字列を指定する。その後メンバ関数set_font_description()でフォント(pango.FontDescriptionオブジェクト)を指定し、メンバwindowのメンバ関数draw_layout()でこれを渡す。

Cairoを用いた描画

Cairoを用いて描画する場合はメンバwindowのメンバ関数cairo_create()によりgtk.gdk.CairoContextオブジェクトを得る。これは

メンバ関数を用いて描画ができるオブジェクトとなる。実際にはpycairoのContextクラスメンバ関数を主に用いることになる。
pycairoで色を指定したい場合は

def __on_self_expose_event(self, widget, event):
  """
  DrawingAreaのexpose-eventシグナルのハンドラ
  """
  ctx = widget.window.cairo_create()
  ctx.set_source_color(gtk.gdk.Color('#ff0000'))
  ...

メンバ関数set_source_color()gtk.gdk.Colorオブジェクト*1を渡す(手っ取り早い方法)か
もしくは

def __on_self_expose_event(self, widget, event):
  """
  DrawingAreaのexpose-eventシグナルのハンドラ
  """
  col = gtk.gdk.color_parse('#ff0000')
  ctx = widget.window.cairo_create()
  ctx.set_source_rgb(col.red_float, col.green_float, col.blue_float)
  ...

gtk.gdk.color_parse()に色の文字列を入れてgtk.gdk.Colorオブジェクトを得て、そのメンバ

  • red_float
  • green_float
  • blue_float

をコンテキストオブジェクトのメンバ関数set_source_rgb()の引数に渡すと便利。pycairoのset_source_rgb()set_source_rgba()(アルファチャンネル指定付き)はRGBの各成分を0から1の範囲の値で指定する形で色を指定することになる。
その他、pycairoのContextクラスメンバ関数の中にはCairo上の幾つかの定数(例:cairo.FONT_WEIGHT_NORMAL)を指定する場面があり、この際には「cairo」のモジュールをimportしておく必要がある。また、円の描画などにおいて、円周率(math.pi)が必要になることもあるため、「math」のモジュールも必要になることがある。

import cairo
import math

(2010/3/26)Cairoを用いた描画の実際に関するメモは「pycairoのContextクラスで描画を行う上での幾つかのメモ」で扱っている。

(「PyGTKでGUI部品を自前で描画する(後半)」に続く)

関連記事:

参考URL:

使用したバージョン:

  • Python 2.6.4
  • PyGTK 2.16.0
  • pycairo 1.8.6

*1:コンストラクタ引数に「#RRGGBB」形式の文字列を入れるなどにより初期化できる