GTK+ はキーの長押しを認識できないようで

Y901 というアプリは上下矢印キーの長押しでリスト選択位置の移動のみを行っていた。
キーを離し WM_KEYUP メッセージを捕まえた所で選択位置のファイルを再生開始していた。
当然 Y901x でもそうしたいわけだ。

しかし…とにかくコレを動かして上下どちらかの矢印キーを押しっ放しにしてみる。

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

import gtk

class KeyUpDown(gtk.Window):
    def __init__(self):
        gtk.Window.__init__(self)
        self.tv = gtk.TextView()
        sw = gtk.ScrolledWindow()
        sw.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
        sw.add(self.tv)
        self.add(sw)
        # GDK イベントの有効化を行っておく
        self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK)
        self.connect("key_press_event", self.on_key_press)
        self.connect("key_release_event", self.on_key_release)
        self.connect("delete-event", gtk.main_quit)
        self.resize(300, 400)
        self.show_all()

    def on_key_press(self, widget, event):
        if event.keyval == 65362 or event.keyval == 65364:
            buf = self.tv.get_buffer()
            s = "押した\n"
            it = buf.get_end_iter()
            buf.insert(it, s, len(s))

    def on_key_release(self, widget, event):
        if event.keyval == 65362 or event.keyval == 65364:
            buf = self.tv.get_buffer()
            s = "離した\n"
            it = buf.get_end_iter()
            buf.insert(it, s, len(s))

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

updown

つまり key_press_event シグナルは必ず key_release_event シグナルと交互に発生する。
Windows のように WM_KEYDOWN イベントのみが起こるというわけではないようだ。
キーを離し WM_KEYUP メッセージを捕まえるように key_release_event を…

できない!

まいった、何か方法を見つけるまで今までどうり一つ上下移動のみにするしかない。
つーかこの現実が解るまで「あれぇ?なんで???」と苦しんだ私であった。

それとラジオメニューとトグルボタンは UIManager から同期させられないっぽい。
しかたがないのでリピート用のトグルボタンを排除するという暴挙で解決!
パッと見て状態が解ればいいんだからステータスバーに表示、これが私のクオリティ。

追記、長押し判定する方法がありました
GTK+ Cancel Long Keypress | PaePoi

PopupMenu と MouseGesture の同居に困った

PopupMenu と MouseGesture の同居に困った

GTK+ のアプリは基本的にマウスの右ボタンダウンでポップアップメニューが出る。
しかしもはや Linux 標準アプリになった Firefox はボタンアップで出る。
マウスジェスチャ機能があるからだ、当然 Opera も同様。

ということで違和感が無い人も多いと思うので遠慮なくボタンアップでポップアップを実装
…しようとしたんだけど完全な振り分け方法を思いつけなくてココだけで半日使った。

popup

まあとにかくここは上手くいったと思う、やはりデカいので入れ子にしたのは妥協だ。

しかし困った、入れ子のメニューは何故か右クリック時しかシグナルを吐いてくれない。
入れ子にしていないメニューは左クリックでもキチンとシグナルを吐くのにどういうこと?

GTK+ 製である Firefox はどうだ…ってコイツの右メニューには入れ子が無かったわ。
Totem で試すとしっかり右クリックで入れ子にも反応する、ますます解らなくなったぞ。
実装方法が変わると違うかも…何か方法があるはずだがよく解らない。

そうそう、試しに右ボタンダウンで出すように実装したら普通にシグナルを吐く。
どういうことかはバックアップしているのを試すと解ると思う。

それと画面 W クリックでフルスクリーンだが。
右メニューやダイアログを出しフォーカスが移ると GNOME メニューがコンニチハ。
これはどうすれば防げるか、Totem はそんなの出ないんだよなぁ…

gtk.gdk.Window

GDK にも何故か fullscreen メソッドがあるんだがもう何がなんだか解らん。
試しに入れてみたけど違いが無いみたいだけど。

せっかくリピートメニューと RadioAction を作ったのに実装する時間がなかったわい。
バックアップを置いておきますんで、くそぉ進まなかった。

y901x-buckup2.zip

GtkDialog 上の GtkEntry で Enter して OK に

GtkDialog 上の GtkEntry で Enter したら OK ということにしたい。
あれ?なんかウイジェットのデフォルト機能ではできないっぽいんですけど。
実は方法があるかもしれないけど自分で作って上手く言った例を貼っておく。
単に GtkEntry の activate シグナルを処理しているだけですけど。

その前に説明が必要だろうけど Y901x にリネーム機能を付ける。
Windows 版 Y901 と同じ方法です、ダイアログを出して名前変更して Enter。
という流れにしたいんだが方法が見つからなかったのでやってみたということで。

よく考えると GTK+ アプリはダイアログの値変更を即摘要という感じなのが多い。
Linux 屋はそういう方向を好むのかな?乗り換え組には結構違和感がある。

右クリックメニューもマウスボタンダウンで出るし、でも慣れると素早い操作ができて楽。
逆に慣れてしまって Windows を使う時に間違えてしかたがない。

つーことで、自分が使っているアトリビュートな変数名とかはそのまんまだけどこんな。
Python は関数内に関数が入れられるから一つの関数に収められて便利だよね。

def rename(self):
    if self.p_filename == "":
        return
    name = self.p_filename
    label = gtk.Label()
    label.set_text(self.p_filename)
    entry = gtk.Entry()
    entry.set_text(self.p_filename)
    d = gtk.Dialog( "リネーム",
                    self.w,
                    gtk.DIALOG_MODAL,# | gtk.DIALOG_DESTROY_WITH_PARENT,
                    (gtk.STOCK_CANCEL, gtk.RESPONSE_REJECT,
                    gtk.STOCK_OK, gtk.RESPONSE_ACCEPT) )
    d.vbox.pack_start(label, False)
    d.vbox.pack_start(entry, False)
    d.show_all()
    # GtkEntry にて Enter キーで OK ボタンを押す処理
    def dlg_ok(self):
        d.response(gtk.RESPONSE_ACCEPT)
    entry.connect("activate", dlg_ok)
    # 再生中ならポーズ、リピート中だと次に行ってしまう
    is_play = False
    if self.player.get_state(1)[1] == gst.STATE_PLAYING:
        is_play = True
        self.player.set_state(gst.STATE_PAUSED)
    # 開始
    if d.run() == gtk.RESPONSE_ACCEPT:
        text = entry.get_text()
        if text == self.p_filename:
            self.messagebox("変更されていません")
        else:
            if  text in os.listdir(self.p_path):
                self.messagebox("同一ファイル名が見つかりました")
            else:
                newname = self.p_path + "/" + text
                self.clear()
                while gtk.events_pending():
                    gtk.main_iteration()
                os.rename(self.p_path + "/" + self.p_filename, newname)
                while gtk.events_pending():
                    gtk.main_iteration()
                self.set_uri("file://" + newname)
    d.destroy()
    if is_play:
        self.player.set_state(gst.STATE_PLAYING)

koion

○いおんってこんな話か…微妙だ。
出てくる名前がジミヘンとかベック…まあ作る人見る人もソッチ系じゃないのでベタになるか。
せめてランディ・ローズあたりの名が出りゃ面白…という私はおっさんだが Dee は名曲だぞ。

YouTube – dee- randy rhoads (studio out-takes)

って話が違いすぎるので置いておいて。
とりあえず今日作れたとこまでをココにバックアップ、明日には出せるかな?
なんたってシーゲイトの HDD をまだ使っていますんで、今の所なんともないなぁ、、、、、
Wordpress は tar.gz で Upload すると何故か tar の前の拡張子が消滅するので zip にて。

y901x-buckup1.zip

Windows Opera を Python で

ゲストの Windows XP に入れたアプリケーション等の覚書。

.NET Framework 3.5   やっぱり必要だった
IronPython   コレを動かさなきゃいけないもん
Windows Power Shell   もうコレが無いと辛い
Windows Live   メールとフォトギャラリのみだが
IE8   何故自動更新してくれない…
WMP11   これも…

以上 Microsoft から、他

Opera   まあ私なので
Python   今回は Ubuntu に合わせて 2.6.2 を
FileZilla   コッチからサイトやブログの更新も可能なように
Paint.net   これも、もう Gimp 対向で標準にしてくれ
IrfanView   観覧にも使うけど主にスクリーンショット用
ExpLZH   圧縮する機会が多いとアーカイバーはコレしか選べない
ATOK   せっかく買ったので、Anthy のオバカ変換にも慣れたけど
EmEditor   主に Python 書き用途
秀丸   何故テキストエディタを2つも入れる?と言うな
秀丸メール   昔のメールを参照しなきゃいけない場合があるのよ
Bz   バイナリチェックをすることが多いのよ
UnitMovie   聞かないでくれ
minipoli   そりゃ自分が使う為に作ったわけで
SeeMe   そりゃ自分が使う為に作ったわけで

ホストで使うなら入れるけど見送るもの。

動画コーデック類
RealPlayer
QuickTime
VisualStudio
Firefox
Apache, PHP, MySQL
VirtualBox
他自分が作ったアプリ(仮想環境では Cinema が動かない…

最小限なのに多すぎる、、、、、

ほとんど「窓の杜」で手に入るものしか使っていないのが唯一の救い。
Linux のほうが徹底しているけど Windows も名の知れたものしか残らないわな。

Windows Power Shell も XP ではシステムフォルダに普通にアクセスしやがる。
楽といえば楽だけどチト怖いわ。

つーことで Windows でもやっぱり Python が主になる。
てゆーか Python しか入れてネェじゃん、あんなにバカにしたのに。
せっかくだから 2.6.2 を使って何か作ってみよう。
こんな私だから Python で Opera を弄くって遊ぶコードでも。

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

import sys
import ctypes

SW_HIDE = 0
SW_MAXIMIZE = 3
SW_MINIMIZE = 6

class FindOpera():
    """
        Windows で Opera を弄くる Python スクリプト
    """
    def __init__(self):
        # user32.dll のコネクト
        self.user32 = ctypes.windll.user32
        # Ansi の関数を使うなら Ansi、UNICODE を使うなら u を使う
        #self.hwnd = self.user32.FindWindowA("OpWindow", None)
        self.hwnd = self.user32.FindWindowW(u"OpWindow", None)
        if self.hwnd:
            print(unicode("起動しています", "utf-8").encode("sjis"))
        else:
            print(unicode("見つかりません", "utf-8").encode("sjis"))
            sys.exit()

    def move(self, x, y, width, height):
        # 移動とリサイズ
        self.user32.MoveWindow(self.hwnd, x, y, width, height, True)

    def active(self):
        # Z オーダーの一番上に持って行く
        self.user32.SetForegroundWindow(self.hwnd)

    def set_title(self, title):
        # タイトルバー文字列を変更する
        self.user32.SetWindowTextW(self.hwnd, title)

    def maximize(self):
        # 最大化
        self.user32.ShowWindow(self.hwnd, SW_MAXIMIZE)

    def minimize(self):
        # 最小化
        self.user32.ShowWindow(self.hwnd, SW_MINIMIZE)

if __name__=="__main__":
    opera = FindOpera()
    opera.active()
    #
    # お好きなのを有効にして実行してみてね
    #
    #opera.move(0, 0, 640, 480)
    #opera.set_title(u"おぺらだよーん - Opera")
    #opera.maximize()
    #opera.minimize()

Linux と併用だから UTF-8 にしているけど cp932 で書いたほうが楽だね。
つーか local と内部コードが違う変態 OS はやっぱり面倒だ。

ま、ウインドウのクラス名が解れば何だってコレは可能なんだけどさ。
とりあえず Windows で 2.6 の実験ということで。

メニューのサイズに差がありすぎ

GuestAdditions はなんとかなったので仮想の Windows XP に開発環境を構築。
ということで VisualStudio をインストール、しかし何度やっても失敗する。
どうも環境じゃなくドライブがおかしいっぽい??

なんかやる気失くした、使うかどうかも解らないし。
.NET がやりたくなったら HDD を繋ぎかえて Vista に戻せばいいや。

ということでネタが無いから日記。

20090503

現在丸ごとコードで作成に切り替え中、v0.1.0 という中途半端なバージョンに。

よく考えたら y901x のクラスは dbus.service.Object の継承なんだっけ。
gtk.Window とで多重継承できるのかな?イマイチよく解らないものはやってみるのが早い。
できないみたい…結局 gtk.Window は self.w とすることに。

それと右クリックメニューをこうしたいんだが。

mainmenu

メニューの横分割を GTK+ はサポートしているのかさえ解らない状態。

てゆーか 100% サイズで画像を貼って見比べるとメニューのサイズに差がありすぎ。
これは同じようにするとかなりみったくないぞ。

かといって入れ子にすると使いにくいし上手い方法が思いつかない。
古い Windows だからできた技なんだよなぁこれ、何か技は無いだろうか?