GTK+」タグアーカイブ

GTK4: GridView

GTK4 は TreeView の他に IconView も廃止なんだね。
GlidView が後継のようで、Nautilus 43 のもコレっぽい。

Gtk.GridView

GtkDemo にサンプルが無い、自力で試してみよう。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Adw', '1')
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio, GObject, Adw

class Items(GObject.Object):
    def __init__(self, items):
        self.items = items
        super(Items, self).__init__()

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        # Set Adwaita Style
        manager = Adw.StyleManager.get_default()
        manager.set_color_scheme(Adw.ColorScheme.DEFAULT)
        # init
        Gtk.ApplicationWindow.__init__(self, application=app, title='GridView')
        #
        model = Gio.ListStore()
        model.append(Items(['OM SYSTEM', 'pen']))
        model.append(Items(['LUMIX', 'GH6']))
        #
        #sel_model = Gtk.SingleSelection(model=model)
        sel_model = Gtk.MultiSelection(model=model)
        #
        factory1 = Gtk.SignalListItemFactory()
        factory1.connect('setup', self.on_listitem_setup)
        factory1.connect('bind', self.on_listitem_bind1)
        #
        listnview = Gtk.GridView(model=sel_model, factory=factory1)
        listnview.connect('activate', self.on_columnview_activate)
        #
        self.set_child(listnview)
        self.set_default_size(200, 200)

    def on_listitem_setup(self, factory, item):
        label = Gtk.Label(label='oman')
        item.set_child(label)

    def on_listitem_bind1(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[0]

    def on_columnview_activate(self, list, pos):
        print(1)

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.omsystem.om1')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

app = TestApplication()
app.run(sys.argv)

grid

ちょっと驚いた、という不正確な日本語での表現にしておくけどナルホドなぁ。
完全に GTK4 の ListView と同様の手順、いや当然狙ってそうしたのだろう。
Box を使ってレイアウトすれば Nautilus 43 の見た目にはできるね。

ついでに。
init 直後に書いた Adw 用途の命令って GTK4 全部に影響するのね。
上記のまま全体の DarkMode にしてみたら。

grid

あぁ macOS や iOS の DarkMode は開発者に丸投げだったもんな。
GNOME はこうしたんですね、いや勘違いかもしれないけれど。

GTK4: ListView and ColumnView

前回は少し勘違いをしてました。
GtkListView を GtkListBox だと思い込んでいた、反省。

ListView は GTK4 で追加された新規のリストビューでした。
ただし 1 カラム限定、それいったい何に使うんだろう?は置いておいて。
複数カラムにするには ColumnView を使う、ということらしい。

Gtk.ListView

Gtk.ColumnView

ListView のほうにはサンプルコードがある。
でも create_application_list って関数何よ、これじゃよくワカンネェよ。
model は GListModel 派生なので Gio.ListStore にすればいいようです。

ただ ListStore には GObject.Object 派生しか append できないみたいなんですが。
GObject.TYPE_STRING 等を指定しても例外、丁度いい class も見つからない。
PyGObject の制限なのかどうかは知らないけど文字列のリストを入れたいんですけど。
ということでちょっぴり手抜きな Item class を作ってサンプルコードを書いてみた。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio, GObject

class Items(GObject.Object):
    def __init__(self, items):
        self.items = items
        super(Items, self).__init__()

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title='ListView')
        #
        model = Gio.ListStore()
        model.append(Items(['OM SYSTEM', 'pen']))
        model.append(Items(['LUMIX', 'GH6']))
        #
        sel_model = Gtk.SingleSelection(model=model)
        #
        factory1 = Gtk.SignalListItemFactory()
        factory1.connect('setup', self.on_listitem_setup)
        factory1.connect('bind', self.on_listitem_bind1)
        #
        listnview = Gtk.ListView(model=sel_model, factory=factory1)
        listnview.connect('activate', self.on_columnview_activate)
        #
        self.set_child(listnview)

    def on_listitem_setup(self, factory, item):
        label = Gtk.Label(label='sexxx')
        item.set_child(label)

    def on_listitem_bind1(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[0]

    def on_columnview_activate(self, list, pos):
        print(1)

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.omsystem.pen')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

app = TestApplication()
app.run(sys.argv)

表示はレンダラではなく Widget を使うようになりました。

リストビューらしい複数カラム表示にするなら ColumnView を使う。
ほとんど同じ手段です、ListView は単なるベースクラスなのかな。
カラムの数だけ ColumnViewColumn を追加して使います。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gio, GObject

class Items(GObject.Object):
    def __init__(self, items):
        self.items = items
        super(Items, self).__init__()

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        Gtk.ApplicationWindow.__init__(self, application=app, title='ColumnView')
        #
        model = Gio.ListStore()
        model.append(Items(['OM SYSTEM', 'pen']))
        model.append(Items(['LUMIX', 'GH6']))
        #
        sel_model = Gtk.SingleSelection(model=model)
        #
        factory1 = Gtk.SignalListItemFactory()
        factory1.connect('setup', self.on_listitem_setup)
        factory1.connect('bind', self.on_listitem_bind1)
        #
        factory2 = Gtk.SignalListItemFactory()
        factory2.connect('setup', self.on_listitem_setup)
        factory2.connect('bind', self.on_listitem_bind2)
        #
        columnview = Gtk.ColumnView(model=sel_model)
        columnview.connect('activate', self.on_columnview_activate)
        #
        column1 = Gtk.ColumnViewColumn(title='Camera', factory=factory1)
        columnview.append_column(column1)
        column2 = Gtk.ColumnViewColumn(title='Model', factory=factory2)
        columnview.append_column(column2)
        #
        self.set_child(columnview)

    def on_listitem_setup(self, factory, item):
        label = Gtk.Label(label='sexxx')
        item.set_child(label)

    def on_listitem_bind1(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[0]

    def on_listitem_bind2(self, factory, item):
        l = item.get_item()
        label = item.get_child()
        label.props.label = l.items[1]

    def on_columnview_activate(self, list, pos):
        print(1)

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.omsystem.om1')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

app = TestApplication()
app.run(sys.argv)

で。

column

解り辛いですよね、でも表示が Widget なので GTK3 以前よりはマシ。
チェックボックスや画像を入れたくなっても Widget の知識でやれますんで。
以前はレンダラという専用のものを使う必要がありました。

Gtk(PyGObject) Tips | レンダラ – Paepoi

しかし Nautilus 43 みたくモダンな選択表示にするにはどうすればいいんだろう?
メッセージが Adw.ToastOverlay になったので Adw だと思ったけど無いんだよな。
それは今後の課題ということで、最後に。

jyoubitaki

本日はジョウビタキが綺麗に撮れました。

GTK4: GtkInscription

そういえば GTK4 に GtkInscription が追加されるんだっけ。
Gtk.Inscription

特殊用途に使う Widget なので通常は GtkLabel を使ってくれ。
ということらしいけど、つまり文字列がはみ出すラベルってことね。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class TestWindow(Gtk.ApplicationWindow):
    def __init__(self, app):
        try:
            Gtk.ApplicationWindow.__init__(self, application=app)
            # Label and Inscription
            label = Gtk.Label(label='文字列に合わせて拡大されます')
            inscription = Gtk.Inscription(text='文字列に合わせて拡大されません、はみ出します')
            # pack
            vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
            vbox.append(label)
            vbox.append(inscription)
            self.set_child(vbox)
        except Exception as e:
            print(e, file=sys.stderr)
            app.quit()

class TestApplication(Gtk.Application):
    def __init__(self):
        Gtk.Application.__init__(self, application_id='org.omsystem.pen')

    def do_activate(self):
        w = TestWindow(self)
        w.present()

app = TestApplication()
app.run(sys.argv)

inscription

なんだそれだけだったのか。
カラム部分とかコンテナが拡大されたら困る場所に使うってことですね。

ところで、GTK4 のドキュメントが親切になっている。
deprecated つまり廃止予定を明確にしてくれています。

Gtk ? 4.0

TreeView がやっと廃止、マウス必須な時代遅れ UI ですからね。
TreeStore だけでなく ListStore も廃止、リストビュー表示もできなくなる。
一応、GtkListView は昔ながらのリストビューではなくスマホの設定画面みたいな UI です。
あれ、Nautilus 43 のリストビュー表示は?
と思うかもだけどアレは ColumnView なんですね、いや今知ったんだけど。

伴ってあの解り辛いレンダラ関連が全面廃止。
あぁ、それで Inscription という Widget が必要になったということか。

ダイアログ関連を全面見直し。
いやそれ何故 GTK4 の最初でやらなかったのか。

ComboBox も廃止。いや困るだろと思ったけど Popover があったわ。
Nautilus 43 の設定もそうなっていた、はよ移行しろってことですね。

StyleContext も廃止。
CSS の適用は今後どうするんだろう?調べなきゃ。

GTK4 の方向性が見えてきましたね。
次は GtkColumnView あたりを調べてみるかな。

GTK4: TextView

Fedora 36 には adwaita-1-demo が最初から入っていると以前書いた。
GTK Demo(gtk4-demo) は gnome-softwere から入手できるので入れてみる。

demo

なんか勝手に 4 ヶも入ってしまったけどまあいい。
こっちはソースが直接見られるので解りやすいですね。

demo

TextView は文字列中に Widget を入れることができるのか。
よし PyGObject でやってみよう。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk

class Win(Gtk.ApplicationWindow):
    '''
        GTK4: TextView in Button
    '''
    def __init__(self, a):
        Gtk.ApplicationWindow.__init__(self, application=a)
        # Button
        button = Gtk.Button(label='Button')
        button.connect('clicked', self.on_button_clicked)
        # TextView
        self.view = Gtk.TextView()
        buf = self.view.get_buffer()
        it = buf.get_start_iter()
        buf.insert(it, 'This')
        anchor = buf.create_child_anchor(it)
        self.view.add_child_at_anchor(button, anchor)
        buf.insert(it, 'click!')
        # pack
        sw = Gtk.ScrolledWindow()
        sw.set_child(self.view)
        self.set_child(sw)
        self.set_default_size(400, 300)

    def on_button_clicked(self, button):
        with open(__file__) as f:
            s = f.read()
            self.view.props.buffer.set_text(s)

def app_activate(a):
    w = Win(a)
    w.present()

app = Gtk.Application()
app.connect('activate', app_activate)
app.run()

demo

マジでできた、必要性は疑問だけど。
他 tag の利用方法なんかもコレで解るね。
GTK4 はこんな感じで勉強すればいいと思います。

ところで SVG エディタなんだけど。
Vectornator という Mac のアプリを使うことにしました。
M1 Mac なのに Raw 現像専用じゃもったいない。

GTK4: Clipboard

ビックリ、Fedora 36 に何故か Python2 が入っていた!

gimp

Gimp にくっ付いてきたのか、PyGtk まで。
てか Gimp で使う Python って 2 のままなのかよ。

そりゃ Gimp 自体が GTK2 だし。
GTK って今は GNU Tool Kit という意味だし。
もしかして開発止まっている?
別の SVG エディタを探すか、mac で探したほうがいいような。

ということで平日は軽く GTK4 でクリップボード。

#!/usr/bin/env python3

import gi
gi.require_version('Gtk', '4.0')
from gi.repository import Gtk, Gdk

class Win(Gtk.ApplicationWindow):
    '''
        GTK4: Clipboard Copy and Peast
    '''
    def __init__(self, a):
        Gtk.ApplicationWindow.__init__(self, application=a)
        # Copy Button
        cbutton = Gtk.Button(label='Copy')
        cbutton.connect('clicked', self.on_button_c_clicked)
        # Paste Button
        pbutton = Gtk.Button(label='Paste')
        pbutton.connect('clicked', self.on_button_p_clicked)
        # Entry
        self.entry = Gtk.Entry()
        #pack
        box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
        box.append(cbutton)
        box.append(pbutton)
        box.append(self.entry)
        self.set_child(box)

    def on_button_c_clicked(self, button):
        # entry text
        text = self.entry.get_buffer().get_text()
        clipboard = button.get_clipboard()
        clipboard.set(text)

    def on_button_p_clicked(self, button):
        clipboard = button.get_clipboard()
        clipboard.read_text_async(None, self.on_read_text_async)

    def on_read_text_async(self, clipboard, res):
        text = clipboard.read_text_finish(res)
        self.entry.get_buffer().set_text(text, -1)

def app_activate(a):
    w = Win(a)
    w.present()

app = Gtk.Application()
app.connect('activate', app_activate)
app.run()

文字列以外はあまり使わないと思うので文字列特化。

最初 init で文字列を入れようとしたけど全然駄目だった。
クリップボードは init を抜けてから操作しましょう。

GtkClipboard が GdkClipboard に代わっているけど GTK3 とほぼ同じ。
get_clipboard はどの Widget でもいいみたい、変な感じだけど。
set_text がバインドされていなくて戸惑うけど実はコレでいい。
読み込みは非同期にしないと上手くいかないみたい。

WordPress が 6.0 になった動作確認書き込みでした。