グラフィックコンテキストの色はもっと簡単に変更できた

グラフィックコンテキストの色はもっと簡単に変更できた

set_rgb_fg_color(gtk.gdk.color_parse("red"))

で expose-event の中でも CPU 負荷もなくアッサリ変更できる。
GTK+ はデフォルトがダブルバッファリングなのでチラツキも全然無い。
チビッと試しに書いてみた。

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

import gtk
import pango

ui_str = """<ui>
    <menubar name="MenuBar">
        <menu action="File">
            <menuitem action="quit"/>
        </menu>
    </menubar>
</ui>"""

class GC_Test(gtk.Window):
    """
        GC で色々な表示を試してみる
        Font を変更するには pango を使う必要があるのね
    """
    def __init__(self):
        # お約束
        gtk.Window.__init__(self)
        # GtkUIManager 作成
        uimanager = gtk.UIManager()
        # GtkAccelGroup を取り出し self にて突っ込む
        accelgroup = uimanager.get_accel_group()
        self.add_accel_group(accelgroup)
        # GtkActionGroup 作成
        actiongroup = gtk.ActionGroup("nandemoii")
        # GtkActionEntry の list を作成して GtkUIManager に突っ込む
        e = [("quit", gtk.STOCK_QUIT, "終了(_Q)", "<Control>Q", "さいなら", self.on_quit),
            ("File", None, "ファイル(_F)") ]
        actiongroup.add_actions(e)
        # GtkUIManager の更新
        uimanager.insert_action_group(actiongroup, 0)
        uimanager.add_ui_from_string(ui_str)
        # メニューを取り出す
        menubar = uimanager.get_widget("/MenuBar")
        # パッキング
        statusbar = gtk.Statusbar()
        drawingarea = gtk.DrawingArea()
        #
        # ダブルバッファリング無効状態にしたいならココを有効にしてね
        #drawingarea.unset_flags(gtk.DOUBLE_BUFFERED)
        #
        # WM_PAINT のようなものを発生させる
        drawingarea.connect("expose-event", self.on_drawingarea_expose)
        # パッキング
        vbox = gtk.VBox()
        vbox.pack_start(menubar, False)
        vbox.pack_start(drawingarea)
        vbox.pack_end(statusbar, False)
        self.add(vbox)
        # いつもの処理
        self.set_title("gc_test")
        self.connect("delete-event", self.on_quit)
        self.resize(320,240)
        self.show_all()

    def on_quit(self, widget, event=None):
        gtk.main_quit()

    def on_drawingarea_expose(self, widget, event=None):
        # グラフィック・コンテキストを得る
        gc = widget.style.fg_gc[gtk.STATE_NORMAL]
        # 赤くする
        gc.set_rgb_fg_color(gtk.gdk.color_parse("red"))
        # 自分のサイズ取得
        d_width = widget.allocation.width
        d_height = widget.allocation.height
        # 塗りつぶす
        widget.window.draw_rectangle(gc, True, 0, 0, d_width, d_height)
        # 緑色にする
        gc.set_rgb_fg_color(gtk.gdk.color_parse("green"))
        # Font を大きくして文字列描写
        font_desc = pango.FontDescription('Monospace 32')
        layout = widget.create_pango_layout ("まっかっか")
        layout.set_font_description(font_desc)
        widget.window.draw_layout(gc, 10, 20, layout)
        # 青色にする
        gc.set_rgb_fg_color(gtk.gdk.color_parse("blue"))
        # 線
        widget.window.draw_line(gc, 0, 0, d_width, d_height)

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

makkakka

これでどこをどう書けばどういう表示になるか簡単に解る…と思う。
2D にしてグリグリウインドウサイズを変更するとチラツキが無いのも理解できる。
ダブルバッファリングを無効にする方法もついでに。

PyGtk って何でもやれて面白いですよ。

keywords

今月も mono が多い…そんなに Linux で C# なんかやりたいの?
キッカケだけならそれでいいけど、私がそうだったし。

IronPython2.6beta を試す

IronPython – Release: 2.6 Beta 1

DevHawk – IronPython 2.6 Beta 1

どうやら IronPython 2.6 には ctypes が追加されるみたいなんだが。
面白そうなので落としてみる。

ipy26b1

なんかイッパイファイルが増えているなぁ。
とりあえずインタラクティブシェルで試してみるか。

errer

だめヤン、やりかたが悪いのかな?

そういえば IronPython 2.0 では普通の ctypes も import できなかったっけか。
なんか os モジュールでエラーになってしまう、こっちも試してみよう。

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

import sys

# CPython 2.6 を自分がインストールしている場所
sys.path.insert(0, "C:\\Python26\\lib")
import ctypes

MB_OK = 0
MB_OKCANCEL = 0x00000001
IDOK = 1

dll = ctypes.windll.user32
res = dll.MessageBoxW(0, u"どちらかを押してください", u"たいとる", MB_OKCANCEL)

if res == IDOK:
    dll.MessageBoxW(0, u"OK を押しました", u"りざると", MB_OK)
else:
    dll.MessageBoxW(0, u"キャンセルを押しました", u"りざると", MB_OK)

IronPython 2.6 で実効。
間違えて CPython で動かしちゃダメよ。

cmd

おぉエラーにならなくなっている。
つまり普通の ctypes を使えばいいだけってことなのかな?
今は解らない、もっと情報が上がるのを待とう。

os.path.join() は理由がある

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

import os

# コレだとカレントディレクトリの場合は空文字になる
print os.path.dirname(__file__) + "/put.txt"
# 正確に行う方法
print os.path.abspath(os.path.dirname(__file__)) + "/put.txt"

output

今頃知った。
ま、実用上は絶対パスにしなくても得に問題は…ある!

このままだとファイル名の先頭がパス区切り文字になる場合があるってことじゃないの。
os.path.join() で合体しろと強調する理由はコレだったのね。
単純にパス区切り文字を振り分けというくだらない理由だけじゃなくて。

それよりこうやって Linux と Windows での表示を比べると…
せめて PowerShell だけでも Windows の標準カレントディレクトリをなんとかしてほしいわ。
変更できるのは解っているけど最初から C:\ユーザー名 でいいじゃないか。

GtkMenu.popup で左右両ボタン認識は簡単だった

今日はこのページを作っていたのだが

ドロップされた画像を表示させる

ここで今まで右クリックメニューを出すコードに右ボタンを指定を忘れていたことに気がつく。
ごまかす為に以前のページを書き換えていたのだが

if event.button == 3:
    self.popup_menu.popup(None, None, None, event.button, event.time)

event.button を何故二回も使っていたのだろう。
Devhelp を改めて見直すと popup の四番目引数はボタンの指定だ。
つまりメニューアイテムの選択を確定させるボタンということである。

あぁだからポップアップの入れ子は右ボタン(つまり 3 )しか反応しないのか。
ここに左を示す 1 を含めた値…int なんだから 4 になって全然違うボタンの指定になってまうし…
だったらゼロにするとどうなる?

if event.button == 3:
    self.popup_menu.popup(None, None, None, 0, event.time)

コレであんなに悩んだ入れ子メニュークリックでの左右両ボタンでの確定がアッサリ解決…
何故こんな単純なことに今まで気がつかなかったのだろうか…
これだけで Y901x を更新するのもアレなので今度まとめてにしよう。

IronPython は親クラスの __init__() がいらない

.NET Framework について何を今頃知ったのだが…
StreamWriter はエンコード指定をしなければ BOM 無し UTF-8 になるらしい。

ま、元々 Opera は付けていたのでSeeme for Linux の場合は問題無いのだが。
UTF-8 を指定すると BOM が付いて困ることがあったので理解しておかなきゃ。

てなわけで実際そうなのか実験コードを IronPython と WPF で書いてみたのだが…
突っ込みどころ満載になってしまった。

# -*- coding: UTF-8 -*-

import clr
#import nt

# 最小限下記ライブラリ(dll)が必要
clr.AddReferenceByPartialName("PresentationCore")
clr.AddReferenceByPartialName("PresentationFramework")
clr.AddReferenceByPartialName("WindowsBase")

from System import *
from System.Windows import *
from System.Windows.Controls import *
from System.Windows.Media import *
from System.IO import *

class UTF8Writer(Window):
    """
        System.IO.StreamWriter の実験
        何も指定せず書き込みすると BOM 無し UTF-8 になる
    """
    def __init__(self):
        """
            IronPython では Window.__init__(self) はいらないようです
            書いても例外にならないけど
        """
        self.Title = "UTF-8 書き込みの実験"
        self.textbox = TextBox()
        self.textbox.TextWrapping = TextWrapping.Wrap
        self.textbox.AcceptsReturn = True
        self.textbox.FontFamily = FontFamily("MS ゴシック")
        # ボタン作成及びクリックハンドラ登録
        button = Button()
        button.Content = "書き込み"
        button.Click += self.onClick
        # StackPanel だとサイズ連動ができないので DocPanel を使う
        # けど何故 static なんだ!
        DockPanel.SetDock(button, Dock.Top)
        # レイアウタを作成してこれらをセット
        dp = DockPanel()
        dp.Children.Add(button)
        dp.Children.Add(self.textbox)
        # レイアウタを Window にセット
        self.Content = dp
        self.Width = 320
        self.Height = 240

    def onClick(self, sender, e):
        """
            流石に以下はできない、nt.path が無い…
            sw = StreamWriter(nt.path.dirname( __file__ ) + "\\put.txt")
        """
        sw = StreamWriter("put.txt")
        try:
            buf = self.textbox.Text
            sw.Write(buf)
        except Exception, ex:
            MessageBox.Show(ex.Message)
        finally:
            sw.Close()

class UTF8WriterCopy(UTF8Writer):
        """
            自作クラスでもコレでイケる、なんか変
        """
        pass

if __name__=="__main__":
    a = Application()
    a.Run(UTF8WriterCopy())

writer

なるほど、BOM 無し UTF-8 になることは確認できた。
XP 用の WPF にはフォントにアンチエイリアスを掛けるのをヤメてくんないかなぁ。

つーかナンジャコレ。

今まで気がつかなかったよ、親クラスの __init__ はいらないんだ。
Python じゃ無いヤン、コンストラクタになっているってことだよね。
それとも CLI の仕様なのかな?

更に気がつかなかったけど DockPanel へのレイアウトは static なんだ。
XAML で書いていると普通に見えるけどコードで書くと違和感がたっぷり。
GTK+ とは違ってパッキング情報は子オブジェクト側が持っているということか。

やりにくいのでコンテナの継承をして pack_start みたいなのを作ろうかな?
と思ったけど要求が StackPanel と DockPanel に分かれているし無理っぽい。
WPF は XAML で書くのを強要しているってことだろう多分。

os モジュールのクローン nt を作ったのなら nt.path も用意してくれよみたいな。

まだ気がついていないところってありそうだ。
IronPython は Python クローンだと思って書くと痛い目に遭いそう。
しかし例外の書き方なんかはまったく同じだ、逆に変な気分になった。