L'Isola di Niente
L'Isola di Niente » PyGObject Tips » レンダラ

レンダラ

GtkCellRenderer は GtkTreeView, GtkComboBox でデータをどのように表示させるかを指定する Widget です。
直接使うことはありません、派生された以下を利用します。

レンダラプロパティ
GtkCellRendererTextstrtext
+----GtkCellRendererAccelstrtext
+----GtkCellRendererCombostrtext
+----GtkCellRendererSpininttext
GtkCellRendererPixbufGdkPixbuf or strpixbuf or stock-id
GtkCellRendererProgressintvalue
GtkCellRendererSpinnerinttext
GtkCellRendererToggleboolactive

GtkCellRendererText

GtkCellRendererText は名前のとおり文字列を表示するレンダラです。

基本的なものですので一般例はツリービュー、リストビューを見てもらうとしてここでは編集手段を。
editable プロパティを True にして edited シグナルを利用すれば編集可能。
データモデル (GtkTreeStore, GtkListStore) のデータを書き換える必要があります。
そのレンダラを使用したコラムはデータ追加を行ってもすべて書き換え可能になります。

edited ハンドラで PyGI の場合は以下のようにすれば GtkTreeModel のデータを変更できる。
コメント内に devhelp の正式な手段もいれておきましたので参照ください。
#!/usr/bin/env python3

from gi.repository import Gtk

class CellRendererTextWin(Gtk.Window):
    """
        Editable GtkCellRendererText
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer = Gtk.CellRendererText.new()
        renderer.props.editable = True
        # Column
        column = Gtk.TreeViewColumn("Column Title", renderer, text=0)
        # ListStore
        store = Gtk.ListStore.new([str])
        tree = Gtk.TreeView.new_with_model(store)
        tree.append_column(column)
        # Data
        for s in ["Edit", "Edit"]:
            store.append([s])
        # Button
        button = Gtk.Button.new_with_label("Renderer Append")
        # Signal
        renderer.connect("edited", self.on_edited, store)
        button.connect("clicked", self.on_button_clicked, store)
        # pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(tree, False, False, 0)
        vbox.pack_start(button, False, False, 0)
        self.add(vbox)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_edited(self, renderer, path, new_text, store):
        """
            # C Like
            it = store.get_iter_from_string(path)
            store.set_value(it, 0, new_text)
        """
        store[path][0] = new_text
        

    def on_button_clicked(self, widget, store):
        store.append(["Edit"])

CellRendererTextWin()
Gtk.main()

img/gtk_cellrenderertext.png

GtkCellRendererAccel

GtkCellRendererAccel は GNOME のキーボードショートカット設定等に使われているもの。
キーボードアクセラレータ関連に特化したウイジェットのようです。

editable プロパティを真にしてレンダラ部をクリックすると accel-edited シグナルが発行される。
このパラメータを利用して GtkAccelMap の変更を行うといったことができます。

gtk_accelerator_name 関数を利用して文字列に変換表示するのが一般的かと。
#!/usr/bin/env python3

from gi.repository import Gtk, Gdk

class CellRendererAccelWin(Gtk.Window):
    """
        Change the keyboard accelerator
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer_text = Gtk.CellRendererText.new()
        renderer_accel = Gtk.CellRendererAccel.new()
        renderer_accel.props.editable = True
        # Column
        column_text = Gtk.TreeViewColumn("Scooter", renderer_text, text=0)
        column_accel = Gtk.TreeViewColumn("Accel key", renderer_accel, text=1)
        # ListStore
        self.store = Gtk.ListStore.new([str, str])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_text)
        tree.append_column(column_accel)
        # Data
        self.store.append(["SYM", "q"])
        self.store.append(["KYMCO", "<Shift>a"])
        self.store.append(["PGO", "<Super>b"])
        # Button
        entry = Gtk.Label("Change the keyboard accelerator")
        # Signal
        renderer_accel.connect("accel-edited", self.on_accel_edited)
        # pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(tree, False, False, 0)
        vbox.pack_start(entry, False, False, 0)
        self.add(vbox)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_accel_edited(self, accel, path_string, accel_key, accel_mods, hardware_keycode, data=None):
        self.store[path_string][1] = Gtk.accelerator_name(accel_key, accel_mods)

CellRendererAccelWin()
Gtk.main()

img/gtk_cellreadereaccel.png

GtkCellRendererCombo

GtkCellRendererCombo はその名のとおりコンボボックスです。
GtkTreeModel に入れたデータから選択する GtkComboBox と同様に利用できます。

プロパティの editable を True にして model を指定すればドロップ選択が可能になる。
has-entry が True なら直書きもできる、text-column は指定した model のデータ位置。
又 edited シグナルも利用できるようです。
#!/usr/bin/env python3

from gi.repository import Gtk, Gdk

class CellRendererComboWin(Gtk.Window):
    """
        Like GtkComboBox
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Data
        store_items = Gtk.ListStore.new([str])
        eur = ["Aprilia", "Ducati", "BMW", "Triumph"]
        for item in eur:
            store_items.append([item])
        # Renderer
        renderer_text = Gtk.CellRendererText.new()
        renderer_combo = Gtk.CellRendererCombo.new()
        renderer_combo.props.editable = True
        renderer_combo.props.model = store_items
        renderer_combo.props.has_entry = False
        renderer_combo.props.text_column = 0
        # Column
        column_text = Gtk.TreeViewColumn("Motor Cycle", renderer_text, text=0)
        column_combo = Gtk.TreeViewColumn("Select", renderer_combo, text=1)
        # ListStore
        self.store = Gtk.ListStore.new([str, str])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_text)
        tree.append_column(column_combo)
        # Data
        self.store.append(["Good", "Ducati"])
        self.store.append(["Bad", "BMW"])
        # Button
        entry = Gtk.Label("Select the Item")
        # Signal
        renderer_combo.connect("changed", self.on_changed, store_items)
        # pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(tree, False, False, 0)
        vbox.pack_start(entry, False, False, 0)
        self.add(vbox)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_changed(self, combo, path_string, new_iter, model):
        self.store[path_string][1] = model.get_value(new_iter, 0)

CellRendererComboWin()
Gtk.main()

img/gtk_cellrenderercombo.png

GtkCellRendererSpin

GtkCellRendererSpin はその名のとおりスピンボタンです。
GtkAdjustment を adjustment プロパティに入れて利用します。

TreeModel で使用するデータは当然 int ですがレンダラは text なので注意しましょう。
専用のシグナルは用意されていません、edited シグナルを利用します。
#!/usr/bin/env python3

from gi.repository import Gtk, Gdk

class CellRendererSpinWin(Gtk.Window):
    """
        Like GtkSpinButton
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer_text = Gtk.CellRendererText.new()
        renderer_spin = Gtk.CellRendererSpin.new()
        renderer_spin.props.editable = True
        renderer_spin.props.adjustment = Gtk.Adjustment(0, 50, 2000, 1, 100, 0)
        # Column
        column_text = Gtk.TreeViewColumn("Motor Cycle", renderer_text, text=0)
        column_spin = Gtk.TreeViewColumn("cc", renderer_spin, text=1)
        # ListStore
        self.store = Gtk.ListStore.new([str, int])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_text)
        tree.append_column(column_spin)
        # Data
        self.store.append(["CB500X", 471])
        self.store.append(["Street Triple", 675])
        # Button
        entry = Gtk.Label("change")
        # Signal
        renderer_spin.connect("edited", self.on_edited)
        # pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(tree, False, False, 0)
        vbox.pack_start(entry, False, False, 0)
        self.add(vbox)
        self.set_title("Test")
        self.resize(200, 1)
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_edited(self, renderer, path, new_text, data=None):
        """
            # or
            self.store[path][1] = int(new_text)
        """
        self.store[path][1] = renderer.props.digits

CellRendererSpinWin()
Gtk.main()

img/gtk_cellrendererspin.png

GtkCellRendererPixbuf

GtkCellRendererPixbuf はその名のとおり画像を表示するレンダラです。

ストックアイコンを表示する場合は stock-id プロパティ指定で文字列を。
自分で用意した画像を表示する場合は pixbuf プロパティ指定で GdkPixbuf を。

pixbuf-expander-closed, pixbuf-expander-open は is-expand プロパティが真の時に使う。
ツリー表示を開いた閉じたで画像を変更したい場合なんかに利用します。

GDK_TYPE_PIXBUF の GType が Python から見つからなかったけど以下でイケました。
#!/usr/bin/env python3

from gi.repository import Gtk, GdkPixbuf

SQUARE = [
"16 16 2 1",
" 	c #000000",
".	c #FFFFFF",
"                ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
" .............. ",
"                "]

TRIANGLE = [
"16 16 2 1",
" 	c #000000",
".	c #FFFFFF",
" ...............",
"  ..............",
" . .............",
" .. ............",
" ... ...........",
" .... ..........",
" ..... .........",
" ...... ........",
" ....... .......",
" ........ ......",
" ......... .....",
" .......... ....",
" ........... ...",
" ............ ..",
" ............. .",
"                "]

class CellRendererPixbufWin(Gtk.Window):
    """
        Picture Renderer
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer_stock = Gtk.CellRendererPixbuf.new()
        renderer_pixbuf = Gtk.CellRendererPixbuf.new()
        # Column
        column_stock = Gtk.TreeViewColumn("stock", renderer_stock, stock_id=0)
        column_pixbuf = Gtk.TreeViewColumn("pixbuf", renderer_pixbuf, pixbuf=1)
        # ListStore
        self.store = Gtk.ListStore.new([str, GdkPixbuf.Pixbuf.__gtype__])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_stock)
        tree.append_column(column_pixbuf)
        # Create Pixbuf
        pixbuf1 = GdkPixbuf.Pixbuf.new_from_xpm_data(SQUARE)
        pixbuf2 = GdkPixbuf.Pixbuf.new_from_xpm_data(TRIANGLE)
        # Data
        self.store.append([Gtk.STOCK_OPEN, pixbuf1])
        self.store.append([Gtk.STOCK_CLOSE, pixbuf2])
        #
        self.add(tree)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

CellRendererPixbufWin()
Gtk.main()

img/gtk_cellrendererpixbuf.png

GtkCellRendererProgress

GtkCellRendererProgress はその名のとおりプログレスバーです。
Value プロパティに 0...100 の値で何パーセント進んだかを入れて利用します。
#!/usr/bin/env python3

from gi.repository import Gtk, GObject

class CellRendererProgressWin(Gtk.Window):
    """
        Progress Bar
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer_progress = Gtk.CellRendererProgress.new()
        # Column
        column_progress = Gtk.TreeViewColumn("progress", renderer_progress, value=0)
        # ListStore
        self.store = Gtk.ListStore.new([int])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_progress)
        # Data
        it = self.store.append([0])
        #
        self.add(tree)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()
        # Timer
        self.timeout_id = GObject.timeout_add(100, self.on_timeout, it)

    def on_timeout(self, it):
        new_value = self.store[it][0] + 1
        if new_value > 100:
            return False
        self.store[it][0] = new_value
        return True

CellRendererProgressWin()
Gtk.main()

img/gtk_cellrendererprogress.png

GtkCellRendererSpinner

GtkCellRendererSpinner はいわゆるウエイト表示。
昔の Windows では砂時計、今はクルクル回るアレです。

active プロパティで表示し pulse プロパティで回り具合を調節します。
#!/usr/bin/env python3

from gi.repository import Gtk, GObject

class CellRendererSpinnerWin(Gtk.Window):
    """
        Wait
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer_spinner = Gtk.CellRendererSpinner.new()
        renderer_spinner.props.active = True
        # Column
        column_spinner = Gtk.TreeViewColumn("spinner", renderer_spinner, pulse=0)
        # ListStore
        self.store = Gtk.ListStore.new([int])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_spinner)
        # Data
        it = self.store.append([0])
        #
        self.add(tree)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()
        # Timer
        self.timeout_id = GObject.timeout_add(20, self.on_timeout, it)

    def on_timeout(self, it):
        new_value = self.store[it][0] + 1
        if new_value > 100:
            return False
        self.store[it][0] = new_value
        return True

CellRendererSpinnerWin()
Gtk.main()

img/gtk_cellrendererspinner.png

GtkCellRendererToggle

GtkCellRendererToggle はその名のとおりチェックボックスです。

チェックボックスをクリックすると toggled シグナルが発生しますが表示は変わりません。
チェック状態を変更したい場合は以下のように自力で行う必要があります。
#!/usr/bin/env python3

from gi.repository import Gtk, GdkPixbuf

class CellRendererToggleWin(Gtk.Window):
    """
        Toggle Button
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # Renderer
        renderer_toggle = Gtk.CellRendererToggle.new()
        renderer_text = Gtk.CellRendererText.new()
        # Column
        column_toggle = Gtk.TreeViewColumn("Toggle", renderer_toggle, active=0)
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=1)
        # ListStore
        self.store = Gtk.ListStore.new([bool, str])
        tree = Gtk.TreeView.new_with_model(self.store)
        tree.append_column(column_toggle)
        tree.append_column(column_text)
        # Data
        self.store.append([True, "Motor Cycle"])
        self.store.append([False, "Car"])
        # Signal
        renderer_toggle.connect("toggled", self.on_toggled)
        #
        self.add(tree)
        self.set_title("Test")
        self.connect("delete-event", Gtk.main_quit)
        self.show_all()

    def on_toggled(self, widget, path, data=None):
        self.store[path][0] = not self.store[path][0]

CellRendererToggleWin()
Gtk.main()
img/gtk_cellrenderertoggle.png
Copyright(C) sasakima-nao All rights reserved 2002 --- 2017.