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

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

PyGTKでツリービューにリストのデータ(ListStore)を表示(データを変更可能にする・メモ)

PyGTKでツリービューにリストのデータ(ListStore)を表示(概要とメモ)」と「PyGTKでツリービューにリストのデータ(ListStore)を表示(簡単な例)」の続き。前回の例をもとに、データの変更操作を行えるようにしてみた中でのメモとなる。

テキストのセルを編集可能にする

PyGTKのツリービューにおいて、テキストの描画されるセルは編集可能にすることができる。

方法

その方法は2種類あり

  • セルレンダラ(gtk.CellRendererTextオブジェクト)に対して直接メンバ関数set_property()で「editable」をTrueに指定する
  • ListStore/TreeStore側にデータの項目ごとに編集可能にするかどうかの真偽値を持たせておいて、コラム(gtk.TreeViewColumnオブジェクト)の設定のところでセルレンダラのgtk.CellRendererTextオブジェクトに対して「text」以外に「editable」という名前で、データ(ListStore/TreeStore)に持たせた真偽値のコラム番号と結びつける

のいずれかとなる。

シグナルとハンドラ

セルが編集可能になってもそのままでは内容を変更しても反映されず、元の値に戻ってしまう。そこでデータが変更されたときのシグナル「edited」のハンドラを設定した後ハンドラ側でデータを変更することになる。
ハンドラが受け取る引数は(クラス内のメンバ関数をハンドラにしたときに先頭に必要な引数(self)を除くと)

の3つで、パスとテキストのデータを用いてツリービューに関連付けられたデータ(ListStore/TreeStore)のメンバ関数set_value()により対応した場所のデータを書き換える流れとなる。最初の引数はgtk.TreeIterオブジェクト*1を渡すのだが、これはListStore/TreeStoreがともに継承しているgtk.TreeModelオブジェクトメンバ関数get_iter()にハンドラ引数のパスを渡すことで得られる。

画像をセルに表示する

データ(ListStore/TreeStore)の項目にgtk.gdk.Pixbufオブジェクトを含めて、コラムの設定でgtk.CellRendererPixbufオブジェクトをセルレンダラに指定し、データ上の項目と関連付けることにより、ツリービューのセルに画像を表示することができる。

ツリービューのコンテキストメニューを作る

今回、上のgtk.gdk.Pixbufオブジェクトの画像を変更可能にするためにツリービューのコンテキストメニューを作成したのだが、これを実現するのは色々と面倒だった。

  • メニュー項目(gtk.MenuItemオブジェクト)を作りメニュー(gtk.Menuオブジェクト)に追加し、show_all()で表示可能にする
  • gtk.TreeViewオブジェクトの「button_press_event」シグナルでハンドラと関連付け、メニュー項目も別途ハンドラと関連付ける
  • 「button_press_event」のハンドラでは、ツリービュー上の項目があるところでクリックがあったことを確実にする*2ためにgtk.TreeViewオブジェクトのメンバ関数get_path_at_pos()でイベント引数*3に含まれる座標を渡して「None」以外が返った場合にのみメニューをポップアップ(gtk.Menuオブジェクトのメンバ関数popup())する
  • メニュー項目のハンドラでデータを操作し、具体的にはgtk.TreeViewオブジェクトのget_selection()で得られた選択範囲オブジェクトgtk.TreeSelectionオブジェクトメンバ関数get_selected()でデータ(gtk.TreeModel)と編集位置(gtk.TreeIter)を得てからその情報をもとにデータのset_value()でデータを変更

関連記事:

参考URL:

*1:ListStore/TreeStoreのデータを編集するカーソル(キャレット)のようなもの

*2:これを行わないと、ツリービューの項目がないところでコンテキストメニューを開いて処理しようとすることが可能になってしまい、その場合データの編集処理が正しく行えない

*3:このハンドラにはウィジェットとイベントの2つの引数を受け取り、そのメンバ変数xとyがツリービュー内の座標として入る