GtkListBox

GTK+ 3.10 で追加された Widget に GtkListBox がある。

Windows でいうところの LISTBOX とは全然違って GtkBox のサブクラス。
GtkListStore のデータを表示するのではなく GtkWidget を普通に表示する。
その詰め込んだ GtkWidget を選択可能にする、ということみたい。

何に利用すれば便利なのかよく解らない。
自力で色々試しても GtkTreeView で別にイイじゃんと思ってしまう。
GtkTreeView の代わりに使うとデータバインドができなくて不便なだけ。

使い道が解らないのも悔しいのでもっと調べてみる。
GNOME(GTK+) 3.10 で導入されたのだからどこかで使っているはず。
どうやらユニバーサルアクセスや検索の設定ダイアログで使っているっぽい。

univ

久々にこのダイアログを見たけどこんなに変わっていたのか。
そういえば Android スマートフォンの設定画面がこんな感じだ。
ListBox という名前に惑わされて想像力が偏っていたみたい。
よし使い道はなんとなく理解した、次はサンプルコードを探そう。

https://github.com/bratsche/gtk-/blob/master/tests/testlist.c

良さげなのを見つけたけど gtk_main_quit(); 処理が無いのは何故だろう。
海外を探すとこんなのが多いよね、ささやかなイジワルなのでしょうか。
端末からテスト起動して Ctrl+C で終了するだけだから気にしていないだけかも。

とりあえず上記を参考にユニバーサルアクセスダイアログっぽいのを作ってみる。
もちろん Python で、C は面倒臭いもん。

#!/usr/bin/env python3

from gi.repository import Gtk

CSS = '''
GtkListBoxRow {
    border-width: 1px;
    border-style: outset;
    border-color: lightgray;
}'''

DATA = ["YAMAHA", "HONDA", "KAWASAKI", "SUZUKI"]

class Row(Gtk.ListBoxRow):
    def __init__(self, label):
        Gtk.ListBoxRow.__init__(self)
        self.label = Gtk.Label(label)
        self.switch = Gtk.Switch()
        hbox = Gtk.Box.new(Gtk.Orientation.HORIZONTAL, 0)
        hbox.pack_start(self.label, False, False, 0)
        hbox.pack_end(self.switch, False, False, 0)
        self.add(hbox)
        self.show_all()

class ListWin(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        # GtkCssProvider
        provider = Gtk.CssProvider()
        provider.load_from_data(CSS.encode("utf-8"))
        # GtkStyleContext
        Gtk.StyleContext.add_provider_for_screen(
                self.get_screen(),
                provider,
                Gtk.STYLE_PROVIDER_PRIORITY_USER)
        # ListBox
        listbox = Gtk.ListBox()
        listbox.connect("row-activated", self.on_listbox_row_activated)
        for data in DATA:
            row = Row(data)
            listbox.add(row)
        # Selection
        combobox = Gtk.ComboBoxText.new()
        combobox.append_text("Gtk.SelectionMode.NONE")
        combobox.append_text("Gtk.SelectionMode.SINGLE")
        combobox.set_active(listbox.get_selection_mode())
        combobox.connect("changed", self.on_combobox_changed, listbox)
        # CheckButton
        checkbutton = Gtk.CheckButton.new_with_label("Single Click Mode")
        checkbutton.set_active(listbox.get_activate_on_single_click())
        checkbutton.connect("clicked", self.on_checkbutton_clicked, listbox)
        # Pack
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 20)
        vbox.pack_start(listbox, False, False, 0)
        vbox.pack_start(combobox, False, False, 0)
        vbox.pack_start(checkbutton, False, False, 0)
        self.add(vbox)
        self.set_border_width(10)
        self.show_all()

    def do_delete_event(self, event):
        Gtk.main_quit()

    def on_listbox_row_activated(self, listbox, row, data=None):
        b = row.switch.get_active()
        row.switch.set_active(not b)

    def on_combobox_changed(self, combo, listbox):
        b = combo.get_active()
        listbox.set_selection_mode(b)

    def on_checkbutton_clicked(self, button, listbox):
        b = button.get_active()
        listbox.set_activate_on_single_click(b)

ListWin()
Gtk.main()

listtest

データを生で管理するのではなく構造体やクラスにするといいみたい。
ソート機能はたとえばよくクリックするものをカウントして順に並べるとかに使えそう。
GtkBox の各ペーンに選択機能とクリック感知機能を追加したと考えればよさげ。
名前に惑わされなくなると結構使い道が思い付く、不思議なものです。