PyGTKでツリービューにリストのデータ(ListStore)を表示(ボタンからデータの順番を入れ替える・コード例)
「PyGTKでツリービューにリストのデータ(ListStore)を表示(ボタンからデータの順番を入れ替える・メモ)」の続き。
コード例
「上へ」の処理を行うハンドラは「PyGTKでツリービューにリストのデータ(ListStore)を表示(ボタンからデータの順番を入れ替える・メモ)」で2種類の方法を扱ったのでそれぞれの方法で2つ用意した。シグナル接続部分で片方コメントにしているので、その部分を入れ替えればもう1つのほうが使用される。
単独選択モード時
#! /usr/bin/python # -*- encoding: utf-8 -*- import sys try: import pygtk pygtk.require('2.0') except: pass try: import gtk except: print >> sys.stderr, 'Error: PyGTK is not installed' sys.exit(1) class TreeViewWithColumn(gtk.TreeView): """ コラムを含んだツリービュー """ ( COLUMN_STR, ) = range(1) def __init__(self, *args, **kwargs): gtk.TreeView.__init__(self, *args, **kwargs) # コラムの設定 self.col_str = gtk.TreeViewColumn('Data', gtk.CellRendererText(), text=self.COLUMN_STR) # コラムを追加 self.append_column(self.col_str) class MainWindow(gtk.Window): """ メインウィンドウ """ # 直接ウィンドウとは関係ないが、データは便宜上ここに用意しておくことにする data = \ [ ('AAA',), ('BBB',), ('CCC',), ('DDD',), ('EEE',), ] def __init__(self, *args, **kwargs): gtk.Window.__init__(self, *args, **kwargs) # ショートカットキー(アクセラレータ) self.accelgroup = gtk.AccelGroup() self.add_accel_group(self.accelgroup) # メニュー項目 self.item_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accelgroup) self.menu_file = gtk.Menu() self.menu_file.add(self.item_quit) self.item_file = gtk.MenuItem('_File') self.item_file.set_submenu(self.menu_file) self.menubar = gtk.MenuBar() self.menubar.append(self.item_file) # ツリービュー self.treeview = TreeViewWithColumn(model=gtk.ListStore(str)) self.treeview.set_rules_hint(True) # ツリービュー向けスクロールウィンドウ self.sw = gtk.ScrolledWindow() self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.sw.add(self.treeview) # ボタン self.button_top = gtk.Button(stock=gtk.STOCK_GOTO_TOP) self.button_up = gtk.Button(stock=gtk.STOCK_GO_UP) self.button_down = gtk.Button(stock=gtk.STOCK_GO_DOWN) self.button_bottom = gtk.Button(stock=gtk.STOCK_GOTO_BOTTOM) # レイアウト用コンテナ self.vbox_btn = gtk.VBox() # ボタンを縦に並べる self.vbox_btn.pack_start(self.button_top) self.vbox_btn.pack_start(self.button_up) self.vbox_btn.pack_start(self.button_down) self.vbox_btn.pack_start(self.button_bottom) self.hbox = gtk.HBox() # ツリービューとボタン群 self.hbox.pack_start(self.sw) self.hbox.pack_start(self.vbox_btn, expand=False, fill=False) self.vbox = gtk.VBox() # 全体 self.vbox.pack_start(self.menubar, expand=False, fill=False) self.vbox.pack_start(self.hbox) # シグナル self.connect('delete_event', gtk.main_quit) self.item_quit.connect('activate', gtk.main_quit) self.button_top.connect('clicked', self.on_button_top_clicked) self.button_up.connect('clicked', self.on_button_up_clicked) #self.button_up.connect('clicked', self.on_button_up_clicked2) self.button_down.connect('clicked', self.on_button_down_clicked) self.button_bottom.connect('clicked', self.on_button_bottom_clicked) # データ追加 for rec in self.data: self.treeview.get_model().append(rec) # ウィンドウ self.add(self.vbox) self.set_size_request(350, 300) def on_button_top_clicked(self, widget): """ 選択項目を一番上に移動 """ # 現在選択されている項目を取り出す (model, iter_current) = self.treeview.get_selection().get_selected() # move_after()の2番目の引数をNoneにすると一番上に移動する model.move_after(iter_current, None) def on_button_up_clicked(self, widget): """ 選択項目を1つ上に移動 """ (model, iter_current) = self.treeview.get_selection().get_selected() # 先頭の項目を示しているか選択項目がない場合は何もしない if iter_current \ and model.get_path(iter_current) != model.get_path(model.get_iter_first()): # 選択項目の1つ上(手前)の項目を探す # 逆方向にはたどれないので先頭から順にたどる iter = model.get_iter_first() while True: iter_next = model.iter_next(iter) # 1つ手前が選択項目と同じ位置であればそこで止まる if model.get_path(iter_next) == model.get_path(iter_current): break iter = iter_next.copy() model.move_before(iter_current, iter) # このときのiterが1つ手前 def on_button_up_clicked2(self, widget): """ 選択項目を1つ上に移動・その2 """ (model, iter_current) = self.treeview.get_selection().get_selected() if iter_current \ and model.get_path(iter_current) != model.get_path(model.get_iter_first()): # ツリーパスのタプルの要素(ListStoreでは1階層だけなので0番のみ)を # 1引くことで手前の項目のツリーパスを得てTreeIterに変換する方法もある iter = model.get_iter(model.get_path(iter_current)[0] - 1) model.move_before(iter_current, iter) def on_button_down_clicked(self, widget): """ 選択項目を1つ下に移動 """ (model, iter_current) = self.treeview.get_selection().get_selected() # 最後の項目を示しているか選択項目がない場合は何もしない if iter_current: iter_next = model.iter_next(iter_current) if iter_next: model.move_after(iter_current, iter_next) def on_button_bottom_clicked(self, widget): """ 選択項目を一番下に移動 """ (model, iter_current) = self.treeview.get_selection().get_selected() # move_before()の2番目の引数をNoneにすると一番下に移動する model.move_before(iter_current, None) class PyGTKTreeViewListStoreTest5: """ リストを用いたツリービューのテスト5 """ def main(self): """ アプリケーションのメイン処理 """ win = MainWindow() win.show_all() gtk.main() if __name__ == '__main__': app = PyGTKTreeViewListStoreTest5() app.main()
複数選択モードで1つの項目が選択されたときに移動できるようにする場合
複数個の項目が選択されたときには何もせず、1つの項目が選択されたときに限り上のように移動できるようになっている。
#! /usr/bin/python # -*- encoding: utf-8 -*- import sys try: import pygtk pygtk.require('2.0') except: pass try: import gtk except: print >> sys.stderr, 'Error: PyGTK is not installed' sys.exit(1) class TreeViewWithColumn(gtk.TreeView): """ コラムを含んだツリービュー """ ( COLUMN_STR, ) = range(1) def __init__(self, *args, **kwargs): gtk.TreeView.__init__(self, *args, **kwargs) # コラムの設定 self.col_str = gtk.TreeViewColumn('Data', gtk.CellRendererText(), text=self.COLUMN_STR) # コラムを追加 self.append_column(self.col_str) # 複数行選択を可能にする self.get_selection().set_mode(gtk.SELECTION_MULTIPLE) class MainWindow(gtk.Window): """ メインウィンドウ """ # 直接ウィンドウとは関係ないが、データは便宜上ここに用意しておくことにする data = \ [ ('AAA',), ('BBB',), ('CCC',), ('DDD',), ('EEE',), ] def __init__(self, *args, **kwargs): gtk.Window.__init__(self, *args, **kwargs) # ショートカットキー(アクセラレータ) self.accelgroup = gtk.AccelGroup() self.add_accel_group(self.accelgroup) # メニュー項目 self.item_quit = gtk.ImageMenuItem(gtk.STOCK_QUIT, self.accelgroup) self.menu_file = gtk.Menu() self.menu_file.add(self.item_quit) self.item_file = gtk.MenuItem('_File') self.item_file.set_submenu(self.menu_file) self.menubar = gtk.MenuBar() self.menubar.append(self.item_file) # ツリービュー self.treeview = TreeViewWithColumn(model=gtk.ListStore(str)) self.treeview.set_rules_hint(True) # ツリービュー向けスクロールウィンドウ self.sw = gtk.ScrolledWindow() self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) self.sw.add(self.treeview) # ボタン self.button_top = gtk.Button(stock=gtk.STOCK_GOTO_TOP) self.button_up = gtk.Button(stock=gtk.STOCK_GO_UP) self.button_down = gtk.Button(stock=gtk.STOCK_GO_DOWN) self.button_bottom = gtk.Button(stock=gtk.STOCK_GOTO_BOTTOM) # レイアウト用コンテナ self.vbox_btn = gtk.VBox() # ボタンを縦に並べる self.vbox_btn.pack_start(self.button_top) self.vbox_btn.pack_start(self.button_up) self.vbox_btn.pack_start(self.button_down) self.vbox_btn.pack_start(self.button_bottom) self.hbox = gtk.HBox() # ツリービューとボタン群 self.hbox.pack_start(self.sw) self.hbox.pack_start(self.vbox_btn, expand=False, fill=False) self.vbox = gtk.VBox() # 全体 self.vbox.pack_start(self.menubar, expand=False, fill=False) self.vbox.pack_start(self.hbox) # シグナル self.connect('delete_event', gtk.main_quit) self.item_quit.connect('activate', gtk.main_quit) self.button_top.connect('clicked', self.on_button_top_clicked) self.button_up.connect('clicked', self.on_button_up_clicked) #self.button_up.connect('clicked', self.on_button_up_clicked2) self.button_down.connect('clicked', self.on_button_down_clicked) self.button_bottom.connect('clicked', self.on_button_bottom_clicked) # データ追加 for rec in self.data: self.treeview.get_model().append(rec) # ウィンドウ self.add(self.vbox) self.set_size_request(350, 300) def on_button_top_clicked(self, widget): """ 選択項目を一番上に移動 """ # 現在選択されている項目を取り出す (model, selected) = self.treeview.get_selection().get_selected_rows() iters = [model.get_iter(path) for path in selected] if len(iters) == 1: # move_after()の2番目の引数をNoneにすると一番上に移動する model.move_after(iters[0], None) def on_button_up_clicked(self, widget): """ 選択項目を1つ上に移動 """ # 現在選択されている項目を取り出す (model, selected) = self.treeview.get_selection().get_selected_rows() iters = [model.get_iter(path) for path in selected] if len(iters) == 1: # 先頭の項目を示しているか選択項目がない場合は何もしない if iters[0] \ and model.get_path(iters[0]) != model.get_path(model.get_iter_first()): # 選択項目の1つ上(手前)の項目を探す # 逆方向にはたどれないので先頭から順にたどる iter = model.get_iter_first() while True: iter_next = model.iter_next(iter) # 1つ手前が選択項目と同じ位置であればそこで止まる if model.get_path(iter_next) == model.get_path(iters[0]): break iter = iter_next.copy() model.move_before(iters[0], iter) # このときのiterが1つ手前 def on_button_up_clicked2(self, widget): """ 選択項目を1つ上に移動・その2 """ # 現在選択されている項目を取り出す (model, selected) = self.treeview.get_selection().get_selected_rows() iters = [model.get_iter(path) for path in selected] if len(iters) == 1: if iters[0] \ and model.get_path(iters[0]) != model.get_path(model.get_iter_first()): # ツリーパスのタプルの要素(ListStoreでは1階層だけなので0番のみ)を # 1引くことで手前の項目のツリーパスを得てTreeIterに変換する方法もある iter = model.get_iter(model.get_path(iters[0])[0] - 1) model.move_before(iters[0], iter) def on_button_down_clicked(self, widget): """ 選択項目を1つ下に移動 """ # 現在選択されている項目を取り出す (model, selected) = self.treeview.get_selection().get_selected_rows() iters = [model.get_iter(path) for path in selected] if len(iters) == 1: # 最後の項目を示しているか選択項目がない場合は何もしない if iters[0]: iter_next = model.iter_next(iters[0]) if iter_next: model.move_after(iters[0], iter_next) def on_button_bottom_clicked(self, widget): """ 選択項目を一番下に移動 """ # 現在選択されている項目を取り出す (model, selected) = self.treeview.get_selection().get_selected_rows() iters = [model.get_iter(path) for path in selected] if len(iters) == 1: # move_before()の2番目の引数をNoneにすると一番下に移動する model.move_before(iters[0], None) class PyGTKTreeViewListStoreTest5Multi: """ リストを用いたツリービューのテスト5-2 複数選択モードで単数選択時に移動できるようにしたもの """ def main(self): """ アプリケーションのメイン処理 """ win = MainWindow() win.show_all() gtk.main() if __name__ == '__main__': app = PyGTKTreeViewListStoreTest5Multi() app.main()
メインウィンドウオブジェクトの書き方の微調整について
この記事の内容とは関係がないが、最近までgtk.main()を呼ぶ前のメインウィンドウオブジェクトを
win = MainWindow()
のように生成しながらそのオブジェクト(win)を使用していない書き方になっていたのでメンバ関数show_all()をここで呼ぶことにした。過去の記事の例についても修正を行った。
関連記事:
- PyGTKでツリービューにリストのデータ(ListStore)を表示(概要とメモ)
- PyGTKでツリービューにリストのデータ(ListStore)を表示(簡単な例)
- PyGTKでツリービューにリストのデータ(ListStore)を表示(データを変更可能にする・メモ)
- PyGTKでツリービューにリストのデータ(ListStore)を表示(データを変更可能にする・コード例)
- PyGTKでツリービューに階層を持ったデータ(TreeStore)を表示
- PyGTKでツリービューにリストのデータ(ListStore)を表示(項目をGUI上で追加/削除、データの並べ替えや入れ替えなど)
- PyGTKでツリービューにリストのデータ(ListStore)を表示(モデルの内容を取り出す)
- PyGTKでツリービューにリストのデータ(ListStore)を表示(ボタンからデータの順番を入れ替える・メモ)