Python GTK+3 チュートリアル

13. セルレンダラ

翻訳して勉強するGtkチュートリアル第13章 CellRenderers です。ようやく、このチュートリアルの後半に差し掛かりました。


Gtk.CellRenderer ウィジェットは Gtk.TreeView Gtk.ComboBox などのウィジェット内の情報を表示するために使われます。これらのウィジェットは関連するウィジェットと密接に連携して動作し、非常に強力で、大量のデータをさまざまな方法で表示するための多くの設定オプションを備えています。

Gtk.CellRenderer ウィジェットは7つあり、それぞれの目的に合わせて使うことができます。

  • Gtk.CellRendererText
  • Gtk.CellRendererToggle
  • Gtk.CellRendererPixbuf
  • Gtk.CellRendererCombo
  • Gtk.CellRendererProgress
  • Gtk.CellRendererSpinner
  • Gtk.CellRendererSpin
  • Gtk.CellRendererAccel

13.1. CellRendererText

Gtk.CellRendererText は、プロパティによって提供されるフォント、色、スタイルの情報を用いて、与えられたテキストをセル内にレンダリングします。長過ぎるテキストは"ellipsize" プロパティで楕円化が許可されている場合は、楕円化されます。

デフォルトでは、Gtk.CellRendererText ウィジェット内のテキストは編集可能ではありません。これは “editable” プロパティの値を True に設定することで変更できます。

13.1.1. 例

動作テスト - Gtk.CellRendererText
# tut13-01.py
# CellRendererText サンプル

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class CellRendererTextWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererText Example")

        self.set_default_size(400, 150)

        self.liststore = Gtk.ListStore(str, str)
        self.liststore.append(["Fedora", "https://fedoraproject.org/"])
        self.liststore.append(["Slackware", "http://www.slackware.com/"])
        self.liststore.append(["Sidux", "http://sidux.com/"])

        treeview = Gtk.TreeView(model=self.liststore)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
        treeview.append_column(column_text)

        renderer_editabletext = Gtk.CellRendererText()
        renderer_editabletext.set_property("editable", True)

        column_editabletext = Gtk.TreeViewColumn(
            "Editable Text", renderer_editabletext, text=1
        )
        treeview.append_column(column_editabletext)

        renderer_editabletext.connect("edited", self.text_edited)

        self.add(treeview)

    def text_edited(self, widget, path, text):
        self.liststore[path][1] = text


win = CellRendererTextWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

13.2. CellRendererToggle

Gtk.CellRendererToggle はセル内のトグルボタンをレンダリングします。ボタンは “radio” プロパティに応じて、ラジオボタンかチェックボタンとして描画されます。アクティベートされると、“toggled” シグナルを発します。

Gtk.CellRendererToggle はアクティブと非アクティブの2つの状態を持つことができるので、セルレンダラの “active” プロパティをモデルのブール値にバインドして、チェックボタンにモデルの状態を反映させたい場合が多いでしょう。

13.2.1. 例

動作テスト - CellRendererToggle
# tut13-01.py
# CellRendererToggle サンプル

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class CellRendererToggleWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererToggle Example")

        self.set_default_size(400, 150)

        self.liststore = Gtk.ListStore(str, bool, bool)
        self.liststore.append(["Debian", False, True])
        self.liststore.append(["OpenSuse", True, False])
        self.liststore.append(["Fedora", False, False])

        treeview = Gtk.TreeView(model=self.liststore)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
        treeview.append_column(column_text)

        renderer_toggle = Gtk.CellRendererToggle()
        renderer_toggle.connect("toggled", self.on_cell_toggled)

        column_toggle = Gtk.TreeViewColumn("Toggle", renderer_toggle, active=1)
        treeview.append_column(column_toggle)

        renderer_radio = Gtk.CellRendererToggle()
        renderer_radio.set_radio(True)
        renderer_radio.connect("toggled", self.on_cell_radio_toggled)

        column_radio = Gtk.TreeViewColumn("Radio", renderer_radio, active=2)
        treeview.append_column(column_radio)

        self.add(treeview)

    def on_cell_toggled(self, widget, path):
        self.liststore[path][1] = not self.liststore[path][1]

    def on_cell_radio_toggled(self, widget, path):
        selected_path = Gtk.TreePath(path)
        for row in self.liststore:
            row[2] = row.path == selected_path


win = CellRendererToggleWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

13.3. CellRendererPixbuf

Gtk.CellRendererPixbuf を使ってセル内の画像をレンダリングすることができます。これにより、与えられた Gdk.Pixbuf ( “pixbuf” プロパティで設定) あるいは名前付きアイコン ( “icon-name” プロパティで設定) のいずれかをレンダリングできます。

13.3.1. 例

動作テスト - CellRendererPixbuf
# tut13-03.py
# CellRendererPixbuf サンプル

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class CellRendererPixbufWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererPixbuf Example")

        self.set_default_size(400, 150)

        self.liststore = Gtk.ListStore(str, str)
        self.liststore.append(["New", "document-new"])
        self.liststore.append(["Open", "document-open"])
        self.liststore.append(["Save", "document-save"])

        treeview = Gtk.TreeView(model=self.liststore)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
        treeview.append_column(column_text)

        renderer_pixbuf = Gtk.CellRendererPixbuf()

        column_pixbuf = Gtk.TreeViewColumn("Image", renderer_pixbuf, icon_name=1)
        treeview.append_column(column_pixbuf)

        self.add(treeview)


win = CellRendererPixbufWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

13.4. CellRendererCombo

Gtk.CellRendererCombo は、 Gtk.CellRendererText と同じように派生元のセル内のテキストをレンダリングします。しかし CellRendererText がテキストを編集するためのシンプルなエントリを提供しているのに対し、Gtk.CellRendererCombo はテキストを編集するための Gtk.ComboBox ウィジェットを提供しています。コンボボックスに表示される値は、“model” プロパティで指定された Gtk.TreeModel から取得します。

Combo-cell-rendererは、コンボボックスにtext-cell-rendererを追加し、その “text-column” プロパティで指定された列を表示するように設定します。

Gtk.CellRendererCombo は2つのモードで動作します。“has-entry” プロパティの値によって、関連する Gtk.Entry ウィジェットの有無に関わらず使うことができます。

13.4.1. 例

動作テスト - CellRendererCombo
# tut13-04.py
# CellRendererCombo サンプル

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class CellRendererComboWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererCombo Example")

        self.set_default_size(400, 150)

        liststore_manufacturers = Gtk.ListStore(str)
        manufacturers = ["Sony", "LG", "Panasonic", "Toshiba", "Nokia", "Samsung"]
        for item in manufacturers:
            liststore_manufacturers.append([item])

        self.liststore_hardware = Gtk.ListStore(str, str)
        self.liststore_hardware.append(["Television", "Samsung"])
        self.liststore_hardware.append(["Mobile Phone", "LG"])
        self.liststore_hardware.append(["DVD Player", "Sony"])

        treeview = Gtk.TreeView(model=self.liststore_hardware)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
        treeview.append_column(column_text)

        renderer_combo = Gtk.CellRendererCombo()
        renderer_combo.set_property("editable", True)
        renderer_combo.set_property("model", liststore_manufacturers)
        renderer_combo.set_property("text-column", 0)
        renderer_combo.set_property("has-entry", False)
        renderer_combo.connect("edited", self.on_combo_changed)

        column_combo = Gtk.TreeViewColumn("Combo", renderer_combo, text=1)
        treeview.append_column(column_combo)

        self.add(treeview)

    def on_combo_changed(self, widget, path, text):
        self.liststore_hardware[path][1] = text


win = CellRendererComboWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

13.5. CellRendererProgress

Gtk.CellRendererProgress は数値をセル内のプログレスバーとしてレンダリングします。プログレスバーの上にテキストを表示することもできます。

“value” プロパティを変更することで、プログレスバーのパーセンテージ値を変更できます。Gtk.ProgressBar と同様に、“value “プロパティの代わりに “pulse “プロパティをインクリメント(変数を1増加)することでアクティビティモードを有効にすることができます。

13.5.1. 例

動作テスト - CellRendererProgress
# tut13-05.py
# CellRendererProgress サンプル

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk, GLib


class CellRendererProgressWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererProgress Example")

        self.set_default_size(400, 150)

        self.liststore = Gtk.ListStore(str, int, bool)
        self.current_iter = self.liststore.append(["Sabayon", 0, False])
        self.liststore.append(["Zenwalk", 0, False])
        self.liststore.append(["SimplyMepis", 0, False])

        treeview = Gtk.TreeView(model=self.liststore)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Text", renderer_text, text=0)
        treeview.append_column(column_text)

        renderer_progress = Gtk.CellRendererProgress()
        column_progress = Gtk.TreeViewColumn(
            "Progress", renderer_progress, value=1, inverted=2
        )
        treeview.append_column(column_progress)

        renderer_toggle = Gtk.CellRendererToggle()
        renderer_toggle.connect("toggled", self.on_inverted_toggled)
        column_toggle = Gtk.TreeViewColumn("Inverted", renderer_toggle, active=2)
        treeview.append_column(column_toggle)

        self.add(treeview)

        self.timeout_id = GLib.timeout_add(100, self.on_timeout, None)

    def on_inverted_toggled(self, widget, path):
        self.liststore[path][2] = not self.liststore[path][2]

    def on_timeout(self, user_data):
        new_value = self.liststore[self.current_iter][1] + 1
        if new_value > 100:
            self.current_iter = self.liststore.iter_next(self.current_iter)
            if self.current_iter is None:
                self.reset_model()
            new_value = self.liststore[self.current_iter][1] + 1

        self.liststore[self.current_iter][1] = new_value
        return True

    def reset_model(self):
        for row in self.liststore:
            row[1] = 0
        self.current_iter = self.liststore.get_iter_first()


win = CellRendererProgressWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()

13.6. CellRendererSpin

Gtk.CellRendererSpin は、Gtk.CellRendererText から派生したもので、セル内のテキストをレンダリングします。しかし CellRendererText がテキストを編集するためのシンプルなエントリを提供するのに対して、Gtk.CellRendererSpin Gtk.SpinButton ウィジェットを提供します。もちろん、これはテキストが浮動小数点数として解析可能でなければならないことを意味します。

スピンボタンの範囲は、セルレンダラの調整プロパティから取得され、明示的に設定することも、セルレンダラのすべてのプロパティと同様にツリーモデルのカラムにマッピングすることもできます。Gtk.CellRendererSpin には、上昇率と表示桁数のプロパティもあります。

13.6.1. 例

動作テスト - CellRendererSpin
# tut13-06.py
# CellRendererSpin サンプル

import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk


class CellRendererSpinWindow(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self, title="CellRendererSpin Example")

        self.set_default_size(400, 150)

        self.liststore = Gtk.ListStore(str, int)
        self.liststore.append(["Oranges", 5])
        self.liststore.append(["Apples", 4])
        self.liststore.append(["Bananas", 2])

        treeview = Gtk.TreeView(model=self.liststore)

        renderer_text = Gtk.CellRendererText()
        column_text = Gtk.TreeViewColumn("Fruit", renderer_text, text=0)
        treeview.append_column(column_text)

        renderer_spin = Gtk.CellRendererSpin()
        renderer_spin.connect("edited", self.on_amount_edited)
        renderer_spin.set_property("editable", True)

        adjustment = Gtk.Adjustment(0, 0, 100, 1, 10, 0)
        renderer_spin.set_property("adjustment", adjustment)

        column_spin = Gtk.TreeViewColumn("Amount", renderer_spin, text=1)
        treeview.append_column(column_spin)

        self.add(treeview)

    def on_amount_edited(self, widget, path, value):
        self.liststore[path][1] = int(value)


win = CellRendererSpinWindow()
win.connect("destroy", Gtk.main_quit)
win.show_all()
Gtk.main()


関連記事