Python」タグアーカイブ

GtkFlowBox (2)

以前 GtkFlowBox の使い道が解らないとか書いた。
GtkFlowBox | PaePoi

よく考えると Totem のサムネイルに使われていたりする。
そうか、GtkIconView の代わりみたいなものかな。

つまり GtkScrollView を噛ませて画像表示なんかで便利かも。
試しにディレクトリ画像サムネイルを作ってみよう。

#!/usr/bin/env python3

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

NAE_PATH = "/home/sasakima-nao/pic/game/gf/nae_yuki_ssr"

class FlowBoxTest(Gtk.Window):
    """
        Easy GtkIconView
    """
    def __init__(self):
        Gtk.Window.__init__(self)
        # GtkFlowBox
        flowbox = Gtk.FlowBox.new()
        flowbox.set_valign(Gtk.Align.START)
        self.get_all_picture(flowbox)
        #flowbox.set_selection_mode(Gtk.SelectionMode.MULTIPLE)
        scroll = Gtk.ScrolledWindow.new()
        scroll.add(flowbox)
        # self
        self.index = 0
        self.add(scroll)
        self.resize(400, 300)
        self.show_all()

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

    def get_all_picture(self, flowbox):
        """
            Thumbnail JPEG File
        """
        d = Gio.file_new_for_path(NAE_PATH);
        # Get GFileEnumerator
        enum = d.enumerate_children(
                Gio.FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE,
                Gio.FileQueryInfoFlags.NONE)
        for info in enum:
            # info is GFileInfo
            content_type = info.get_content_type()
            if content_type == "image/jpeg":
                name = info.get_name()
                fullpath = "{0}/{1}".format(NAE_PATH, name)
                thumbnail = GdkPixbuf.Pixbuf.new_from_file_at_scale(fullpath, 100, 100, True)
                image = Gtk.Image.new_from_pixbuf(thumbnail)
                flowbox.add(image)

FlowBoxTest()
Gtk.main()

yuki_nae

GtkIconView より圧倒的に簡単だった。
専用のセルレンダラは不要で Widget をそのまま使える。
便利というより簡単で判り易いという使い道みたい。
いや、どんな Widget でも入れられるメリットもある。

でもデータの入れ替えが頻繁な場合は逆に面倒臭くなるなと。
「ドキュメント/ビューアーキテクチャ」とはいったい何だったのか。

ってデータをほとんど入れ替えないならコッチのほうがいいよね。
ということで、優木苗(cv日高里菜)は本当にカワイイです(gf は放置中

Clutter Timeline

今回は Clutter で図形を書き、ついでに動かしてみよう。
年末で超忙しいので更新が遅くてごめん。

Clutter: a beginner’s tutorial | TuxRadar Linux

こんな感じらしい。
少しずつ試してみよう。

別のページで見かけたけどウインドウを閉じるのは hide シグナルのほうがいいみたい。
PyGObject で書く時はこんな感じかな。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Clutter', '1.0')

from gi.repository import Clutter

class ClText(Clutter.Stage):
    def __init__(self):
        Clutter.Stage.__init__(self)
        # ClutterRectangle Green
        rectcolor = Clutter.Color.new(0, 255, 0, 255)
        rect = Clutter.Rectangle.new_with_color(rectcolor)
        rect.set_size(100, 50)
        rect.set_position(50, 20)
        self.add_actor(rect)
        # ClutterRectangle Blue
        rectcolor = Clutter.Color.new(0, 0, 255, 127)
        self.rect = Clutter.Rectangle.new_with_color(rectcolor)
        self.rect.set_size(50, 100)
        self.rect.set_position(40, 30)
        self.add_actor(self.rect)
        # Timeline
        self.rotation = 0
        timeline = Clutter.Timeline.new(500)
        timeline.connect("new-frame", self.on_new_frame)
        self.sorce = Clutter.Score.new();
        self.sorce.set_loop(True)
        self.sorce.append(None, timeline)
        self.sorce.start()
        # self
        windowcolor = Clutter.Color.new(255, 0, 0, 255)
        self.set_color(windowcolor)
        self.set_title("Test")
        self.set_user_resizable(True)
        self.set_size(320, 240)
        self.show_all()

    #def do_delete_event(self, event):
    #    Clutter.main_quit()

    def do_hide(self):
        Clutter.main_quit()

    def on_new_frame(self, num, data):
        self.rotation += 0.3
        self.rect.set_rotation(Clutter.RotateAxis.X_AXIS, self.rotation, 0, 0, 0)

Clutter.init(sys.argv)
ClText()
Clutter.main()

clutter_rotate

CLUTTER_Z_AXIS が Clutter.RotateAxis 内の所で迷ったけど上手くいった。
ここで指定した軸を中心に 3D でグルグル回すことができるんだね。

add_actor の順番どおりで重なっていくようだ。
これを利用すれば簡易 3D アニメーションなら簡単に作れそう。
モデリングは、今は解らない。

そうそう、ClutterScore を self にくっつけるのを忘れないようにね。
こうしないとガベージコレクションで破棄されちゃうので。

Clutter (GNOME)

ClutterGst で動画関連をヤル前に。
Clutter 自体の基本をおさらい、つか完全に忘れているわ筆者は。
その前に Clutter とは。

Projects/Clutter – GNOME Wiki!

GNOME プロジェクトの作っている OpenGL ES ツールキット。
Windows の WPF のようなもの、方向性は違うみたいだけど。
iOS,Mac の Metal といい、今のグラフィックはリッチです。

筆者の MacBook Air は中古の 2011 なので El Capitan の恩恵が無い…
持ち運び用途で買ったんだから別にどうだってイイモン!
Windows は一年以上寝ている、自動更新が恐ろしいので起動すらしたくない。

まあそれはどうでもよくて。
WPF みたいなものなので普通にウインドウが作れます。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Clutter', '1.0')

from gi.repository import Clutter

# initialized
Clutter.init(sys.argv)

def on_delete_event(stage, event):
    Clutter.main_quit()

#stage = Clutter.Stage.get_default() # delete 1.10
stage = Clutter.Stage.new()
stage.connect("delete-event", on_delete_event)
stage.set_title("Hello Clutter")
stage.set_user_resizable(True)
stage.show()
Clutter.main()

clutter_window

GtkWindow とは違い[閉じる]ボタンで Window は閉じる。
けど clutter_main_quit() を呼ばないとプロセスが残るので注意。
よく見ると GtkWindow とは影が違うことに気が付く。
X で描写しているのではないということがこれで判ります。

ウインドウだけではしょうがないので文字列を表示します。
ついでに書き換えできるように。

#!/usr/bin/env python3

import gi, sys
gi.require_version('Clutter', '1.0')

from gi.repository import Clutter

class ClText(Clutter.Stage):
    def __init__(self):
        Clutter.Stage.__init__(self)
        # ClutterText
        edit = Clutter.Text.new()
        edit.set_text("Hello ClutterText")
        edit.set_editable(True)
        self.add_child(edit)
        self.set_key_focus(edit)
        # self
        color = Clutter.Color.new(255, 0, 0, 255)
        self.set_color(color)
        self.set_title("Test")
        self.set_user_resizable(True)
        self.set_size(320, 240)
        self.show_all()

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

Clutter.init(sys.argv)
ClText()
Clutter.main()

clutter_text

GtkWidget の GtkLabel 等とは違い背景透過のようです。
書き換えできるようにしてみたけど GtkEntry のようにはなりません。
クリックでフォーカスが持てないし日本語入力もできない。
まあそういう使い方ではないということでしょう。

Clutter も PyGObject では do_* の接頭子でオーバーライドできるようです。
なんか直感だけでここまで解ったぞと。

WPF と違い部品 Widget は無いけど GtkWindow に乗せられるので問題ない。
いや、スマホの普及を見るとそういう考えがもう古いのかな。

しかし devhelp 3.18 は Ctrl+G で次を検索しないのか?
Ctrl+クリックで別タブもできない、凄く使い辛いんですけど。

ClutterGst 3.0 and GtkHeaderBar

タイトルどおりのモノを作っているので覚書。
実は GtkHeaderBar って Widget を置けるはずがない所に描写している。
なのでこんなことがおこります。

いきなり少し違うけど PyGObject のオーバーライドバグ。

def do_size_allocate(self, allocation):
    pass

ovverride_error

BUG って出るんだね、親切になったもんだ。
connect メソッドなら普通にコネクトできる。

ただ本体の大きさで ClutterActor のサイズを合わせると

class ClPlayer(Gtk.Window):
    def __init__(self):
        Gtk.Window.__init__(self)
        # etc...
        self.connect("size-allocate", self.on_size_allocate)

    def on_size_allocate(self, widget, allocation):
        self.actor.set_width(allocation.width)
        self.actor.set_height(allocation.height)

allocate_size

外枠とタイトルバーの大きさの二倍が加算されてしまうようです。
Box を噛ませてその Box の大きさに合わせてなら問題ないようだ。
GtkHeaderBar さえ使わなければコレでもいいんですけどね。

それと draw シグナルは絶対に処理してはいけない。

def do_draw(self, cr):
    pass

gtkheaderbar_draw

GtkHeaderBar が真っ黒なレゴになってしまいます。
描写処理は Clutter で行うようにする。

そんなこんなで色々困ったことが起こったけどなんとかなった。

#!/usr/bin/env python3

import sys, gi
gi.require_version("Gtk", "3.0")
gi.require_version("ClutterGst", "3.0")
gi.require_version("GtkClutter", "1.0")

from gi.repository import Gtk, Gdk, ClutterGst, GtkClutter, Clutter

# Own Change
URI = "file:///home/sasakima-nao/movie/kawasaki_h2r.mp4"

class ClPlayer(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)
        # Dark Theme
        settings = Gtk.Settings.get_default()
        settings.props.gtk_application_prefer_dark_theme = True
        # GtkHeaderBar
        self.hbar = Gtk.HeaderBar()
        self.hbar.set_show_close_button(True)
        self.set_titlebar(self.hbar)
        # Full Screen Button
        fullbutton = Gtk.Button.new()
        image_full = Gtk.Image.new_from_icon_name("view-fullscreen-symbolic", Gtk.IconSize.MENU)
        fullbutton.set_image(image_full)
        self.hbar.pack_end(fullbutton)
        # new
        self.actor = Clutter.Actor.new()
        self.content = ClutterGst.Aspectratio.new()
        self.player = ClutterGst.Playback.new()
        # set
        self.content.set_player(self.player)
        self.actor.set_content(self.content)
        # add
        embed = GtkClutter.Embed()
        stage = embed.get_stage()
        stage.add_child(self.actor)
        # box
        vbox = Gtk.Box.new(Gtk.Orientation.VERTICAL, 0)
        vbox.pack_start(embed, True, True, 0)
        vbox.connect("size-allocate", self.on_vbox_size_allocate)
        self.add(vbox)
        # play
        self.player.set_uri(URI)
        self.player.set_playing(True)
        # show
        self.show_all()

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

    def on_vbox_size_allocate(self, vbox, allocation):
        """
            Fit a Clutter.Actor
        """
        self.actor.set_width(allocation.width)
        self.actor.set_height(allocation.height)

GtkClutter.init(sys.argv)
ClutterGst.init(sys.argv)

win = ClPlayer()
Gtk.main()

gst_headerbar

GtkHeaderBar とダークテーマが実装できた。
次はシークバーだな、また色々出るんだろうな…
だから楽しいんだYO!

ClutterGst 3.0 with Python

ClutterGst PyGI | PaePoi

以前こんなのを書いたけど

Clutter Gst 3.0.14 Reference Manual: Clutter Gst 3.0.14 Reference Manual

ClutterGst.VideoTexture なんて 3.0 の現在ではもう無い。
今はどうすれば ClutterGst を扱えるのかな?

そういえば Sushi は Gjs だったな。
一応、Sushi は Nautilus にて Space Key でプレビューするアプリね。
Fedora には最初から入っているよ。
だったらコイツのコードを参考にすればいいじゃないか。

sushi_gst

って VideoTexture のまんまや!
Nautilus で動画をプレビューすると緑色でやはり表示できない。

[sushi] viewer: gst: port to ClutterGst 3.0

見つけた、十月にはコミットされているはずなんだけどなぁ。
自力で置き換えして試してみる、Gjs は面倒だから Python で。

#!/usr/bin/env python3

import sys, gi
gi.require_version("Gtk", "3.0")
gi.require_version("ClutterGst", "3.0")
gi.require_version("GtkClutter", "1.0")

from gi.repository import Gtk, Gdk, ClutterGst, GtkClutter, Clutter

class ClPlayer(Gtk.Window):

    def __init__(self):
        Gtk.Window.__init__(self)
        # new
        self.actor = Clutter.Actor.new()
        self.content = ClutterGst.Aspectratio.new()
        self.player = ClutterGst.Playback.new()
        # set
        self.content.set_player(self.player)
        self.actor.set_content(self.content)
        self.actor.show()
        # size
        self.actor.set_width(320)
        self.actor.set_height(180)
        # add
        self.embed = GtkClutter.Embed()
        self.stage = self.embed.get_stage()
        self.stage.add_child(self.actor)
        self.add(self.embed)
        # play
        self.player.set_uri("file:///home/sasakima-nao/movie/kawasaki_h2r.mp4")
        self.player.set_playing(True)
        # show
        self.resize(320, 180)
        self.show_all()


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

#Clutter.init(sys.argv) # Error
GtkClutter.init(sys.argv)
ClutterGst.init(sys.argv)

win = ClPlayer()
Gtk.main()

cluttergst3

思っていたより簡単だった。
よしコレで我が Y901x の GtkHeaderBar 化に取り掛かりできそうだ。
いやまあ、いいかげんに自分で気になってきたので。

実は今まで Ubuntu 環境での Clutter がよく解らないので避けていた。
GNOME プロジェクトの成果物依存から脱却したいココは絶対に導入しないだろうし。

Ubuntu Sushi その1 – Nautilusでプレビューを行うアプリの紹介・Sushiの使い方 – kledgeb

でも Sushi を入れるだけで依存関係から必要な環境がそろうようだ。
だったら Clutter も問題ないか、多分まだ 3.0 じゃない気がするけど。