Python」タグアーカイブ

止まりぎみ

覚書のページ更新を又始めたので blog は止まりぎみになるかも。

テキストや図形を描写する

自分で書いていながら目から鱗。
gyk.gdk.Color() で GdkColor を作る時って 16bit だったのか。
ずっと 8bit (0?255 まで)だと思っていた、やっぱり Windows が長すぎだ。
つーか自分は真っ黒しか使っていなかったので全部ゼロだったわけで。

しかしグラフィック・コンテキストは何でこんなにイッパイあるのだろう?
PAINTSTRUCT がやっている部分も全部コンテキストがやっているということかな。
あんまりよく解っていないまま適当に書いているので気にしないで。
多分 GLib から勉強すれば解るんだろうけど。

なんか自力で解説を作っていると勝手に勉強になって楽しい。

しかし、この blog へのアクセスも今月ついに Vista が Ubuntu を抜いた…
今年から Ubuntu と PyGtk のネタがほとんどなのに世間はそうなのね。

全滅状態のデルヒャァ屋さん達はコッチにいらっしゃい、待っているよ。
ティーエディタの代わりに Pygtksourceview2 もあるよ。
キャイリクスは捨ててね。

GtkTextView って内部は UNICODE なのかな

ちょっと gEdit のプラグインを弄くっていたのでありますが。

13.3. Text Buffers

を見てカーソル位置の GtkTextIter を得て後は多分コレでイケるだろうと作っていた。
上手くいったからイイのだろう、で、面白いことを見つけた。

def on_hoge_activate(self, action):
    # バッファを得る
    view = self._window.get_active_view()
    buf = view.get_buffer()
    try:
        # カーソル位置の GtkTextIter 取得
        pos = buf.get_property("cursor-position")
        it = buf.get_iter_at_offset(pos)
        # 一つ前の文字を得る
        it1 = buf.get_iter_at_offset(pos-1)
        s = it1.get_char()
        if s == "\n":
            return
        # 必要な変数を初期化してループ
        count = pos
        itnext = None
        itend = buf.get_end_iter()
        s1 = ""
        while 1:
            # 次の GtkTextIter を得る
            count += 1
            itnext = buf.get_iter_at_offset(count)
            # EOF
            if itnext.equal(itend):
                break
            # 文字を得て比較
            s1 = itnext.get_char()
            #
            # 表示してみる
            print s1
            #
            if s1 == "\n" or s1 == "。":
                break
            elif s == s1:
                # ここまでの範囲を print
                itnext = buf.get_iter_at_offset(count)
                text = it.get_text(itnext)
                print text
                break
    except Exception, s:
        self.messagebox("%s" % s)

とまあ説明しやすく?書き換えたけどカーソル位置から特定範囲の文字列を得る。
具体的にはカーソルの直前文字と同じ文字を見つけたら抜き出すコードです。

これでイイの?
だって Ubuntu って UTF-8 だよ、アルファベットは 1 バイト、日本語は 2?3 バイト。
というか Windows で文字列を弄くる時に絶対に問題になるんですよ文字コードは。
いやまて、get_char() で char を取り出したって結局はポインタなんだし。
でも漢字とか混ぜると破壊されるわけで、内部はどうなるんだろう?

ということで上のように途中で char を抜いた部分にて print してみることにした。
アルファベットとひらがなカタカナ漢字記号を混ぜた文を作って実験。

atom

あれ、char 配列になっていないじゃん。
_ismbslead みたいなことをしているのか内部で UNICODE 化しているか知らないけど.。
これは楽だ、 gEdit プラグインでは UTF-8 であることを意識しないでいいようです。

どうでもいいけど char って character の略なので「キャラ」と読みますお。

覚書

結局覚書ページの Python 関連は新しく PyGtk として作ることにした。

覚書のページ – L’Isola di Niente

GtkUIManager のほうをさっきまで作っていたけどパッキングの説明のほうが先だよなぁ普通。
ということで書き直ししている、解説する必要があるかどうかよく解らないけど。

こういうまとめを他に誰か、せめて大手が作らないのかなぁ。
今週の週刊アスキーも Ubuntu が載っていたがソフトウエアの紹介だけだし。
Windows と同じことしかしないのなら Linux は使いにくい Windows でしかないのに。
PyGtk もデフォルトで入っているんですよ。

Compiz と DWM は結果が同じ

Y901x 0.1.5 公開しました。

で、前回困っていた動画の背景を黒くする処理ですけど。
メソッドからは塗りつぶしができないので expose-event を処理して GDK で塗った。

def on_aframe_expose(self, widget, event):
    gc = widget.style.fg_gc[gtk.STATE_NORMAL]
    gc.set_foreground(gtk.gdk.Color(0,0,0))
    widget.window.draw_rectangle(gc, True, event.area.x, event.area.y,
                                    event.area.width, event.area.height)

なんか Windows でデバイス・コンテキストを使うのと同じ感覚。
ペンや色の情報はグラフィック・コンテキストが持っているってことですよね。
GTK+ から色の変更をする関数も実はコレをラッピングしているだけなんだろうきっと。
つまりは GDI+ のように、とか考えていたら気になった。

Linux ではこれはどうなるのだ?

ぱぇぽぃ2 ? Blog Archive ? Aero の TextOut

Compiz は言うまでもなく Aero と同じようにタイトルバーが透けたりとかする。
ウインドウをマウスで掴んでグルグルとかでは 3D のほうが CPU 負荷が極端に少ない。
ということは 3D 状態では DWM 有効時と同じ結果になるのであろうか?
2D 描写と 3D 描写でどうなるか今回は円を描写して実験。

#!/usr/bin/env python
#-*- coding:utf-8 -*-

import gtk

class Wm_Paint(gtk.Window):
    """
        ボタンクリックで円を描く最低なコード
    """
    def __init__(self):
        gtk.Window.__init__(self)
        # DrawingArea
        self.drawing_area = gtk.DrawingArea()
        self.drawing_area.set_events(gtk.gdk.EXPOSURE_MASK | 
                                    gtk.gdk.STRUCTURE_MASK | 
                                    gtk.gdk.VISIBILITY_NOTIFY_MASK )
        self.drawing_area.connect("expose-event", self.on_paint)
        # GtkButton
        button = gtk.Button("クリック")
        button.connect("clicked", self.on_button_click)
        # pack
        vbox = gtk.VBox()
        vbox.pack_start(button, False)
        vbox.pack_start(self.drawing_area)
        self.add(vbox)
        # いつもの処理
        self.connect("delete-event", gtk.main_quit)
        self.resize(320, 150)
        self.show_all()

    def on_button_click(self, widget, event=None):
        # GetDC()
        gc = self.drawing_area.style.fg_gc[gtk.STATE_NORMAL]
        # window メンバが GdkWindow
        self.drawing_area.window.draw_arc(
            gc,    # グラフィックコンテキスト
            True,  # 塗りつぶすなら True
            0,     # x 座標
            0,     # y 座標
            self.drawing_area.allocation.width,  # width
            self.drawing_area.allocation.height, # height
            0,     # 開始位置、3時方向の位置から反時計回りに 1/64度刻みで指定
            64*360) # 64 の倍数が描写する円の角度
        #pass

    def on_paint(self, widget, event):
        # 本当はココに書く、てか widget パラメータが使える
        """gc = widget.style.fg_gc[gtk.STATE_NORMAL]
        widget.window.draw_arc(
            gc,
            True,
            0,
            0,
            widget.allocation.width,
            widget.allocation.height,
            0,
            64*360)"""
        pass

if __name__ == "__main__":
    w = Wm_Paint()
    gtk.main()

と、ボタンを押したら Window いっぱいに円を描写するだけの GUI アプリを作る。
コレを起動させ、上に何かウインドウを少し被せてみたら描写した円はどうなるか。
まず Compiz で 3D 有効状態は…やはり Vista の DWM 有効時と同じで何も起こらない。

次に 2D にして同じようにやってみる。

paint1

paint2

あーあ、結局 X も基本描写関連は Windows とそんなに変わらないということだわ。
Compiz の 3D 表示も Vista の DWM と同じ結果になると考えておけばよさそうだ。

3D 描写がもう少し普及したら勘違いしてしまう人が続出しないだろうか?
この手の情報が圧倒的に少ない Linux から開発に入ると理解に苦しむだろうなと思う。
いや、Windows も既にそうなって(略

ついでにコレを試したおかげで widget に allocation メンバがあることを知った。
サイズを得るのに今まで get_allocation() していたけどこのメンバから簡単に得られた。
実践は最大の練習だと本当に思う。

GtkAspectFrame スゲェ

renamedlg プラグインを更新しました、たった一日かよ!
いや、リネーム時に拡張子を選択から省く処理がなんか上手くいったんで。
UNICODE で計算しなきゃいけないのね、てか今まで試していた手段が悪かった。

つーことで。

そろそろ Y901x にアスペクト比変更機能を追加せねばなるまい。
そう思って色々調べてみたので覚書しておきます。

変更させるには2通り手段がある。
この比率で表示してね!と GStreamer に伝えてやってもらう、方法があるかは今は解らない。
もう一つは自分で縦横位置とサイズを計算して配置する、Y901 や Cinema はこの方法。
古い Windows は絶対位置配置なので簡単だったけど Gtk+ のパッキング方法ではどうやるの?

とりあえずデフォルトのソースサイズを無視するだけなら on_sync_message で

imagesink.set_property("force-aspect-ratio", False)

とこの部分を False にすればよいだけだ。

とにかく自力で計算しても配置方法が思いつかないので GStreamer から行う方法を探す。
上の例もあるし XvImageSink から設定できないかな?

xvimagesink

mediactrl.cpp – wxWidgets/src/unix – Code Search

wxWidget には便利そうなラッパークラスがあるんだね。
んー GstPad からサイズ取得はやったし… pixel-aspect-ratio なんてのも抜けるのか。
試しにやってみたら「そんなのネェ」と例外、うーよく解らん。
こんな感じで他も探すも見当たらず,何か関係ありそうな pixel-aspect-ratio で探す。

viewer.py – pitivi-0.10.0/pitivi/ui – Code Search

あ、、、、、、、、、、こんな方法が。

てか GtkAspectFrame なんつークソ便利なものがあったんだ。
早速 force-aspect-ratio を False にして実験じゃ!

aspect

あっさりアスペクト比維持は完成、GtkAspectFrame スゲェ。
しかし背景がボタン色でダサイ、こうしたら背景を黒くする方法はどうするの?
modify_bg は GtkAspectFrame や GtkVBox には効かないみたいだし。
Eye of GNOME みたい、Totem のコードでも漁るか。

てか変更するラジオメニューも作らなきゃ、こりゃ今日中に終わりそうもない。
つーことでプラグインのみ更新、さて続きをやります。