2009年12月31日木曜日

namebenchを使ってみた

このエントリーをはてなブックマークに追加
DNSサーバのベンチマークソフトであるnamebenchを使ってみました.

[ダウンロードはこちら]


このソフトは,自身が設定しているDNSサーバやGoogle Public DNS,また,その地域にあるDNSサーバなどを検査し,最良のDNSサーバをレコメンドしてくれます.

使い方も簡単で,結果はWeb上にて,グラフィカルに表示してくれます.
便利ですねー

僕の環境では,Google Public DNSは,5番目でした.






2009年12月29日火曜日

Autohotkeyでプリントスクリーン機能拡張

このエントリーをはてなブックマークに追加
プリントスクリーンはよく使う機能の一つですが,
Autohotkeyを用いて,この機能を拡張してみたいと思います.

拡張する機能は以下のようなものです.

Ctrlキーが押されている場合は,マイクロソフトペイントを起動し,
自動的にペーストすることで,編集状態に入ります.
逆にCtrlキーが押されていない場合には,ExClipを起動します.
ExClipは,クリップボードに格納されている画像を保存するためのソフトです.詳しくは開発元ページを御覧下さい.

もちろん,Altキーを押しながらプリントスクリーンキーを押すことでアクティブなウィンドウの画像のみ取得できるのは,変わりありません.

途中で100ミリ秒Sleepしているのは,ペイントを起動しきっていない状態で,ペーストするのを防ぐためです.また,変数exClipにExClipのパスを予め設定しておいてください.

; キャプチャ画像を保存する ※ExClipが必要 
*~PrintScreen::
 GetKeyState, ctrlFg, Ctrl   ; Ctrlが押されているか?
 if ctrlFg = D     ; Ctrlが押されている場合
 {
  Run, mspaint.exe
  Sleep 100
  Send, ^v
 } else {
  Run, %exClip%
 }
return

2009年12月26日土曜日

素人のように考え、玄人として実行する

このエントリーをはてなブックマークに追加
素人のように考え、玄人として実行する(金出 武雄 著)

先日京都大学で開催されたマイクロソフトリサーチ主催の21世紀コンピューティングコンファレンスにて,カーネギーメロン大学の金出先生の発表を聴講しました.
なにより感じたのは「楽しそうに研究している」ということでした.
金出先生が,研究に対してどのような哲学を持ち,取り組んでおられるか興味があり,この本を手に取りました.

参考になった箇所をいくつか抜粋したいと思います.

p.34 問題の発見方法について
A・ニューウェル教授は,学生たちに熱っぽく語るのが常であった.「そういう問題の一つ一つが『解いてくれ,解いてくれ』と,恋人を待っているようにわれわれ研究者を待っているのだ」と.

p.43 玄人としての実行方法について
プロとしていい仕事ができるか,できないか,アイデアを完成できるかどうかの分かれ道は,捨てて買える決断力,勇気があるかであろう.

p.82 研究が難航した時に
できるやつほど迷うものだ

p.180 異なるジャンルの人と触れ合う必要があるという文にて
世の中には,自分よりはるかに優れている人,自分のしらないことを知っている人,自分が思いもしないことを考えている人がいくらでもあり,驚かされる.

p.270 プレゼンについて
プレゼン資料は一目で内容がわからないように作る(略)
それだけで何を言いたいのかがわかると,聴衆は勝手なことを考え始める.(略)
それだけでは何を言いたいのかわからないが,講演者の説明とあわせると初めて,言いたいことがちょうどぴったりわかるように設計すべきである.(略)
すると聴衆は,何だろうかと思うから講演者の言う事を聞き始める.そして,講演者は聴衆の考えることをコントロールできるのである.

p.295 日本独自の~~というものについて
世界で売れている自動車や電気製品は「日の丸自動車」とか「日本人だからできたウォークマン」とは言わない.言う必要がないからである.




「素人のように考え、玄人として実行する」ということの何と難しいことか….ただ,これから心がけていきたいと思います.

2009年12月25日金曜日

切磋琢磨するアメリカの科学者たち

このエントリーをはてなブックマークに追加
切磋琢磨するアメリカの科学者たち(菅 裕明 著)
を読みました.

この本を読むきっかけについてなのですが,
先日,僕の通っている大学院の講義にて,この本の著者がゲストとして呼ばれ,1コマ分の授業を持ちました.
その中で,著者が米国の大学のシステムについてお話をしてくださったのですが,その内容がとても興味深く,もっと知りたいと思い,この本を購入しました.

著者は,岡山大学大学院を卒業後,MITにてPh.D.を取得,ニューヨーク州立バッファロー大学のAssistant Professorを経て,現在は,東京大学先端科学技術研究センターの教授をされています.そのため,著者は,日米どちらの学生,教員も経験されており,その経験をもとにこの本を記されています.

この本では,まず,米国における学生側から見た大学システム(特にPh.D.について)や教員側のシステム(新人教員のスタートアップ費用やテニュアの審査法,大学の設備など)について述べられています.
さらに,科研費(著者がライフサイエンス分野の方なので,NIH… National Institute of Healthについて詳しく)の取得方法についても記載されています.

この本の中で,著者が言いたいことのひとつに,ピアレビューというものがあります.米国のアカデミックシステムは公平な評価のもとに成り立っているということです.例えば,Ph.D.の資格適性試験は,担当の教員以外にも同じ学科の教員複数人で審査する点や,教員のテニュア審査には,同じ学科の教員以外にも外部の大学の教員を審査に加えることが挙げられます(資格適性試験は,日本でも複数人の教員が審査すると思う.また,日本にはテニュアのような資格はない).

米国では,学生の間は,少しでもよい大学院(研究室)に入るために成績は当たり前のようによい点を取り,統一試験や資格適性試験などを受け,教員になったら,限られた予算や研究室のスペースから研究を初め,テニュアを取得する・・・つまり,常に競争の中に晒され続けます.この中で勝ち抜くためには,米国の研究者は,常にモチベーションを高く維持する必要があります.(もちろん,日本の研究者のモチベーションが低いわけではない)
私が思うに,米国のシステムの良い点は,簡単に言うと,「研究者としてダメなやつはさっさと諦めて,違う仕事を探しなさい」ということです.
年を取ってから研究者にはなれないと言うわけではないけども,若いうちの方が,他の求人に関しての幅も広く,チャンスも多いだろう.米国のシステムには,「ダメ」とはっきり言うことで,アカデミックポストを早い段階で諦めさせ,別の仕事に就くチャンスを多くするという優しさがあると思います.

最後に,著者は「では,日本のアカデミックシステムをどのように改革したらよいか?」について書かれています.興味が沸いた方は是非手に取ってお読みください.

決断力

このエントリーをはてなブックマークに追加
決断力(羽生 善治著)

この本では棋士の羽生善治氏が決断力と題して,いかにビジネスや研究,勝負事において決断をするかについて記している.

感銘を受けた部分をいくつか紹介したい.

p.39 将棋をする上でなぜ新しい手を指すかについて
未知の世界に踏み込み,自力で考え,新しいルートを探し求める気迫こそ,未来を切り開く力になると私は考えている.

p.57 考える力について
私は,将棋を通して,そういう人間の本質に迫ることができればいいな,と思っている.

p.73 新しい手を指す際のリスクについて
私は,積極的にリスクを負うことは未来のリスクを最小限にすると,いつも自分に言い聞かせている.

p.131 新しいアイデアを発想することについて
自分で手を動かすことが知識に血肉を通わせることになる.

p.155 学びのプロセスについて
遠回りをすると目標に到達するのに時間はかかるだろうが,歩みの過程で思わぬ発見や出会いがあったりする.

p. 157 プロジェクトを組む,研究会に参加するということに関して
基本は,自分の力で一から考え,自分で結論を出す.それが必要不可欠であり,前に進む力もそこからしか生まれないと,私は考えている.
(誤解のないように言っておくが,この前の文章で「何人かの人と共同で検討すると,理解の度合いが二倍というよりも,二乗,三乗と早く進んでいくのは確かだ.」と述べている.)

p.165 コンピュータ将棋について
たとえコンピュータが必勝法を見つけ出したとしても,それを人間が理解することはできないだろう.

p.168 才能について
才能とは,同じ情熱,気力,モチベーションを持続することである.

p.169 頭のよさについて
たくさんの知識を活用できる,記憶力がいい,計算が速くできる,機転がきく…なども頭がいいといえよう.私は,ロジカルに考えて判断を積み上げる力も必要であると思うが,見切りをつけ,捨てることを決断する力も大事だと思っている.



将棋の世界は一般社会的に生きる人から見ると特異な世界と言える.しかし,この本を読む中で,私は,棋士が将棋を指す中で行う情報の取捨と次の一手の選択を行う上で必要な決断力は,一般社会に生きる人でも多いに参考にする箇所があると思った.

2009年12月16日水曜日

簡単に,単純に考える

このエントリーをはてなブックマークに追加
簡単に,単純に考える(羽生 善治 著)

この本では棋士の羽生善治氏がスポーツジャーナリストの二宮清純氏,元ラグビー日本代表監督の平尾誠二氏,カーネギーメロン大学教授の金出武雄氏と対談した内容が記されている.

本書内で感銘を受けた箇所,共感を持てた箇所,考え深かった箇所をいくつか紹介したいと思う.

p.12 秀才について
二宮:秀才というのは相対的な能力評価だと,私は思うんですよ.周りとの比較でものを考える.たとえば,誰かが100メートルを9秒8で走ったら,自分は9秒7で走れば勝つことができるのだと.

p.43 記憶力と創造力について
二宮:「どうも記憶が悪くて」という人がいますが,そういう人にかぎって企画力や想像力では負けないと自負している.ですが,創造力やアイデアの源は,頭の中の記憶の組み合わせから生まれてくるような気がします.

p.46 将棋には非常によくできたルールがあることについて
羽生:制約や約束事があるから,工夫しよう,打破しようという気持ちになるのでしょうね.

p.116 理想の将棋について
羽生:私の将棋の理想は,一局の将棋が初手から終わりの一手まで,一本の線のようになっていることなんです.

p.156 羽生の目標について
金出:羽生さんは「いい棋譜を残したい」といわれていますね.

p.158 有限ゲームについて
金出:ものすごく賢い宇宙人が二人でやってきて,これからチェスを指そうと言う話になる.まずは駒を並べて,先手はじっと考えた末「勝った!」,相手は「参りました」といって,終わったという・・・

p.176 将棋の盤面の評価について
金出:つまり,盤面のよさを評価する関数は滑らかでない.

p.189 研究について
金出:研究というのは,自然の世界とか摂理に対して「こういうことをやらせてほしい」「いや,それは難しいからやってくれるな」と交渉しているんですよ.それがちょうどいいところで交渉できたら,研究は成功すると.

p.229 思考法について
羽生:最善手は一つである.過去の成功体験や決断を妨げている複雑な思いから脱却する勇気を持てば,どこに次の一手を打つべきかという本質も見えてくるはずである.

われはロボット(I, Robot)

このエントリーをはてなブックマークに追加
われはロボット(I, Robot)アイザック・アシモフを読んだ

SFの名作中の名作ですね.
アシモフによって考えられたロボット工学三原則をご存じの方も多いのではないでしょうか?

第一条 ロボットは人間に危害を加えてはならない。また、その危険を看過することによって、人間に危害を及ぼしてはならない。

第二条 ロボットは人間にあたえられた命令に服従しなければならない。ただし、あたえられた命令が、第一条に反する場合は、この限りでない。

第三条 ロボットは、前掲第一条および第二条に反するおそれのないかぎり、自己をまもらなければならない。

この本の構成は短編集となっており,ロボット工学三原則を軸に話が展開されていきます.
基本的にロボットはロボット工学三原則に基づいて行動します.つまり,命令を与えられて行動を起こす必要がある場合,原則に最も適した行動を選択する必要があります.そこで,一定時間内に,無数の行動パターンの中からベストな解を探索する必要があるのですが,探索が同じ箇所を繰り返したり,探索が止まってしまうことがあります.このような状態に陥るとロボットは暴走したり停止してしまいます.

これを回避するために,人間はロボットに命令を与える際に,探索する必要がある空間をできるだけ限定し,命令の意図を明確にする必要があります.
(フレーム問題ってやつですね)

この本の中では,ロボットにこのような問題が起こり,人々に対して不利益をもたらすケースが記されています.

あーーーーーーーーーーーなるほど!!と推理小説を読んでいる気分になり,その度にアシモフが半世紀も前によくこれだけの話を考えられたなと驚愕しました.

2009年12月13日日曜日

英語学習法

このエントリーをはてなブックマークに追加
勝手に僕の英語学習法を公開したいと思います.

タダで気軽に行うということがモットーですw

◆Reading
[VOA Special English]
毎日様々な分野のトピックが掲載され,購読することができます.
また,ゆっくりめに音読してくれる音楽ファイル(mp3)をダウンロードすることができます.
一度自分で読み,音声を聞きながらシャドーイングをしてはどうでしょうか.


◆Writing
[lang-8]
一言でいうと添削SNSです.ユーザは登録時に自分の学習したい言語と,母国語を登録します.そして,学習したい言語で日記を書きます.例えば今僕が英語で学習したいとしましょう.
そうすると,英語が母国語の人たちが僕の日記を修正してくれます.逆に彼らが日本語を学びたく,日記を書いたとすると,僕は彼らの日記を修正します.人々の善意で成り立つまさにWeb 2.0というサイトです.
もちろん,ネイティブとはいえ,一般の方なので,論文等のネイティブチェックに使えるわけではないのですが,気軽に日記を書いて修正してもらえるのは嬉しいです.


◆Listening
[YouTube EDU]
StanfordやHarvard, UCBerkeley, Carnegie Mellonなど名高い大学の講義の動画を無料で閲覧することができます.
Stanfordの卒業式でのスティーブ・ジョブズやHarvardでのビル・ゲイツ,CMUでのランディ・パウシュの最後の授業はとても有名ですね.


[TED]
Technology Entertainment Design conference (TED)での素晴らしいスピーチを聞くことができます.ビデオによっては,日本語を表示することも可能です.また,多くのビデオで英語の字幕を表示することができます.


◆Speaking
[EnglishCentral]
このサイトでは,スピーキングの練習をすることができます.
英語のビデオが流れるのですが,一文ずつ停止します.そして,マイクを通して今聞いた文を発声します.この発声に基づいて,ポイントを入手することができます.友人とポイントを競いあうことができますね.


◆Vocabulary
[smart.fm]
効率良く英単語を学習することができます.
良い点としては,iKnow(実際に単語を学習するアプリ)のインタフェースが良い点です.飽きずに楽しく学習することができます.
また,コンテンツ(smart.fm上ではコースと呼びます)も分野別に整理されており,また,多数用意されています.例えば,英語入門,TOEIC listening or writing,TOEFL,Business用などです.おもしろいコースとして恋愛の生英語などがあります.
僕はこのsmart.fmで6000ワード学習しました.


◆TOEIC
[TOEICデイリーミニテスト - 英語学習 - Yahoo!学習]
リスニングセクションのPart1-3,リーディングセクションのPart5から,毎日模擬TOEIC問題が掲載されます.
時間が5分余った時,やってみてはどうでしょうか.


[TOEIC Testプラス・マガジン]
こちらは書籍です.
今話題のニュースや覚えて欲しい単語などが掲載されたあと,TOEICの模擬問題1回分が掲載されています.TOEICテストを受ける前に,過去問をやるだけで点数がいくぶんが伸びると思います.

2ヶ月に1回発行されます.

◆余談
これは英語学習が目的ではないのですが,毎日Google Scholarで英語論文を1本検索し,アブストだけ目を通すようにしています.もちろん,アブストだけで論文の内容がしっかり伝わってくるわけではないので,英語もわからない上に,内容もわかならないことが多いのですが,英語アレルギーを少しでも減らすように,おまじない程度に行っています.(ただ,自分は毎日英語に触れているという意識を持つことは非常に重要だと思っています.)

また,上記のように日課として行うから,少し疲れた日でも頑張って続けるというのもありますが,基本的に自分の興味のある分野を学習する,ということを通して英語を学習する方法がよいと思います.
例えば,僕の場合,工学や科学技術に興味があるので,YouTube EDUやTED,VOA Special Englishなどでは,それらに関係ある内容しか見ません.また,lang-8では,旅行した時とか,月の写真を撮ったとか,僕自身の楽しかった思い出を書いています.(つらかった事をわざわざつらい英語で書きたくはないです)


みなさんも是非.

企業の研究者をめざす皆さんへ

このエントリーをはてなブックマークに追加
企業の研究者をめざす皆さんへ(丸山 宏著)

IBMの東京基礎研究所の所長としてご活躍されていた丸山 宏さんが,企業の研究者の方,あるいはそれを目指す学生へのメッセージとして書かれた本である.

トピックとしては以下のようなものがある.
・研究について
・コミュニケーショの大切さ
・研究者のキャリア
・リーダシップについて
・企業の研究所のマネジメント
・知的・契約・技術調査
・研究所の風土
・企業の研究者をめざす学生の皆さんへ

企業の研究者をターゲットとしているため,研究者としてのキャリア形成に関する話題以外にも,研究所を機能させるためのマネジメントやビジネス論についても述べられている.

印象に残った箇所を一部抜粋してみたいと思う.
p.20
CMUの金出先生とのエピソードにて
(金出先生に筆者が)では,どうやったら良い問題を選ぶセンスを見に着けることができるのでしょう?夜の食事の席でこの質問をしたら,「うーん」としばらく考えて,「研究が成功したときにどういうデモをするつもりか」を考えてみたら,と言われました.
金出先生のおっしゃるには,研究の成果をデモとして見せたとき,「これはどのように動いているのですか」と聞かれるようではまだまだで,見せたとたんに「これはいくらですか」と聞かれることが,デモの成功した証拠なのだそうです.

p.44
プレゼンテーションの仕方について
私が会社に入って受けたプレゼンテーションの研修の中で,一番頭に残っていることは,「聴衆の興味を画面ではなく,あなた自身に向けるようにしなさい」ということです.
(~略~)
特に印象に残ったのが,「説得と納得の違い」です.いくら理詰めで説得しようとしても,人は自分の言葉で納得できないと行動にはつながらないものです,

p.82
IBMのテクニカル・コミュニティのリーダーであるNick Donofrioのスピーチについて
Nickは,「Don't settle for anything」と言っています.
(~略~)
Steve Jobsのスピーチにも出てくる,現状に満足してしまったら進歩が無い,常に次の一歩を探して生きよう,という意味だ.

p.151
知的財産権について
他人の知財を知らずに使うと罰せられるが,良い知財を持っているのに社会のためにそれを役立たせない人には罰則の規定がない.

「Research that matters」という筆者の言葉,また,本の中で繰り返し引用されている金出先生の「素人発想,玄人実行」という言葉には大変感銘を受けました.

企業の研究者を目指している人だけでなく,研究職を目指す人,さらには,大学での卒業論文のために研究を行う必要がある全ての人にこの本をオススメします.

眠れなくなる宇宙のはなし

このエントリーをはてなブックマークに追加
眠れなくなる宇宙のはなし(佐藤 勝彦著)を読みました.

この本では人類の歴史上の宇宙観について,古代インドの捉え方や,宇宙をめぐる宗教裁判,相対性理論,そして最新の動向であるブレーン宇宙論までまとめてあります.
また,それ以外にもアインシュタインなどの学者についての教科書には載ってないような小話が書かれており,非常に楽しく読むことができました.

一部を抜粋して掲載したいと思います.
p.114
宇宙は永遠のものであると唱えたアリストテレスに対してのアクィナス
「宇宙に始まりがあるというのは,信じるべきことであって,論証すべきものではないのだ」と主張したのです.人間の理性には限界があり,宇宙の始まりの問題はその限界を超えたものなので,これは議論しても始まらない,ただ聖書を信じていればいいのだ,というわけです.

p.121
アリスタルコスが唱えていた地動説を再発見したコペルニクスについて
コペルニクスは神に逆らって地動説を唱えたわけでもありません.むしろ神様を信じ,宇宙を「偉大な創造者の荘厳な作品」だと信じていました.その上で,「神がお造りになった美しい宇宙の姿にふわさしいのは,天動説よりも地動説なんだ」と確信したんですね.

p.221
宇宙の歴史を説明するビッグバン宇宙論を完璧にする理論について
私たち人間はニュートン力学を手にすることで,太陽系の天体の動きを説明し,未知の惑星の存在を予言することにも成功しました.さらに二十世紀には,ニュートン力学を乗り越える相対性理論を得て,宇宙がミクロンの卵から膨張してきたという宇宙の歴史を描けるようになったのです.そして,宇宙誕生の謎に迫るためには,相対性理論さえ乗り越える究極の理論が必要なのです.

まさにタイトルに 偽りなしですね!
楽しく読むことができました.

2009年12月12日土曜日

AutohotkeyでTVClockもどき

このエントリーをはてなブックマークに追加



僕は普段こちらのサイトのTVClockというソフトウェアを使用させてもらっています.

TVの時計のようなシンプルで視認性の高い時計なんですが,このソフトウェアのもどきをAutohotkeyで作成しました.

clockPointX = 1440   ; X座標
clockPointY = -20   ; Y座標
clockColor = FFFFFF  ; フォントカラー
backColor = 000000  ; 仮の背景色
textSize  = 30   ; テキストサイズ
updateTime = 20000   ; タイマをポーリングする時間(msec)

Gui, Color, %backColor%
Gui, Font, S%textSize%, Courier New
Gui, Font, C%clockColor%
Gui, Add, Text, vMyText %clockColor%, HH:MM
Gui, +LastFound -0x00C00000 +ToolWindow

WinSet, TransColor, %backColor% 255
Gui, Show, X%clockPointX% Y%clockPointY%
GuiControl,, MyText, %A_Hour%:%A_Min%

SetTimer, Update, %updateTime%
Gosub, Update
return

Update:
 GuiControl,, MyText, %A_Hour%:%A_Min%
return

2009年12月4日金曜日

AutoHotkeyを使ったTexのコンパイル

このエントリーをはてなブックマークに追加
私は,普段エディタにはEmEditorを使用しています.
論文等書く際にTexを使う必要がありますが,WinShellなどは使わず,EmEditorで編集してから,バッチファイルを実行することにより,.texを.dviや.ps, .pdfにしていました.

ここで,AutoHotkeyを利用して,EmEditorがアクティブな状態で,ホットキーを押すと,texファイルのコンパイルを行ってくれるようにしました.
(EmEditorのTexプラグインもあるのですが,どうも使いづらい)

AutoHotkeyのスクリプトは下記のようになります.
プログラム内部では,platex, dviout, dvipdfmのコマンドを使用しています.
これらのコマンドがお使いの環境で使用できることを確認してください.

このスクリプトでは,EmEditorで,texファイルを編集している時,F5を押すと,texファイルをコンパイルし,dvioutからdviファイルを閲覧することができます.
また,Ctrl+F5を押すと,tex=>dvi=>pdfの変換を行った後,pdfファイルを開いてくれます.

/*
platex,dviout,dvipdfmが使用できる必要あり
*/

#NoEnv

; EmEditorか判断
#IfWinActive, ahk_class EmEditorMainFrame3
 *F5::             ; 任意キーとF5 or F5が押された場合
  GetKeyState, ctrlFg, Ctrl    ; Ctrlが押されているか?

  WinGet, window,, ahk_class EmEditorMainFrame3
  WinGetTitle, title, ahk_id %window%  ; title=>C:\aaa\bbb\ccc.tex -EmEditor

  StringSplit, array, title, " "   ; array=>{C:\aaa\bbb\ccc.tex,-EmEditor}
  filePath = %array1%       ; filePath=>C:\aaa\bbb\ccc.tex
  StringRight, extension, filePath, 4  ; extension=>.txt

  If extension = .tex
  {
   StringGetPos, pos, filePath, \, 1
   StringLeft, dir, filePath, pos  ; path=>C:\aaa\bbb

   RunWait, platex %filePath%, %dir% ; tex=>dvi

   StringGetPos, pos, filePath, ., 1
   StringLeft, name, filePath, pos  ; name=>C:\aaa\bbb\ccc
   
   If ctrlFg = D       ; Ctrlが押されている場合
   {
    IfWinExist ahk_class dviout  ; dvioutが開いていたら閉じる
     WinClose
    RunWait, dvipdfm %name%.dvi, %dir% ; dvi=>pdf
    If ErrorLevel = 1
     Msgbox, "pdfを閉じてください"
    Run, %name%.pdf
   } Else {
    IfWinNotExist ahk_class dviout
     Run %name%.dvi
    Else
     WinActivate, ahk_class dviout
   }
  }
 return
#IfWinActive

2009年12月3日木曜日

IMEのOn-OffをAutoHotkeyで行う

このエントリーをはてなブックマークに追加
Google日本語入力が登場しましたね.

早速私も使おうと思ってインストールしました.
しかし,ここで問題が発生しました.

私はHHK(Happy Hacking Keyboard)を愛用しているのですが,これは英字キーボードであるため,半角/全角キーがありません.
そこで,私はMicrosoft IME等では,IMEのOn-OffをShift+Spaceに割り当てることで対処しています.

しかし,Google日本語入力では,(私の見たところ)IMEのOn-Offを半角/全角キー意外に割り当てることはできません.

そこで,仕方ないので,なんでもできるAutoHotKeyで,対処することにしました.

まず,AutoHotkeyを流行らせるページのアップロードより,089.zipをダウンロードします.
URL:
http://lukewarm.s101.xrea.com/up/index.php
zipを解凍し,中からIME.ahkを取り出します.

これにはIMEの状態をSETしたりGETするための関数がいくつか用意されています.
呼び出すには下記のように使用します.
※Includeのパスは環境は環境に合わせてください.
※例では左Shift+Spaceを押すことにより,IMEのOn-Offを切り替えれます.


#Include IME.ahk; 左Shift+Spaceを半角全角に
<+Space::
getIMEMode := IME_Get()
if (%getIMEMode% = 0)
{
    IME_SET(1)
    return
}
else
{
    IME_SET(0)
    return
}

2009年11月20日金曜日

Google Chrome OSを入れてみた

このエントリーをはてなブックマークに追加
[Download]
こちらのサイトからVMの仮想ディスクイメージをダウンロードします.
(DLにはユーザ登録が必要)
http://gdgt.com/google/chrome-os/download/

[Install]
VM PlayerやVM WorkStationで実行します.
vmdkからの展開となるので,少し厄介.
インストールには,下記ページを参照してください.
http://www.forest.impress.co.jp/docs/special/20091120_330552.html

[Screen shot]

・OSが立ち上がった直後のログイン画面.
ここのログインにはGmailのアカウントが必要となります.
また,ネットワークに接続されている必要があります.





・このページを見たところ.
右上にメニューがあります.




 ・メモリーの使用量
26Mbyteほどで動作しているみたいです.
ちなみにOSの最小動作メモリは32Mbyteとなっています.





・ダウンロードしたファイルも,ブラウザ上からアクセスします.




・バージョン情報




まだまだ,実用レベルには達していないと思いますが,今後の開発には注目していきたいです.
[追記]
proxy環境下ではログインすらできないのかな??

2009年11月15日日曜日

reacTIVisionを使ってみた2(volume controller)

このエントリーをはてなブックマークに追加
こんなのを作ってみました。



二つのマーカーを使っていて、
ひとつはボリューム調節用コントローラとして
もうひとつは、写真を表示するためのXY座標を決定するために使用しています。

ボリューム調節用コントローラは時計回転すると(見にくいんですけど)マーカーの下に黒色のゲージがたまっていきます。
逆回転すると下がります。

そして、ボリューム調節用コントローラのボリューム値によって写真を拡大・縮小しています。

2009年11月10日火曜日

reacTIVisionを使ってみた

このエントリーをはてなブックマークに追加
reacTIVision
は,タンジブルユーザインターフェースやフィンガートラッキングを実現するためのオープンソースなフレームワークです.




昨日,研究室の先輩に教えていただき,とりあえずサンプルプログラムをいじって,簡単なプログラムを書いてみた.

どういうことをしているかって言うと,壁の手前にプロジェクターとカメラを用意しています.

壁にマーカーを貼り付けることにより,マーカーの座標を取得し,その座標を基に,描画を行いプロジェクターから出力しています.

とりあえず,作ってみたのは,

二つのマーカーを使用した音楽再生プログラム.
一つのマーカーは音楽プレーヤを表していて,処理として「Play」と「Stop」を持ちます.

もうひとつのマーカーは音楽プレーヤをコントロールするためのマーカーです.
音楽プレーヤマーカーの近くに表示されているPlayとStopの近くにこのコントロールマーカーを持っていくことで,音楽を再生したり止めたりすることができます.

画像認識,処理などの知識なんて全くって言っていい程ないけど,reacTIVisionを使うと簡単にプログラムを書けます.

2009年11月2日月曜日

Google Guiceを使ってみた

このエントリーをはてなブックマークに追加
Google Guice はオープンソースの Java™ 開発用DI (Dependency Injection: 依存性注入)フレームワークです.

DIとは依存性の注入のことで,同じインターフェースを持つ具象クラスを,設定によって入れ替え可能にする方法を指します.このことにより,プログラムの挙動を動的に変更することができます.

[download]
http://code.google.com/p/google-guice/downloads/list

[Main.java]
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

public class Main {
 public static void main(String[] args) {
  Injector injector = Guice.createInjector(new AbstractModule() {
   @Override
   protected void configure() {
    bind( String.class ).toInstance( "まつたけ" );
    bind( int.class ).toInstance( 5000 );
   }
  });
  injector.getInstance(Item.class).view();
 }
}

[Item.java]
import com.google.inject.Inject;

public class Item {
 @Inject
 private String name;
 @Inject
 private int price;
 
 public void view() {
  System.out.println("商品名" + " : " + name);
  System.out.println("値段" + " : " + price);
 }
}

上記のプログラムでは,次の2行でItemクラスのフィールドに対して値を代入しています.
bind( String.class ).toInstance( "まつたけ" );
bind( int.class ).toInstance( 5000 );

ここでは,Itemクラスのフィールドの型が別なので,自動的にString型がnameへintがpriceに代入されています.

ここで,Itemクラスに商品番号を表すint idというフィールドがあった時,どちらを代入すればよいのかわからないため,例外が飛びます.
bind( int.class ).toInstance( 5000 ); // price?
bind( int.class ).toInstance( 1 );  // id?

そのとうな場合には,下記のようにアノテーションで名前をつけることにより,解決できます.

[Main.java]
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.name.Names;

public class Main {
 public static void main(String[] args) {
  Injector injector = Guice.createInjector(new AbstractModule() {
   @Override
   protected void configure() {
    bind( String.class ).annotatedWith(Names.named( "name" )).toInstance( "まつたけ" );
    bind( int.class ).annotatedWith(Names.named( "price" )).toInstance( 5000 );
    bind( int.class ).annotatedWith(Names.named( "id" )).toInstance( 1 );
   }
  });
  injector.getInstance(Item.class).view();
 }
}

[Item.java]
import com.google.inject.Inject;
import com.google.inject.name.Named;

public class Item {
 @Inject
 @Named("name")
 private String name;
 @Inject
 @Named("price")
 private int price;
 @Inject
 @Named("id")
 private int id;
 
 public void view() {
  System.out.println("商品名" + " : " + name);
  System.out.println("値段" + " : " + price);
  System.out.println("ID" + " " + id);
 }
}


参考:
Guice による依存性注入(IBM Developerworks)
http://www.ibm.com/developerworks/jp/java/library/j-guice.html

GoogleからリリースされたDIフレームワーク(gihyo.jp)
http://gihyo.jp/dev/serial/01/awdp/000101


GoogleのDIフレームワーク"Guice"を使ってみる(マイコミジャーナル)
http://journal.mycom.co.jp/articles/2007/03/14/googleguice/001.html

2009年7月16日木曜日

AutoHotKeyを使ってみた

このエントリーをはてなブックマークに追加
AutoHotkeyはアプリケーション毎のホットキーの割り当てや,キーカスタマイズ,スクリプトによるOS/アプリケーションのコントロール等ができるツールです.

簡単に言うと,自由自在に操作できる高機能なスクリプト実行環境です.

詳しい使い方は,
AutoHotkeyを流行らせるページ
に書いてあるので,見て下さい.


いくつかスクリプトを書いたので,メモします
■Alt+Tabの動作変更
通常,Alt+TabでWindows標準のウィンドウ切り替えが起動しますが,インクリメンタルサーチで絞り込めるウィンドウ切り替えソフトウェア「CLTC」に変更します.
!Tab::Run "C:\MyPrograms\cltc\cltc.exe"



■起動orアクティブ
関数を定義し,プログラムが起動していなかったら起動し,起動している場合には,アクティブ(トップに表示すること)にします.
ここでは,Alt+aで便利な2画面ファイラー「あふ」を,Alt+cで,ユーザデスクトップ上で,コマンドプロンプトを起動します.その他にもいくつか割り当ててますが,省略します.
Launch(class, path)
{
IfWinNotExist ahk_class %class%
Run, %path%
else
WinActivate, ahk_class %class% 
return
}
Launch_Param(class, path, param)
{
IfWinNotExist ahk_class %class%
Run, %path%, %param%
else
WinActivate, ahk_class %class%
return
}
!a::Launch("TAfxForm", "C:\MyPrograms\afx11\AFX.EXE")
!c::Launch_Param("ConsoleWindowClass", "cmd.exe", "C:\Users\*****\desktop")



■F10でアクティブなウィンドウを半透明にする
こんな感じ


F10::
WinGet, t, Transparent, A
if %t%
WinSet, Transparent, Off, A
else
WinSet, Transparent, 160, A
return



■Ctrl+F10で上記を全てのウィンドウに
^F10::
WinGet, id, list, , , Program Manager
Loop, %id%
{
StringTrimRight, this_id, id%a_index%, 0
WinGet, t, Transparent, ahk_id %this_id%
if %t%
WinSet, Transparent, Off, ahk_id %this_id% 
else
WinSet, Transparent, 160, ahk_id %this_id% 
}
return




■F11でアクティブなウィンドウを最大化
F11::
WinGet, State, MinMax, A
if State != 0
WinRestore, A
else
WinMaximize, A
return



■Ctrl+F11でアクティブなウィンドウを最小化
^F11::
WinGet, State, MinMax, A
if State != 0
WinRestore, A
else
WinMinimize, A
return



■Win+カーソルでウィンドウの移動
Ctrlも一緒に押すと移動量が少なくなります
WinMoveStep(XD,YD,PARAM) {
WinGet,win_id,ID,A
WinGetPos,x,y,,,ahk_id %win_id%
Step := 128
if(PARAM = 1)
Step := 24
x := x + (XD * Step)
y := y + (YD * Step)
WinMove,ahk_id %win_id%,,%x%,%y%
return
}
#Left::WinMoveStep(-1,0,0)
#Right::WinMoveStep(1,0,0)
#Up::WinMoveStep(0,-1,0)
#Down::WinMoveStep(0,1,0)
#^Left::WinMoveStep(-1,0,1)
#^Right::WinMoveStep(1,0,1)
#^Up::WinMoveStep(0,-1,1)
#^Down::WinMoveStep(0,1,1)



■Win+Shift+カーソルでウィンドウサイズを変更
Ctrlも一緒に押すと移動量が少なくなります
WinSizeStep(XD,YD,PARAM) {
WinGet,win_id,ID,A
WinGetPos,,,w,h,ahk_id %win_id%
Step := 128
if(PARAM = 1)
Step := 24
w := w + (XD * Step)
h := h + (YD * Step)
WinMove,ahk_id %win_id%,,,,%w%,%h%
return
}
+#Left::WinSizeStep(-1,0,0)
+#Right::WinSizeStep(1,0,0)
+#Up::WinSizeStep(0,-1,0)
+#Down::WinSizeStep(0,1,0)
+#^Left::WinSizeStep(-1,0,1)
+#^Right::WinSizeStep(1,0,1)
+#^Up::WinSizeStep(0,-1,1)
+#^Down::WinSizeStep(0,1,1)



■Shift+SpaceでIME ON-OFF切り替え
+Space::Send, {vkF3sc029}



■単独のWinキーのみでスタートメニューを表示しない
※誤動作防止のため
RWin::return
RWin & RWin::return
LWin::return
LWin & LWin::return



■コマンドプロンプト
コマンドプロンプト上でもクリップボードの内容を貼り付けるのに,Ctrl+vを使えるようにする.また,終了はCtrl+w,全て選択はCtrl+a等

#IfWinActive ahk_class ConsoleWindowClass
^v::Send,!{Space}ep     ; ^V ペースト
^w::Send,!{Space}c      ; ^W 終了
^f::Send,!{Space}ef     ; ^F 検索
^a::Send,!{Space}es     ; ^A 全て選択
^k::Send,!{Space}ek     ; ^K 選択
#IfWinActive





AutoHotkeyを流行らせるページに行くと便利なサンプルプログラムがあります.
中でもホイールリダイレクトは便利!

2009年6月7日日曜日

Linuxコマンド

このエントリーをはてなブックマークに追加
-----------------------------
find
-----------------------------
⇒ /foo/bar 以下の全ファイル一覧を表示
find /foo/bar -type f
⇒ /foo/bar 以下の全ディレクトリ一覧を表示
find /foo/bar -type d
⇒ 特定のファイル名を検索
find . -name "*.conf"
⇒ 4日以内にアクセスされたファイル
find . -atime -4
⇒ 4日以内に修正されたファイル
find . -mtime -4
⇒ 10分以内に修正されたhtmlファイルを検索
find . -mmin -10 -exec grep *.html {} \;
⇒ /var/以下で"成功"という文字列を持つhtmlファイルを検索する
find /var/ -name \*.html -print0 | xargs -0 grep 成功 /dev/null

-----------------------------
iptables
-----------------------------
⇒ 状態の確認
iptables -L
⇒ ポリシーの設定
iptables -P INPUT ACCEPT
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
⇒ ルールの削除
iptables -F
⇒ icmp(ping)からの入力を許可
iptables -A INPUT -p icmp -j ACCEPT
⇒ 自端末からの入力を許可
iptables -A INPUT -i lo -j ACCEPT
⇒ Web,SSHからの入力を許可
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
⇒ 他の接続はすべて破棄(ポリシーの再設定)
iptables -P INPUT DROP
⇒ ルールをセーブする
/etc/init.d/iptables save
⇒ 再起動
networking restart


-----------------------------
netstat ネットワーク関連の統計情報を表示する
-----------------------------
⇒ 全てのサービスを表示(-t:tcp,-u:udp)
netstat -a

-----------------------------
arp システムのARPキャッシュを操作する
-----------------------------
⇒ 指定したホストに対しての情報を表示する
arp -a [ホスト名]
⇒ 指定したホストに対しての情報を削除する
arp -d [ホスト名]

-----------------------------
route ルーティング・テーブルを表示・設定する
-----------------------------
⇒ ルーティングを追加する 消す場合はaddをdelete
route add -net [192.168.1.0] netmask 255.255.255.0 eth0
⇒ デフォルト・ゲートウェエイを指定する
route add default gw [192.168.0.1]


-----------------------------
at
-----------------------------
⇒ 15時20分にjob.sh内のコマンドを実行します
at -f job.sh 15:20
⇒ 実行されていないジョブを表示する
at -l
⇒ ジョブを削除
at -d [ジョブ番号]


-----------------------------
other
-----------------------------
⇒ バージョンの確認
lsb_release -a
⇒ Apacheデーモン起動
/etc/rc.d/init.d/httpd start
⇒ ログファイルの最後の5行をずっと監視する
tail -n 5 -f [ファイル名]
⇒ 現在の日付と時刻を表示する
date
⇒ 時刻を合わせる
ntpdate ntp.nict.jp
⇒ 実行するコマンドにのみ環境変数を一時的に設定
env 変数名=設定する値 コマンド
⇒ 現在ログインしているユーザーを表示する
who

2009年5月26日火曜日

Ubuntu Serverでネットワークに接続できない

このエントリーをはてなブックマークに追加
Ubuntu Server9.04をVM Ware上にインストールしましたが,初期状態でネットワークに接続できません(IPが正しく割り振られません)でした.
少し詰まったのでメモ

ネットワークカードを正常に認識していなかったようです.

1.ネットワークデバイス名を調べる
# lshw -C network

logical name をメモ
私の環境ではeth0でした.

2.ネットワークデバイスの設定
# vi /etc/network/interfaces
---------------------------
auto lo
iface lo inet loopback
# 以下を追記
auto eth0
iface eth0 inet dhcp
---------------------------


3.ネットワークの再起動
# /etc/init.d/networking restart


以上により,正常にIPが割り振られネットワークに接続できます.

2009年5月7日木曜日

JBox2Dのプログラムサンプル

このエントリーをはてなブックマークに追加
2D物理シュミレーションエンジンBox2DのJavaバージョンであるJBox2Dを使用してみました.
JBox2D:http://www.jbox2d.org/


以下のプログラムは,ある閉じた空間(2D)内に複数のボールを用意し,物理演算を行ってボールが跳ねる様子を見ることができます.
また,自由に新しいボールや壁を追加することができます.


[PhysicalWorld.java]

import org.jbox2d.collision.AABB;
import org.jbox2d.collision.CircleDef;
import org.jbox2d.collision.PolygonDef;
import org.jbox2d.collision.Shape;
import org.jbox2d.common.Vec2;
import org.jbox2d.dynamics.Body;
import org.jbox2d.dynamics.BodyDef;
import org.jbox2d.dynamics.World;
import org.jbox2d.dynamics.joints.MouseJoint;
import org.jbox2d.dynamics.joints.MouseJointDef;
import org.jbox2d.collision.*;

import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.*;

import java.util.*;

public class PhysicalWorld extends JFrame {
public static void main(String[] args) {
new PhysicalWorld();
}

public PhysicalWorld() {
// タイトルを設定
setTitle("MyFrame");
// 閉じるボタンを押した際,プログラムを終了
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 起動時のロケーション設定
// setLocation(0, 0);

// メインパネルを作成してフレームに追加
MainPanel panel = new MainPanel();
Container contentPane = getContentPane();
contentPane.add(panel);
setVisible(true);
// パネルサイズに合わせてフレームサイズを自動設定
pack();
}
}

class MainPanel extends JPanel implements Runnable {
// パネルサイズ
private static int width = 600;
private static int height = 400;
// 1m = 10px
private static final int WORLD_SCALE = 10;
private World mWorld;

// 壁格納用リスト
private java.util.List groundBodyList = new ArrayList();
// ボール格納用リスト
private java.util.List ballBodyList = new ArrayList();

// マウスジョイント
private MouseJointDef mouseJointDef;
private MouseJoint mouseJoint;

// アニメーション用スレッド
private Thread thread;
Body ballBody;

public MainPanel() {
initMainPanel();
initWorld();
initGround();
initBall();
// スレッドを起動
thread = new Thread(this);
thread.start();
}

private void initMainPanel() {
// パネルの推奨サイズを設定
// pack()するときに必要
setPreferredSize(new Dimension(width, height));
setBackground(Color.BLACK);
// マウスリスナを登録
this.addMouseListener(new MyListener());
this.addMouseMotionListener(new MyListener());
}

private void initWorld() {
Vec2 minV = new Vec2(-100,-100);
Vec2 maxV = new Vec2(100,100);
AABB aabb = new AABB(minV,maxV);
mWorld = new World(aabb, new Vec2(0.0f,9.8f),true);
}

private void initGround() {
// 上壁
createGroundBody(0.0f, 0.0f, (width * 0.9f) / WORLD_SCALE, 0.0f);
// 下壁
createGroundBody(0.0f, (height * 0.9f) / WORLD_SCALE, (width * 0.9f) / WORLD_SCALE, (height * 0.9f) / WORLD_SCALE);
// 左壁
createGroundBody(0.0f, 0.0f, 0.0f, (height * 0.9f) / WORLD_SCALE);
// 右壁
createGroundBody((width * 0.9f) / WORLD_SCALE, 0.0f, (width * 0.9f) / WORLD_SCALE, (height * 0.9f) / WORLD_SCALE);
}

private void initBall() {
// ボールの作成
for(int i = 15; i < 30; i++){
createBallBody((float)i, 10.0f);
}

// ジョイント用ボールの作成
BodyDef ballBodyDef = new BodyDef();
ballBodyDef.position.set(15.0f, 5.0f);
CircleDef ballShapeDef = new CircleDef();
ballShapeDef.radius = 1.0f;
ballShapeDef.density = 1.0f;
ballShapeDef.restitution = 0.7f;

ballBody = mWorld.createBody(ballBodyDef);
ballBody.createShape(ballShapeDef);
ballBody.setMassFromShapes();
ballBodyList.add(ballBody);

mouseJointDef = new MouseJointDef();
mouseJointDef.body1 = mWorld.getGroundBody();
mouseJointDef.body2 = ballBody;
mouseJointDef.target =  ballBody.getWorldCenter();
mouseJointDef.maxForce = 1000;
}

private void createGroundBody(float sx, float sy, float ex, float ey){
BodyDef groundBodyDef = new BodyDef();
groundBodyDef.position.set((sx + ex)/2.0f, (sy + ey)/2.0f);
PolygonDef groundShapeDef = new PolygonDef();
int angle = (int)(Math.atan((double)(ey - sy) / (double)(ex - sx)) * 180 / Math.PI);
float dis = (float)Math.sqrt(Math.pow((sx-ex), 2) + Math.pow((sy-ey), 2)) / 2.0f;
groundShapeDef.setAsBox(dis, 0.1f, new Vec2(0,0),(float)(Math.PI * angle / 180.0));
Body groundBody = mWorld.createBody(groundBodyDef);
groundBody.createShape(groundShapeDef);
groundBodyList.add(groundBody);
}

private void createBallBody(float x, float y){
BodyDef ballBodyDef = new BodyDef();
ballBodyDef.position.set(x, y);
CircleDef ballShapeDef = new CircleDef();
ballShapeDef.radius = 1.0f;
ballShapeDef.density = 1.0f;
ballShapeDef.restitution = 0.7f;
Body ballBody = mWorld.createBody(ballBodyDef);
ballBody.createShape(ballShapeDef);
ballBody.setMassFromShapes();
ballBodyList.add(ballBody);
}

public void paintComponent(Graphics g) {
super.paintComponent(g);

g.setColor(Color.GREEN);

for(Body groundBody : groundBodyList){
Shape shape = groundBody.getShapeList();
Vec2[] vPts = ((PolygonShape)shape).getVertices();

int minX = (int)Math.min(Math.min(vPts[0].x, vPts[1].x), Math.min(vPts[2].x, vPts[3].x));
int minY = (int)Math.min(Math.min(vPts[0].y, vPts[1].y), Math.min(vPts[2].y, vPts[3].y));
int maxX = (int)Math.min(Math.max(vPts[0].x, vPts[1].x), Math.max(vPts[2].x, vPts[3].x));
int maxY = (int)Math.min(Math.max(vPts[0].y, vPts[1].y), Math.max(vPts[2].y, vPts[3].y));

minX = (int)(groundBody.getWorldCenter().x + minX) * WORLD_SCALE;
minY = (int)(groundBody.getWorldCenter().y + minY) * WORLD_SCALE;
maxX = (int)(groundBody.getWorldCenter().x + maxX) * WORLD_SCALE;
maxY = (int)(groundBody.getWorldCenter().y + maxY) * WORLD_SCALE;

if(vPts[0].y <= vPts[1].y){
g.drawLine(minX, minY, maxX, maxY);
} else {
g.drawLine(minX, maxY, maxX, minY);
}
}

g.setColor(Color.RED);
int r = 2;
Vec2 pos;

for(Body ballBody : ballBodyList){
pos = ballBody.getWorldCenter();
g.fillOval((int)((pos.x-r/2) * WORLD_SCALE), (int)((pos.y-r/2) * WORLD_SCALE), r*WORLD_SCALE, r*WORLD_SCALE);
}
}

// メインループ
public void run() {
// プログラムが終了するまでフレーム処理を繰り返す
while (true) {
mWorld.step(1/20f, 8);

// ボールを再描画
repaint();

// 20ミリ秒だけ休止
try {
Thread.sleep(20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

public class MyListener extends MouseAdapter {
Point startP,endP;

// ボタンプレス時
public void mousePressed(java.awt.event.MouseEvent e){
if((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0){         // 左クリック
// ジョイントの作成
mouseJoint = (MouseJoint)mWorld.createJoint(mouseJointDef);
mouseJoint.m_localAnchor = ballBody.getLocalCenter();
} else if((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0){   // 右クリック
// クリックポイントの作成
startP = e.getPoint();
}
}   

// ボタンリリース時
public void mouseReleased(java.awt.event.MouseEvent e){
if((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0){
// ジョイントの削除
mWorld.destroyJoint(mouseJoint);
mouseJoint = null;
} else if((e.getModifiers() & MouseEvent.BUTTON3_MASK) != 0){
// リリース場所の格納
endP = e.getPoint();
if(Math.abs(startP.x - endP.x) < 3 && Math.abs(startP.y - endP.y) < 3){   // プレス時とリリース時にあまり差が無い場合
// 新しいボールを作成
createBallBody(startP.x / WORLD_SCALE, startP.y / WORLD_SCALE);
} else {
// プレス場所からリリース場所まで壁を作成する
createGroundBody(startP.x / WORLD_SCALE, startP.y / WORLD_SCALE, endP.x / WORLD_SCALE, endP.y / WORLD_SCALE);
}
}
}

// マウスドラッグ時
public void mouseDragged(java.awt.event.MouseEvent e){
if((e.getModifiers() & MouseEvent.BUTTON1_MASK) != 0){
if(mouseJoint != null){
// ボールの移動
int x = e.getPoint().x / WORLD_SCALE;
int y = e.getPoint().y / WORLD_SCALE;
mouseJoint.setTarget(new Vec2(x, y));
}
}
}
}
} 

2009年1月14日水曜日

[Java]インタフェースのフック

このエントリーをはてなブックマークに追加
Javaでインタフェースのフックを行います.


サンプルプログラムは,GUIに表示されたボタンを押した場合のフックについて記述してあります.

[実行クラス Main.java]
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;

import javax.swing.*;

public class Main extends JFrame{

public Main(){
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(200, 200, 200, 200);
setVisible(true);
JPanel p = new JPanel();

InvocationHandler handler = new MyInvocationHandler(new MyListener());
ActionListener action = (ActionListener) Proxy.newProxyInstance(MyListener.class.getClassLoader(), new Class[]{ActionListener.class}, handler);

JButton btn = new JButton("push");
btn.addActionListener(action);
btn.setActionCommand("btn");

p.add(btn);
add(p);
}

public static void main(String[] args) {
new Main();
}
}



[イベントリスナー MyListener,java]
import java.awt.event.*;

public class MyListener implements ActionListener{
public void actionPerformed(ActionEvent e){
if(e.getActionCommand().equals("btn")){
System.out.println("push");
}
}
}




[インボケーションハンドラー MyInvocationHandler.java]
import java.awt.event.ActionListener;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;

public class MyInvocationHandler implements InvocationHandler {

private ActionListener action;

public MyInvocationHandler(ActionListener action) {
this.action = action;
}

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
Object result;
System.out.println("前処理");
result = method.invoke(action, args);
System.out.println("後処理");
return result;
}
}



GUIで表示されたボタンを押した際の処理結果は下記の様になります.
前処理
push
後処理

[Java]リフレクションによるメソッドの取得

このエントリーをはてなブックマークに追加
リフレクションを用いて,特定クラスのメソッドを解析します.
サンプルプログラムでは親クラスから継承しているメソッドは取り除いています.

[調べるクラス Function.java]
import java.util.*;

public class Function {
public static int service(List list, int a ,byte e) throws Exception{
return 1;
}

public void service2(){
}
}


[メソッド情報を保持するクラス MethodInfo.java]
import java.util.List;
import java.util.ArrayList;

public class MethodInfo {
private String    name;   // メソッド名
private String    modifier;  // 修飾子
private List  paramTypes;  // メソッドの引数型の配列
private String    returnType;  // 返り値の型

public MethodInfo(){};

public MethodInfo(String   _name,
String   _modifer,
List _paramTypes,
String   _returnType){
name         = _name;
modifier     = _modifer;
paramTypes   = _paramTypes;
returnType   = _returnType;
}

public void setName(String _name){
name = _name;
}

public void setModifier(String _modifer){
modifier = _modifer;
}

public void setParamTypes(List _paramTypes){
paramTypes = _paramTypes;
}

public void setReturnType(String _returnType){
returnType = _returnType;
}

public String getName(){
return name;
}

public String getModifier(){
return modifier;
}

public List getParamTypes(){
return paramTypes;
}

public String getReturnType(){
return returnType;
}

public String toString(){
String str =  "Modifier : " + modifier + "\n";
str += "Name : " + name + "\n";
str += "Params : " + paramTypes.toString() + "\n";
str += "Retrun : " + returnType;
return str;
}
}


[解析実行クラス MethodAnalyzer.java]
import java.lang.reflect.*;
import java.util.ArrayList;
import java.util.List;

public class MethodAnalyzer {
private String className;
public MethodAnalyzer(String _className){
className = _className;
}

/**
* クラスのメソッド一覧を取得する
* @param cls
* @return 
*/
private List getMethodList(Class cls){
List list = new ArrayList();
Method[] methods = cls.getMethods();
for(Method method : methods){
list.add(method);
}
return list;
}

/**
* 親クラスのメソッド一覧を取得する
* @param clas
* @return
*/
private List getParentMethodList(Class cls){
return getMethodList(cls.getSuperclass());
}

/**
* 第1引数から第2引数に存在するMethodを削除する
* @param list1
* @param list2
*/
private void removeMatchList(List list1, List list2){
for(Method method : list2){
if(list1.indexOf(method) != -1){
list1.remove(method);
}
}
}

/**
* リフレクションを用いて,クラスを解析する.
* @return MethodInfo[]
*/
public MethodInfo[] analyze(){
// メソッド情報を保持
MethodInfo[] methodInfos = null;
try{
// 親クラスには存在せず,自クラスのみに存在するメソッドを抽出
Class cls = Class.forName(className);
List methodList = getMethodList(cls);
removeMatchList(methodList, getParentMethodList(cls));

// メソッド情報配列の領域確保
methodInfos = new MethodInfo[methodList.size()];

for(int i = 0 ; i < methodList.size(); i++){
// メソッド情報配列の初期化
methodInfos[i] = new MethodInfo();

// 修飾子を取得&格納
methodInfos[i].setModifier(Modifier.toString(methodList.get(i).getModifiers()));

// 戻り値の型を取得&格納
methodInfos[i].setReturnType(methodList.get(i).getReturnType().getName());

// メソッド名を取得&格納
methodInfos[i].setName(methodList.get(i).getName());

// 引数の型を取得&格納
Class[] params = methodList.get(i).getParameterTypes();
List paramTypes = new ArrayList();
for(Class c : params){
paramTypes.add(c.getName());
}
methodInfos[i].setParamTypes(paramTypes); 
}
} catch (ClassNotFoundException cnfe){
cnfe.printStackTrace();
}
return methodInfos;
}

// 使用例
public static void main(String[] args) {
MethodAnalyzer ma = new MethodAnalyzer("Function");
MethodInfo[] mis = ma.analyze();

for(MethodInfo mi : mis){
System.out.println(mi.toString() + "\n");
} 
}
}



[実行結果]
Modifier : public
Name : service2
Params : []
Retrun : void

Modifier : public static
Name : service
Params : [java.util.List, int, byte]
Retrun : int