プログラマメモ2 - programmer no memo2

目次

[SWT windows]GetAsyncKeyStateでキーイベント処理 2008/09/25

Windowsです。SWTです。
GetAsyncKeyStateを使ってキーイベントを取得します。
下記のコードは、ALT + SHITFTキーの同時押しを念頭において作成しています。
ALTキーはVK_MENUなのかと勝手に類推して作成しています。

参考



import org.eclipse.swt.internal.win32.OS;

public class TestEvent {

public static void main(String[] args) {

key_alt_shift();
}

static void key_alt_shift() {

while (true) {

int s1 = OS.GetAsyncKeyState(OS.VK_MENU) & 0x8000;// alt key???
int s2 = OS.GetAsyncKeyState(OS.VK_SHIFT) & 0x8000;

System.out.println(s1 + " " + s2);

/*
* 同時押しかどうか....
*/
if (0 < s1 && 0 < s2) {
System.out.println("*** BINGO!!");
}

try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
}

}
}

いられ練習 2008/09/24



イラストレーターです。
地味目なグラデーションの効いたボタンを作る練習です。

僕がとった手順をおおまかに。
(1)線を使って、線幅(20ピクセルぐらい)、丸型線端でベースを作ります。
(2)1.で書いた線をオブジェクトのパスでパスのアウトラインでアウトラインにします。
(3)同じく、オブジェクトのパスでパスのオフセットで周りのラインを作成します。ひとつづつ作って外枠を最背面にしていきます。
(4)グラデーションを設定していきます。
(5)グループ化して、ドロップシャドウをつけます。

(1)の方法は書籍でその方法を知りました。
(4)のグラデーションは研究の余地ありです。
まず、作成したいサイト、アプリケーションの全体のカラーの決定から、明るい部分から暗い部分の設定をいかにやるかです。
RGBのスライドバーではなくHSBを使って、ルーチンにしないと全体のバランスが悪くなるのではないかと考えていますが、どうでしょうか。

自分がかっこいいと思ったサイトは、あちらこちらに微妙なグラデーションが効いている感じがします。その微妙さ加減(質感に対する配慮!?)が、センスなのかもと考えたりしてます。

あとこういったボタンぐらいでしたら、ある程度デザインが決定できたら、グラフィックツール(イラストレーターとかフォトショップなど)ではなく、専用のプログラムを作成したほうがいいのかなぁと考えたりしてます。それよりも、グラフィックツールに組こまれているスクリプトを使うのが正攻法かな。

フェードアウト - 消えてなくなってしまうもの 2008/09/21
2008/09/23



Javaです。画面をフェードアウトです。
最近消えてなくなってしまうものに興味があります。

mac osxですと、Window自体を透明にしてそれに描画する際に、AlphaCompositeを使って透明度をたかくしていくというアプローチをとっています。

windowsの場合、現状のJavaだとpure javaだと厳しそうです(やり方教えてほしい!!)。なので、wicocoというライブラリ
使って、描画するたびごとに、windowの透明度を設定するという方法をとりました。

注意点は、paintComponentでの描画処理の際にclearRectすることですかね...
この時での注意点、wicocoで、Win32FeatureManagerのsetVitrificationByColorKeyを使う場合、clearRectで使われるbackgroundカラーと背景を抜く色を同じにしておくこととか。

こういった効果をアプリケーションに取り込めると、ユーザの作業を中断させず関心を惹くということができるかなと考えています。

突然消えるのではなく、消えることがわかっているのでユーザはびっくりしないかなぁと。

Vitrification 2008/09/21

Vitrificationはガラス化されたという意味らしい。

Vitrification - Wikipedia, the free encyclopedia

こういうふうにした。java.lang.UnsatisfiedLinkError: xxxl: Can't find dependent libraries 2008/09/21

Windowsです。Javaです。

ネイティブなライブラリを読み込むようにして下記のようなエラーがでた場合。

java.lang.UnsatisfiedLinkError: no xxx in java.library.path

これだとパスに必要なDLLを置くか、DLLのある場所にパスを通せばよいわけです。
Javaコマンドに引数追加。
-Djava.library.path=


次に、パスは設定したが下記のようなエラーがでる場合。
java.lang.UnsatisfiedLinkError: xxxl: Can't find dependent libraries

これは、読み込んだライブラリがさらに他のライブラリに依存しているということになります。

じゃ何が足りないのかを探る方法です。
僕がとったアプローチです。
コードギア(ボーランド)のbcc55についているtdumpというコマンドを使ってDLL他の何に依存しているか調べます。



何やらぞろぞろダンプしてくれます。
それっぽい記述をみつけます。

Imports from XXXX.DLL

って感じで記述されているところがそれっぽいです。

つぎに、そのDLLがあればパスに追加してみます。
そのDLLをもっていなければ、みつけてきます。



こういった手順でとりあえず必要なものがそろうかもしれません。
乱暴なやりかたかも....

osxでjavax.swing.JWindow上のcursorが変わらない!? 2008/09/20

Javaです。osxです。自信がないのでとりあえず記録がわりにメモ。
osx上のjava1.5,JWindow上でcursorを変更しようとしても変更できなかった。JFrame上なら問題なかったんだけど。
何かまちがってるのかなぁ....
osxもいまだに10.4.xxだしなぁ...
windows上で同じように動作するコードを書きたいのに、こんなことにはまるとは...

以下、検証用コード。

import java.awt.Color;
import java.awt.Cursor;

import javax.swing.JFrame;
import javax.swing.JWindow;

public class TestCursol {

/**
* @param args
*/
public static void main(String[] args) {

JWindow frame = new JWindow();
//JFrame frame = new JFrame();
// frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
//frame.setFocusableWindowState(true);
frame.setBounds(100, 100, 300, 300);

System.out.println(frame.getCursor());

frame.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
frame.setVisible(true);

System.out.println(frame.getCursor());
}

}

MouseEventのisPopupTriggerを使って、JPopupMenuだすというふうにコードを書いていて、osxとwindowsで注意しないといけないことです。 2008/09/18

Javaです。
MouseEventのisPopupTriggerを使って、JPopupMenuだすというふうにコードを書いていて、osxとwindowsで注意しないといけないことです。

macの場合は、pressedでwindowsはreleasedで。

参考

intのキャストで失われるもの。 2008/09/18

Javaです。
intのキャストで失われるもの、それはあなたの自信です....
...

何度か失敗してるんですよね。これで...

import static java.lang.Math.*;
public class TestMathRound {

public static void main(String[] args) {

double s = 0.0;
for(double i=s;i<=1.0;i+=0.1){
System.out.printf("%.1f:%d:%d%n", i, (int)i, round(i));
}

}

}


参考
[ヅラド] Javaによる小数の切り捨て/切り上げ/四捨五入/intへのキャストなど

MouseEventでshift押し 2008/09/18

Javaです。

mouseEventが発生しているときに同時shiftキーが押されているかどうかは、

if ((e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0)

あとは、そのものずばり、
if (e.isShiftDown())

用意されているなら使わない手はない...

参考
Javaの部屋

AffineTransformにはinverseTransformなるメソッドがありまして。 2008/09/16

Graphics2Dを使って画面に描画した《もの》をマウスイベントをひろってその《もの》選択するようなアプリケーション作成したい場合、
そのコンポーネントのpaintとマウスイベントを素直に使う分には、MouseEventgetX(),MouseEventgetY()で、
描画位置が対になっているのでさほど苦労せず簡単に対応できます。

つぎにこの《もの》をAffineTransformを使って描画した場合、はて、どうしたものだろうと頭をひねっていたら、
AffineTransformにはinverseTransformなるメソッドがあることに気がつきます。

僕ははじめマウス変換をかけて表示したものとMouseEventgetX(),MouseEventgetY()対応させようと考えていたのですが、
発想を変えてMouseEventgetX(),MouseEventgetY()を逆変換かけて、
AffineTransformする前の《もの》と比較すればよいわけです。

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.geom.AffineTransform;
import java.awt.geom.NoninvertibleTransformException;
import java.awt.geom.Point2D;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class Test_AffineTransform_inverseTransform {

public static void main(String[] args) {

JFrame frame = new JFrame();
JPanel panel = new JPanel() {
MouseEvent mouseEvent;
boolean isPressed = false;
{
addMouseListener(new MouseAdapter() {

@Override
public void mousePressed(MouseEvent e) {
isPressed = true;
mouseEvent = e;
repaint();
}

@Override
public void mouseReleased(MouseEvent e) {
isPressed = false;
mouseEvent = null;
repaint();
}

});
}

@Override
protected void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D) g;

Rectangle rectangle = new Rectangle(30, 30, 70, 100);

AffineTransform affineTransform = new AffineTransform();
affineTransform.setToRotation(Math.toRadians(45));
affineTransform.translate(100, 0);
affineTransform.shear(0.2, 0.2);
g2d.setTransform(affineTransform);
//
g2d.setColor(Color.BLACK);
if (isPressed) {
if (mouseEvent != null) {

try {
Point2D p = affineTransform.inverseTransform(
new Point2D.Double(mouseEvent.getX(),
mouseEvent.getY()), null);
if (rectangle.contains(p))
g2d.setColor(Color.ORANGE);
} catch (NoninvertibleTransformException e) {
e.printStackTrace();
}

}

}
g2d.fill(rectangle);

}

};

frame.getContentPane().add(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.setBounds(100, 100, 500, 300);
frame.setVisible(true);

}

}

自分ドリブンの難しさ。 2008/09/16

お仕事しているともちろん誰かの期待に応えたいとか、お客さまの喜ぶ顔がみたいとかあると思います。
でもそれが受け身でありたくないんですよね。もっと攻めというかなんというか。まあ、自分ドリブンとかいってますけど。
なかなか難しいなと。

Perl - ref関数 - むずかしい... 2008/09/16

Perlです。

ハッシュをprintしようと思いました。

試しに、

%hash = (a=>"aa", b=>"bb");
print %hash."\n";

としましたが、もちろん出力されませんでした。

2/8


出力したければ、おそらくこうします。
%hash = (a=>"aa", b=>"bb");
while(($k, $v) = each %hash){
print "$k => $v\n";
}


次に、ハッシュだったら、という処理を行おうと考えました。
ref関数なるものがありました。

引数がリファレンスの場合に真、違う場合は偽を返します。

だそうです。

正直このリファレンスというのを理解していないので、下記のようなコードを書いて頭を悩ませました。

%hash = (a=>"aa", b=>"bb");

if(ref(%hash) eq 'HASH'){
print "i am hash\n";
}


何故判定されない!?

正しくは下記のように書きます。
%hash = (a=>"aa", b=>"bb");

if(ref(\%hash) eq 'HASH'){
print "i am hash\n";
}


きっとperlのリファレンスを僕が理解していなからです。

さらに、
%hash = (a=>"aa", b=>"bb");
$ref = \%hash;
if(ref($ref) eq 'HASH'){
print "i am hash\n";
}


リファレンス
リファレンス [Perl講座 -Smart]

[雑記]ANTLR 2008/09/13

この数日はANTLRで遊んでいます。
使っていぜん実装を断念したものをこれで実装すれば簡単じゃんということ思い出しました。
HL7のバージョン3ではない2.xでセグメントの並び順を検査するのどうしようかなぁと考えていたのですが、当時それほど要求がなく別にいいやと思っていて、実は頭の片隅ではちょっとくやしいなぁと思っていたのです。
定義書にはたしかBNFとかで書かれていたので、当時パーサージェネレーターを使えばいいなとは気がついていましたけど、根性なくてためしていなかったのもまた事実。

日頃から使える道具をみつけて磨くのは大事だなぁと。

RFC 2234風パーサーを目指してantlrで定義 その2 2008/09/13

CSVの処理系って以外と適当につくっているところが多いのかなと。
Javaならカンマで適当にStringのsplitを使うかStringTokenizerとかでやったりしている人が多いかも。
それで改行コードがフィールドに入ってたりすると、あわてたりするわけで。Orz...

ANTLR使って、CSVをListのListにして返すように定義してみました。

CSVのヘッダーってわざわざ定義する必要がないですよね。

呼び出しコード

package csv;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;

public class Test2 {

public static void main(String[] args) throws IOException,
RecognitionException, URISyntaxException {
URL url = Test2.class.getResource("test.csv");
FileInputStream fileInputStream = new FileInputStream(new File(url
.toURI()));
ANTLRInputStream inputStream = new ANTLRInputStream(fileInputStream);
CsvLexer lexer = new CsvLexer(inputStream);
CommonTokenStream tokens = new CommonTokenStream(lexer);
CsvParser parser = new CsvParser(tokens);
System.out.println(parser.file());
}
}


ANTLRのグラマーなほうCsv.g
ヘッダーとして使う使わないかはあとから決定することにしてグラマーには定義しませんでした。
たぶんうまくいっていると思うんだ。
grammar Csv;

@header {
package csv;
}
@lexer::header {
package csv;
}
// file = [header CRLF] record *(CRLF record) [CRLF]
file returns[List list]
scope {
List l;
}
@init {
$file::l = new ArrayList();
}

:r=record{$file::l.add($r.list);} ((LF | CRLF) r=record{$file::l.add($r.list);})*{
// System.out.println("*** *** file!!");
// System.out.println($file::l);
$list = $file::l;
};
// header = name *(COMMA name)
header
: name (COMMA name)*;
// record = field *(COMMA field)
record returns[List list]
scope {
List f;
}
@init {
$record::f = new ArrayList();
}
: l=field{ $record::f.add($l.text); } (COMMA l=field{$record::f.add($l.text);})*
{
$list = $record::f;
};

// name = field
name: field;
// field = (escaped / non-escaped)
field
: escaped {
}
| nonescaped {
};
// escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
escaped returns [String var]
scope {
StringBuilder b;
}
@init {
$escaped::b = new StringBuilder();
}
: DQUOTE (TEXTDATA{ $escaped::b.append($TEXTDATA); }
| COMMA{ $escaped::b.append($COMMA); }
| CR{ $escaped::b.append($CR); }
| LF{ $escaped::b.append($LF); }
| d=DQUOTE{ $escaped::b.append($d); } DQUOTE)* DQUOTE {

$var = $escaped::b.toString();
};
// non-escaped = *TEXTDATA
nonescaped: TEXTDATA* {
};

// COMMA = %x2C
COMMA
: ',';
// CR = %x0D ;as per section 6.1 of RFC 2234 [2]
CR : '\r';
// DQUOTE = %x22 ;as per section 6.1 of RFC 2234 [2]
DQUOTE : '"';
// LF = %x0A ;as per section 6.1 of RFC 2234 [2]
LF : '\n';
// CRLF = CR LF ;as per section 6.1 of RFC 2234 [2]
CRLF: CR LF;
// TEXTDATA = %x20-21 / %x23-2B / %x2D-7E
TEXTDATA
: (~(COMMA| CR| LF| DQUOTE))+
;

RFC 2234風パーサーを目指してantlrで定義 2008/09/13
2008/09/13

ふとCSVのパーサーをつくろうと再び考え、今回はANTLRを使ってみることに。
オレオレDSLをつくってみたいのでその練習もかねて。

改行をCRLF以外にLFでもうけつけるようにしてみたことと、
トークンTEXTDATAを定義するのCOMMA 、CR、LF、DQUOTEでないものはというふうに乱暴な定義にしてみた。
これうごくのだろうか。。。
まだ動作させていない....


grammar Csv;
@header {
package csv;
}
@lexer::header {
package csv;
}
// file = [header CRLF] record *(CRLF record) [CRLF]
file: record ((LF | CRLF) record)*;
// header = name *(COMMA name)
header
: name (COMMA name)*;
// record = field *(COMMA field)
record
: field (COMMA field)*;
// name = field
name: field;
// field = (escaped / non-escaped)
field
: escaped
| nonescaped;
// escaped = DQUOTE *(TEXTDATA / COMMA / CR / LF / 2DQUOTE) DQUOTE
escaped
: DQUOTE (TEXTDATA|COMMA|CR|LF|DQUOTE DQUOTE)* DQUOTE;
// non-escaped = *TEXTDATA
nonescaped: TEXTDATA*;

// COMMA = %x2C
COMMA
: ',';
// CR = %x0D ;as per section 6.1 of RFC 2234 [2]
CR : '\r';
// DQUOTE = %x22 ;as per section 6.1 of RFC 2234 [2]
DQUOTE : '"';
// LF = %x0A ;as per section 6.1 of RFC 2234 [2]
LF : '\n';
// CRLF = CR LF ;as per section 6.1 of RFC 2234 [2]
CRLF: CR LF;
// TEXTDATA = %x20-21 / %x23-2B / %x2D-7E
TEXTDATA
: (~(COMMA| CR| LF| DQUOTE))+
;

サイン、コサイン、タンジェント、アークタンジェント 2008/09/12

三角関数よくわからんです。

というわけで、コードを使えば少しは理解が進むかな。



a角をもとめるのは、逆正接関数(atan,アークタンジェント)を使います。


package t005;

import static java.lang.Math.*;

public class Test1 {

public static void main(String[] args) {

System.out.println(tan(toRadians(76)));
double d = tan(toRadians(76));

System.out.println(toDegrees(atan(d)));

System.out.println(A(60, 50));

System.out.println(Pythagorean(12, 5));

System.out.println(a(100, 400));

System.out.println("======");
System.out.println(a(12, 5));
double a = a(12, 5);
System.out.println(C(a, 5));
System.out.println(Pythagorean(12, 5));
System.out.println(B(a, 12));
System.out.println(A(a, C(a, 5)));
}

/**
* <p>
* a角の大きさをもとめます。
* </p>
*
* @param A辺
* @param B辺
* @return
*/
static double a(double A, double B) {
return toDegrees(atan(B / A));
}

/**
* <p>
* A辺をもとめます。
* </p>
*
* @param a 角度
* @param C辺
* @return
*/
static double A(double a, double C) {
return cos(toRadians(a)) * C;
}

/**
* <p>
* B辺をもとめます。
* </p>
*
* @param a 角度
* @param A辺
* @return
*/
static double B(double a, double A) {
return tan(toRadians(a)) * A;
}

/**
* <p>
* C辺をもとめます。
* </p>
*
* @param a 角度
* @param B辺
* @return
*/
static double C(double a, double B) {
return B / sin(toRadians(a));
}

/**
* <p>
* ピタゴラスの定理 A辺、B辺からC辺を求めます。
* </p>
*
* @param A
* @param B
* @return
*/
static double Pythagorean(double A, double B) {
return sqrt(pow(A, 2) + pow(B, 2));
}
}

GrowthList - 成長するよリスト 2008/09/11

Javaです。
java.util.Listのインターフェイスに、indexを指定できるsetメソッドがあります。
これは、インデックスが範囲外の場合、IndexOutOfBoundsException 例外を発生するようになっています。

気分的には、サイズが足りない場合は、補間してセットできたらいいかなぁと思うことがあります。

そんなクラスどこかにないかなぁというわけで、さがすとapache.commons.collections.list.GrowthListというのがありました。
このクラスに用意されているsetはIndexOutOfBoundsExceptionを発生させません。

Collections - Home

それで、自分のニーズにあわないのは、補間される値がnullであること(まあそういうものだろうという気はします。)

そう思ってうろうろ散策していたら、org.apache.commons.collections.list.LazyListというものがあり、
decorateする際の指定の仕方によっては値がない場合に任意のオブジェクトを返すことができることがわかりました。

参考
2006-07-03 - a geek

次に、getするだけでサイズが大きくなる可能性がある....
それはそれで仕方がないか....

以下コード

import java.util.List;

import org.apache.commons.collections.functors.ConstantFactory;
import org.apache.commons.collections.list.GrowthList;
import org.apache.commons.collections.list.LazyList;

public class TestCollection {

public static void main(String[] args) {

List<String> list = LazyList.decorate(new GrowthList(), ConstantFactory
.getInstance("o_o!"));

list.set(8, "aaa");
System.out.println(list);
System.out.println(list.get(5));
System.out.println(list);
}

}


結果
[null, null, null, null, null, null, null, null, aaa]
o_o!
[null, null, null, null, null, o_o!, null, null, aaa]

JTextPaneでコードアシストもどき 2008/09/10

前回、JTextFieldでコードアシストもどきができたので、今回は、JTextPaneでやってみた。
前回のコードのTextFieldの部分を書き換えたらそれでてokだった.....



コードは以下

import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;

import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.JTextPane;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;

public class TestCodeAssistModoki {

public static void main(String[] args) {

JFrame frame = new JFrame();
JTextPane textPane = new JTextPane();
textPane.getKeymap().addActionForKeyStroke(
KeyStroke.getKeyStroke("ctrl SPACE"), new Action() {

public void addPropertyChangeListener(
PropertyChangeListener listener) {

}

public Object getValue(String key) {
return null;
}
public boolean isEnabled() {
// !!!!!!!!
return true;
}

public void putValue(String key, Object value) {

}

public void removePropertyChangeListener(
PropertyChangeListener listener) {
}

public void setEnabled(boolean b) {
}

/**
* イベントが発生したコンポーネントでJWindowを表示してみる
*/
public void actionPerformed(ActionEvent e) {
System.out.println(e.getSource());
final JTextPane textPane = (JTextPane) e.getSource();
final int p = textPane.getCaretPosition();
Rectangle rectangle;
try {
rectangle = textPane.modelToView(p);

JPopupMenu popupMenu = new JPopupMenu();

ActionListener actionListener = new ActionListener() {

public void actionPerformed(ActionEvent e) {
try {
textPane.getDocument().insertString(p,
e.getActionCommand(), null);
} catch (BadLocationException e1) {
e1.printStackTrace();
}

}

};
System.out.println(rectangle);
popupMenu.add("テストです").addActionListener(
actionListener);
popupMenu.add("0_0!").addActionListener(
actionListener);
popupMenu.add("^_^!").addActionListener(
actionListener);
popupMenu.add("o_o!").addActionListener(
actionListener);
popupMenu.show(textPane, rectangle.x, rectangle.y
+ rectangle.height);
} catch (BadLocationException e1) {
e1.printStackTrace();
}

}
});

frame.getContentPane().add(textPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.setVisible(true);

}
}

JTextFieldでコードアシストもどき 2008/09/10

Javaです。Swingです。そしてJTextFieldです。

JFaceでコードアシストをためしてみていい感じだったので、今度は、swingでできないかとチャレンジ。



まず、getKeymapでKeyStrokeの登録。"ctrl SPACE"で行う。
Actionで、textFiledでイベントが発生した場所から、実際のポップアップを表示を特定します。
で、ここではた悩む。とりあえず、API調べてみて、よさげなものをみつけて試してみました。
getCaretPositionを使って現在のビームの位置をもとめます。さらに、modelToViewメソッドを使ってキャレット位置からViewの座標に変換(※この説明が正しいかいささか自信ないですがとりあえずうまくいったようなので)この値を使ってポップアップが表示される位置をもとめます。

modelToViewはRectangleを返します。

ポップアップメニューを使ってコードアシストもどきを表現して選択されたら、そのアクションでtextFieldのほうに値を挿入します。

次はJTextPaneで試してみましょうか。

import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeListener;

import javax.swing.Action;
import javax.swing.JFrame;
import javax.swing.JPopupMenu;
import javax.swing.JTextField;
import javax.swing.KeyStroke;
import javax.swing.text.BadLocationException;

public class TestKeyStroke {

public static void main(String[] args) {

JFrame frame = new JFrame();
JTextField textField = new JTextField();
textField.getKeymap().addActionForKeyStroke(
KeyStroke.getKeyStroke("ctrl SPACE"), new Action() {

public void addPropertyChangeListener(
PropertyChangeListener listener) {

}

public Object getValue(String key) {
return null;
}
public boolean isEnabled() {
// !!!!!!!!
return true;
}

public void putValue(String key, Object value) {

}

public void removePropertyChangeListener(
PropertyChangeListener listener) {
}

public void setEnabled(boolean b) {
}

/**
* イベントが発生したコンポーネントでJWindowを表示してみる
*/
public void actionPerformed(ActionEvent e) {
System.out.println(e.getSource());
final JTextField textField = (JTextField) e.getSource();
final int p = textField.getCaretPosition();
Rectangle rectangle;
try {
rectangle = textField.modelToView(p);

JPopupMenu popupMenu = new JPopupMenu();

ActionListener actionListener = new ActionListener() {

public void actionPerformed(ActionEvent e) {
try {
textField.getDocument().insertString(p,
e.getActionCommand(), null);
} catch (BadLocationException e1) {
e1.printStackTrace();
}

}

};
System.out.println(rectangle);
popupMenu.add("テストです").addActionListener(
actionListener);
popupMenu.add("0_0!").addActionListener(
actionListener);
popupMenu.add("^_^!").addActionListener(
actionListener);
popupMenu.add("o_o!").addActionListener(
actionListener);
popupMenu.show(textField, rectangle.x, rectangle.y
+ rectangle.height);
} catch (BadLocationException e1) {
e1.printStackTrace();
}

}
});

frame.getContentPane().add(textField);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.setVisible(true);

}
}

antlr grammarでpackageの指定 2008/09/07

試したのはantlrのバージョン3です。

出力されるJavaコードがいつまでもデフォルトではねー
というわけで、パッケージの指定についてです。


@header {
package xxx;
}
@lexer::header {
package xxx;
}


これでできるJavaファイルはパッケージ指定がされます。
注意一点、lexerの指定とparserの指定は別であることに注意です。

参考
Antlrをさらに使ってみる

はしごだか 2008/09/07

はしごだか



文字化けは、悩みの種

コードアシストしてくれるアプリケーションを作るための手習い その2- eclipse,JFace,swt 2008/09/06

前回に続いて実験。

(1)
eclipseでコード書いているとctrl + spaceでコードアシストしてくれるので、ためしみました。
キーストロークで"Ctrl+Space"するとよいようです。

(2)
入力された値によって提案するもんもんを変更したい場合。
org.eclipse.jface.fieldassist.IContentProposalProviderを工夫すればよい感じ。
もっといいコードの書き方があるかも。
これが実現できると、入力している語の続きの文字を提案できるから入力を軽減できますね。

実行はこんな感じです。



コードです。

import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.ParseException;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.IControlContentAdapter;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;

/**
* コードアシストの手習い
*
* @author nakawakashigeto
*
*/
public class Main extends ApplicationWindow {
public Main() {
super(null);
}

public static void main(String[] args) {

Main window = new Main();
window.setBlockOnOpen(true);
window.open();
Display.getCurrent().dispose();
}

protected Control createContents(Composite parent) {

Text text = new Text(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
IControlContentAdapter contentAdapter = new TextContentAdapter();

/*
* 提案する内容提供します。
*/
IContentProposalProvider provider = new IContentProposalProvider() {

public IContentProposal[] getProposals(String content, int pos) {

return createProposals(content, pos);
}

};

/*
* ctrl + spaceでコードアシストするようにしています。
*/
ContentProposalAdapter contentProposalAdapter = new ContentProposalAdapter(
text, contentAdapter, provider, keystroke("Ctrl+Space"), null);

return parent;
}

/**
* <p>
* 入力された文字列が「あなたは」で終わっている場合に提案します。
* </p>
*
* @param content
* @param pos
* @return
*/
static public IContentProposal[] createProposals(final String content,
final int pos) {

if (content.length() == 0 || !(0 < (pos - 3))
|| "あなたは".equals(content.substring(pos - 3, pos))) {
return new IContentProposal[] {};
}

String[] strings = { "愉快な人","ちょっとあぶない", "いい人", "いやな人", "楽しい人"};

IContentProposal[] proposals = new IContentProposal[strings.length];
for (int i = 0; i < proposals.length; i++) {
final String s = strings[i];
proposals[i] = new IContentProposal() {
public String getContent() {
return "、ずばり" + s;
}

public int getCursorPosition() {
return 0;
}

public String getDescription() {
return "あなたは" + s;
}

public String getLabel() {
return s;
}
};

}

return proposals;
}

static KeyStroke keystroke(String s) {
try {
return KeyStroke.getInstance(s);
} catch (ParseException e) {
e.printStackTrace();
}
return null;
}

}

コードアシストしてくれるアプリケーションを作るための手習い - eclipse,JFace,swt 2008/09/06
2008/09/06

Javaです。

身近にコードアシストを使ったアプリケーションを作っている方がいて、それを見ていいなxと思ったので練習です。
コードアシストって、いろいろ応用範囲がありそうですね。

話変わって、個人的には、あと、別に文字から文字へ変換させるのではなく、絵がでて絵から選択して文字列にするとかでもおもしろそうです。

参考



使用したeclipseのバージョン3.2.2
ライブラリは、


テキストフィールドで$と入力すると補完候補がでてきます。

以下コードです。
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.IControlContentAdapter;
import org.eclipse.jface.fieldassist.SimpleContentProposalProvider;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.window.ApplicationWindow;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;

public class Main extends ApplicationWindow {
public Main() {
super(null);
}

public static void main(String[] args) {

Main window = new Main();
window.setBlockOnOpen(true);
window.open();
Display.getCurrent().dispose();
}

protected Control createContents(Composite parent) {

Text text = new Text(parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
IControlContentAdapter contentAdapter = new TextContentAdapter();
// IContentProposalProvider provider = new IContentProposalProvider() {
//
// public IContentProposal[] getProposals(String arg0, int arg1) {
// return null;
// }
//
// };

IContentProposalProvider provider = new SimpleContentProposalProvider(
new String[] { "1", "2", "o_o!" });

ContentProposalAdapter contentProposalAdapter = new ContentProposalAdapter(
text, contentAdapter, provider, null, new char[] { '$' });

// contentProposalAdapter
// .setProposalAcceptanceStyle(ContentProposalAdapter.PROPOSAL_REPLACE);

return parent;
}
}

XPath生成もどきもどきもどき 2008/09/05

Javaです。
既に出来上がったXMLをパースするプログラムを書く際に、必要な箇所だけをXPathとかでとりたいなぁというときに、パスが既に存在するXMLから生成できたら便利かなぁ、というわけで作成。

不完全だけど、パスの雰囲気はでてるかな。

package xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Set;
import java.util.TreeSet;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class TestXPathGenUtils {

public static void main(String[] args) throws URISyntaxException,
FileNotFoundException, SAXException, IOException,
ParserConfigurationException {

URL url = TestXPathGenUtils.class.getResource("test.xml");

File file = new File(url.toURI());
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();

Set<String> set = new TreeSet<String>();
XPathGenUtils.generatePath(builder.parse(new InputSource(new FileInputStream(file))), set);

for (String s : set) {
System.out.println(s);
}

}

}


package xml;

import java.util.Set;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* <p>
* XPath生成もどき
* </p>
*
* @author nakawaka
*
*/
public abstract class XPathGenUtils {

public static void generatePath(Document document, Set<String> set) {
innerGeneratePath(document.getDocumentElement(), set);
}

public static void generatePath(Element element, Set<String> set) {
innerGeneratePath(element, set);
}

static void innerGeneratePath(Node node, Set<String> set) {
switch (node.getNodeType()) {

case Node.DOCUMENT_NODE:
generatePath(((Document) node).getDocumentElement(), set);
return;
case Node.ELEMENT_NODE:

Element element = (Element) node;

NamedNodeMap namedNodeMap = element.getAttributes();
for (int i = 0; i < namedNodeMap.getLength(); ++i) {
innerGeneratePath(namedNodeMap.item(i), set);
}

NodeList nodeList = element.getChildNodes();
for (int i = 0; i < nodeList.getLength(); ++i) {
innerGeneratePath(nodeList.item(i), set);
}

return;
case Node.TEXT_NODE:
set.add(p(node, new StringBuilder()));
return;
case Node.CDATA_SECTION_NODE:
return;
case Node.ENTITY_REFERENCE_NODE:
return;
case Node.ATTRIBUTE_NODE:
set.add(p(node, new StringBuilder()));
return;
}

}

public static String p(Node node, StringBuilder builder) {

// System.out.println(parent.getNodeName());

if (node.getNodeType() == Node.DOCUMENT_NODE)
return builder.toString();

switch (node.getNodeType()) {
case Node.TEXT_NODE:
builder.insert(0, "/" + "text()");
return p(node.getParentNode(), builder);
case Node.CDATA_SECTION_NODE:
break;
case Node.ENTITY_REFERENCE_NODE:
break;
case Node.ATTRIBUTE_NODE:
builder.insert(0, "/@" + node.getNodeName() + "");
Attr attr = (Attr) node;
return p(attr.getOwnerElement(), builder);
}

builder.insert(0, "/" + node.getNodeName());
return p(node.getParentNode(), builder);
}
}


出来上がったパスは下のコードで実行
package xml;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Document;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

public class TestReadXml {

public static void main(String[] args) throws URISyntaxException,
ParserConfigurationException, FileNotFoundException, SAXException,
IOException, XPathExpressionException {

URL url = TestReadXml.class.getResource("test.xml");

File file = new File(url.toURI());
DocumentBuilder builder = DocumentBuilderFactory.newInstance()
.newDocumentBuilder();
Document document = builder.parse(new InputSource(new FileInputStream(
file)));

System.out.println(string(document, compile("パステストここに入れる")));
}

static final XPath xpath = XPathFactory.newInstance().newXPath();

static XPathExpression compile(String expression)
throws XPathExpressionException {
return xpath.compile(expression);
}

static String string(Document root, XPathExpression expr)
throws XPathExpressionException {
return (String) expr.evaluate(root, XPathConstants.STRING);
}

}

osxでjava - resizeしてチラつくについて 2008/09/04

Javaです。osxで動作するjavaです。

JFrameを使ってコードを試していてふと気になったことです。
このフレームをsetSizeして大きさを変更するとどうもflickerが発生しました。

おもしろいことに、osxのJFrameにデフォルトでついている右はしのresizeアイコンで大きさを変えるとちらつかないです。


理由が知りたくて、実行中に例外を発生させてどういった経路でペイントが走るのかみてみました。
なんとなく違うのはわかったのですが、どう解消すればよいのかノーアイデアです....

ちらつくときの例外

at t004a.TestResizableWindow$1.paintComponent(TestResizableWindow.java:65)
at javax.swing.JComponent.paint(JComponent.java:1006)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:559)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:34)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1722)
at javax.swing.JFrame.update(JFrame.java:393)
at sun.awt.RepaintArea.updateComponent(RepaintArea.java:267)
at sun.awt.RepaintArea.paint(RepaintArea.java:233)
at apple.awt.ComponentModel.handleEvent(ComponentModel.java:251)
at apple.awt.CWindow.handleEvent(CWindow.java:176)
at java.awt.Component.dispatchEventImpl(Component.java:4126)
at java.awt.Container.dispatchEventImpl(Container.java:2068)
at java.awt.Window.dispatchEventImpl(Window.java:1791)
at java.awt.Component.dispatchEvent(Component.java:3885)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:463)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)


ちらつかないときの例外
実際のペイント処理までが短いです。
at t004a.TestResizableWindow$1.paintComponent(TestResizableWindow.java:65)
at javax.swing.JComponent.paint(JComponent.java:1006)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at javax.swing.JLayeredPane.paint(JLayeredPane.java:559)
at javax.swing.JComponent.paintChildren(JComponent.java:843)
at javax.swing.JComponent.paint(JComponent.java:1015)
at java.awt.GraphicsCallback$PaintCallback.run(GraphicsCallback.java:34)
at sun.awt.SunGraphicsCallback.runOneComponent(SunGraphicsCallback.java:60)
at sun.awt.SunGraphicsCallback.runComponents(SunGraphicsCallback.java:97)
at java.awt.Container.paint(Container.java:1722)
at apple.awt.ComponentModel$1.run(ComponentModel.java:351)
at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:199)
at apple.awt.CToolkit$CPeerEvent.dispatch(CToolkit.java:1116)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:461)
at java.awt.EventDispatchThread.pumpOneEventForHierarchy(EventDispatchThread.java:269)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:190)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:184)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:176)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:110)



使用したコード
package t004a;

import java.awt.BorderLayout;
import java.awt.Color;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestResizableWindow {

public static void main(String[] args) {

final JFrame window = new JFrame();
class DragMove extends MouseAdapter implements MouseMotionListener {

Point pressed;

public void mouseDragged(MouseEvent e) {
// System.out.println(e);
if (this.pressed != null) {
int dw = pressed.x - e.getX();
int dh = pressed.y - e.getY();
window.setSize(window.getWidth() - dw, window.getHeight()
- dh);
}
this.pressed = e.getPoint();
}

public void mouseMoved(MouseEvent e) {

}

@Override
public void mouseReleased(MouseEvent e) {
this.pressed = null;
}

@Override
public void mouseExited(MouseEvent e) {
this.pressed = null;
}
}

JPanel panel = new JPanel(){
{
setOpaque(true);
add(new JButton("aaaaaaaaaa"));
}

@Override
protected void paintComponent(Graphics g) {
try{
if(true) throw new RuntimeException();
}catch(Exception e){
e.printStackTrace();
}
super.paintComponent(g);
int x2 = this.getWidth();
int y2 = this.getHeight();
System.out.println("*** ");
Graphics2D g2d = (Graphics2D)g;
g2d.clearRect(0,0, x2, y2);
g2d.setColor(Color.BLUE);
g2d.drawLine(0, 0, x2, y2);
}

};
window.getContentPane().setLayout(new BorderLayout());
window.getContentPane().add(panel, BorderLayout.CENTER);

DragMove dragMove = new DragMove();
window.addMouseListener(dragMove);
window.addMouseMotionListener(dragMove);
window.setBounds(100, 100, 300, 300);
window.setAlwaysOnTop(true);
window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
window.setVisible(true);
}

}

ラジアンから度、度からラジアン 2008/09/04

Javaです。
ラジアンから度、度からラジアンのためのユーティリティメソッドです。

package t004a;

public class TestRadAndDegree {

/**
* ラジアンから度に変換します。
*
* @param radian
* @return
*/
public static double radsToDegrees(double radian) {
return radian * (180f / Math.PI);
}

/**
* 度からラジアンに変換します。
*
* @param degrees
* @return
*/
public static double degreesToRads(double degrees) {
return degrees * (Math.PI / 180f);
}

public static void main(String[] args) {

double d = degreesToRads(90);
System.out.println(d);
double d2 = radsToDegrees(d);
System.out.println(d2);

long t = System.currentTimeMillis();
for(int i=0;i<100000000;i++){
radsToDegrees(90);
}
System.out.println((System.currentTimeMillis() - t)/1000d + "sec");
}
}

[雑記]あとからみて後悔するようなコードを書かないように 2008/09/04

あとからみて後悔するようなコードを書かないようにしたい。
最近、多いのは、過去の自分の《置き土産》が、現在の自分を苦しめるというパターン。
コードは簡潔に、意図がわかるようにしたい。フラグをあちらこちらに置かないようにしたい。
最悪なのは、あるフラグの効果を打ち消すためのフラグを置くこと。

確信がないコードは書かないようにしたい。何となく動くからというコードを書かないようにしたい。
失敗は素直に認めたい。コードから死臭がし始めたら、書き直したほうがよい。

headlessには気をつけろ!! 2008/09/04

Javaです。

あまりないことですが、クライアントアプリケーションをサーバーで動かそうとすると、
headlessなんとか例外でます。

GUI環境でチェックする場合は、VM引数にしてテストしてからサーバで動かそう。

-Djava.awt.headless=true

org.jruby.Rubyをシンクロして使う。 2008/09/04

JRubyです。

org.jruby.Rubyオブジェクトを使いまわしてスクリプトを実行する際に、グローバル変数を使ってJRubyに値を渡すとき、org.jruby.Rubyをシンクロしないといけないよというお話。

以下、スレッドをぽこぽこ起こして、org.jruby.Rubyにグローバル変数経由で値をわたすと意図せずまざります。
org.jruby.Rubyを生成するコストはばかにならないので、newしてぽこぽこ生成したくはないです。

あたりまえといえばあたりまえですが、使うorg.jruby.Rubyをsynchronizedブロックにしてしまいます。

テスト用のjrubyのスクリプト

p $a + ' ' + $b + ' ' + $c + ' ' + $d + ' ' + $e + ' ' + $f + ' ' + $g + ' ' + $h


このスクリプトの意図はグローバル変数が途中で書き換わると、値に一貫性がなくなることをチェックするためです。

シンクロしないとものの見事に、一貫性がなくなることが確認されます。

以下うまくいったコード

package test_jruby;

import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.bsf.util.IOUtils;
import org.jruby.Ruby;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.GlobalVariable;
import org.jruby.runtime.builtin.IRubyObject;

public class Test_multi {

public static void main(String[] args) throws IOException {

final Ruby ruby = Ruby.newInstance();
final String script = script("test_multi_glv_1.jruby", "MS932");
for (int i = 0; i < 10000; i++) {

final int FI = i;
new Thread(new Runnable() {

@Override
public void run() {

String result = evalByJRuby_GLV(ruby, script,
new Object[][] { { "a", "" + FI },
{ "b", "" + FI }, { "c", "" + FI },
{ "d", "" + FI }, { "e", "" + FI },
{ "f", "" + FI }, { "g", "" + FI },
{ "h", "" + FI } });

System.out.println(result);
}
}).start();
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}

}

static public String script(String filename, String enc) throws IOException {
String script = IOUtils.getStringFromReader(new InputStreamReader(
ExperimentationJRubyScriptBase.class
.getResourceAsStream(filename), enc));
return script;
}

/**
* <p>
* Rubyスクリプトにグローバル変数で値を渡します。
* </p>
*
* @param ruby
* @param script
* @param objects
* @return
*/
public static String evalByJRuby_GLV(Ruby ruby, String script,
Object[][] objects) {

synchronized (ruby) {

if (objects != null) {
for (int i = 0; i < objects.length; i++) {
Object[] objects2 = objects[i];
if (2 <= objects2.length) {

ruby.defineVariable(new GlobalVariable(ruby, "$"
+ objects2[0].toString(), JavaEmbedUtils
.javaToRuby(ruby, objects2[1])));
}
}

}
IRubyObject result = ruby.evalScriptlet(script);
ruby.tearDown();
if (result instanceof org.jruby.RubyString) {
org.jruby.RubyString s = (org.jruby.RubyString) result;
return s.getUnicodeValue();
}
return result.toString();

}

}
}


以下うまくいかなかったコード
org.jruby.RubyのdefineVariableをする間隔で、Tread.sleepさせるとさらにまざる感じがします。

package test_jruby;

import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.bsf.util.IOUtils;
import org.jruby.Ruby;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.GlobalVariable;
import org.jruby.runtime.builtin.IRubyObject;

public class Test_multi {

public static void main(String[] args) throws IOException {

final Ruby ruby = Ruby.newInstance();
final String script = script("test_multi_glv_1.jruby", "MS932");
for (int i = 0; i < 10000; i++) {

final int FI = i;
new Thread(new Runnable() {

@Override
public void run() {

String result = evalByJRuby_GLV(ruby, script,
new Object[][] { { "a", "" + FI },
{ "b", "" + FI }, { "c", "" + FI },
{ "d", "" + FI }, { "e", "" + FI },
{ "f", "" + FI }, { "g", "" + FI },
{ "h", "" + FI } });

System.out.println(result);
}
}).start();
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
}

}

static public String script(String filename, String enc) throws IOException {
String script = IOUtils.getStringFromReader(new InputStreamReader(
ExperimentationJRubyScriptBase.class
.getResourceAsStream(filename), enc));
return script;
}

/**
* <p>
* Rubyスクリプトにグローバル変数で値を渡します。
* </p>
*
* @param ruby
* @param script
* @param objects
* @return
*/
public static String evalByJRuby_GLV(Ruby ruby, String script,
Object[][] objects) {

// synchronized (ruby) {

if (objects != null) {
for (int i = 0; i < objects.length; i++) {
Object[] objects2 = objects[i];
if (2 <= objects2.length) {

ruby.defineVariable(new GlobalVariable(ruby, "$"
+ objects2[0].toString(), JavaEmbedUtils
.javaToRuby(ruby, objects2[1])));
}
}

}
IRubyObject result = ruby.evalScriptlet(script);
ruby.tearDown();
if (result instanceof org.jruby.RubyString) {
org.jruby.RubyString s = (org.jruby.RubyString) result;
return s.getUnicodeValue();
}
return result.toString();

// }

}
}

ルビーの練習 - メソッド 2008/09/04

JRubyです。


いまいちクロージャーとブロックとメソッドの仕組みがわかってないです。

とりあえず、メソッドで実験。
メソッドをハッシュに格納してとりだして利用するって感じのことがしたいのでした。
callを使うといいようです。callを使わないでも実行できないのかしら。

サンプル
#
def hello( name )
p "hello, " + name
end

hello "ugo!!"

hello_m = method :hello
(method :hello).call "ugo"
hello_m.call "o_o!"
hello("-_-!")
n = {"hello" => hello_m , "hey" => :hello }
p hello_m
n['hello'].call("OKo_o!")
p n['hey']


結果
"hello, ugo!!"
"hello, ugo"
"hello, o_o!"
"hello, -_-!"
#<Method: Object#hello>
"hello, OKo_o!"
:hello



Javaコード
package test_jruby;

import java.io.IOException;
import java.io.InputStreamReader;

import org.apache.bsf.util.IOUtils;
import org.jruby.Ruby;
import org.jruby.javasupport.JavaEmbedUtils;
import org.jruby.runtime.GlobalVariable;
import org.jruby.runtime.builtin.IRubyObject;

public class Test_Executor {

public static void main(String[] args) throws IOException {

final Ruby ruby = Ruby.newInstance();
final String script = script("test_method.jruby", "MS932");
evalByJRuby_GLV(ruby, script, new Object[][] {});

}

static public String script(String filename, String enc) throws IOException {
String script = IOUtils.getStringFromReader(new InputStreamReader(
ExperimentationJRubyScriptBase.class
.getResourceAsStream(filename), enc));
return script;
}

/**
* <p>
* Rubyスクリプトにグローバル変数で値を渡します。
* </p>
*
* @param ruby
* @param script
* @param objects
* @return
*/
public static String evalByJRuby_GLV(Ruby ruby, String script,
Object[][] objects) {

synchronized (ruby) {

if (objects != null) {
for (int i = 0; i < objects.length; i++) {
Object[] objects2 = objects[i];
if (2 <= objects2.length) {

ruby.defineVariable(new GlobalVariable(ruby, "$"
+ objects2[0].toString(), JavaEmbedUtils
.javaToRuby(ruby, objects2[1])));
}
}

}
IRubyObject result = ruby.evalScriptlet(script);
ruby.tearDown();
if (result instanceof org.jruby.RubyString) {
org.jruby.RubyString s = (org.jruby.RubyString) result;
return s.getUnicodeValue();
}
return result.toString();

}

}
}

角度の練習 2008/09/03

回転の練習です。

参考にしたのはJavaによる図形処理入門 - 1998 - プログラマの本棚の時計のプログラムです。




package t004a;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JWindow;

public class TestKAITEN {

public static void main(String[] args) {

final JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);
frame.setBackground(new Color(200, 200, 170, 190));
final JPanel panel = new JPanel() {

@Override
protected void paintComponent(Graphics g) {
int w = getWidth();
int h = getHeight();
Graphics2D g2 = (Graphics2D) g;
g2.clearRect(0, 0, getWidth(), getHeight());
g2.setColor(Color.BLACK);

g2.drawLine(w / 2, 0, w / 2, h);
g2.drawLine(0, h / 2, w, h / 2);

float dash[] = { 10.0f, 3.0f };
final BasicStroke dashStroke = new BasicStroke(1.0f,
BasicStroke.CAP_BUTT, BasicStroke.JOIN_MITER, 3.0f,
dash, 0.0f);
final BasicStroke stroke = new BasicStroke(1.f);
int x;
int y;
int ang = 60;
final double RAD = Math.PI / 180d;//radian
int r = 200;// 半径

Point center = new Point(w / 2, h / 2);// 中心点
for (int i = 1; i <= 12; i++) {
x = (int) ((r) * Math.cos(RAD * ang) + (w / 2));
y = (int) ((r) * Math.sin(RAD * ang) + (h / 2));
g2.drawString("" + ang, x, y);

g2.setStroke(dashStroke);
// 線が重ならないようにする
if ((ang % 90) != 0)
g2.drawLine(center.x, center.y, x, y);
ang -= 30;
}
g2.setStroke(stroke);
g2.drawArc(center.x - r, center.y - r , r*2, r*2, 0, 360);

}

};

frame.getContentPane().add(panel);
frame.setLocation(100, 200);
frame.setSize(500, 500);
frame.setVisible(true);
}

}

[雑記]さしせまった要望 2008/09/03
2008/09/03

最近、DSLって何だろうって考えることが多いけど、具体的にこれだというものを掴めていない。
さしせまった必要性が思い浮かばないからだと思うけど。


「明日の言語」について考えている



DSLについていろいろと。
誰が幸せになるのだろうか。設定がらくとか、納期が短くなるとか。まちがいがなくなるとか。

JavaからJRubyへStringしてgetBytesしたい 2008/09/03

JavaからStringをJRubyに渡してgetBytesしたい。

こんな感じにしてみた。

Java::java::lang::String::new(s).getBytes("shift_jis").length

直接、s.getBytes()みたいにしたいんだけど.....

mac osx上のjavaでフレームの背景をぬく 2008/09/02

mac osx上のjavaでフレームの背景をぬく

package t004a;

import java.awt.Color;
import java.awt.Graphics;
import java.awt.Polygon;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class TestTransparentFrame {

public static void main(String[] args) {

// 透明度100にしたフレームに
// 何かしら描画したパネルをのせる。
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setAlwaysOnTop(true);

frame.setBackground(new Color(0,0,0,0));
JPanel panel = new JPanel() {

@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);

g.setColor(Color.ORANGE);

g.fillPolygon(new Polygon(new int[] { 3, 600, 600, 0 },
new int[] { 0, 300, 600, 200 }, 4));
}

};

frame.getContentPane().add(panel);
frame.setBounds(100, 200, 600, 600);
frame.setVisible(true);
}

}


groovyのクロージャ 練習 2008/09/02

Groovyです。
クロージャです。


Groovyのクロージャの書き方が好きかも。

def localMethod() {
def v = new Date()
return { println v }
}

def clos = localMethod()
Thread.sleep(3000)

println new Date()

// 実行
clos()


結果
Tue Sep 02 22:05:48 JST 2008
Tue Sep 02 22:05:45 JST 2008


次に下記のような書き方ができることに僕は何かしらの可能性をみているのだった。

def c = [
"a1": { println "==>a1"},
"a2": { println "==>a2"},
"a3": { println "==>a3"}
]
c.a1()
c['a2']()
def clos = c['a3']
clos()


結果
==>a1
==>a2
==>a3


ふたつめのこのc['a2']()の書き方がかっこいいと思うのだけど。

あと僕がJSONにたいしてなんとなく可能性をみているのは、キー:値の値にやはりプログラムを載せれそうなところなんだよね。

org.jruby.Rubyのイニシャルコスト 2008/08/31

JRubyです。

どうもjavaからJRubyにスクリプトを喰わせて実行させる際に、カクカクとなってしまいました。何度やってもカクカクするので、どうしてこんなに遅いんだろうと思って、いろいろ試してみてどうも毎回、org.jruby.Ruby.newInstance()するのがいけないようです。

下手すると 充分回数実行すると,outofmemoryが....

org.jruby.Rubyを使い回した場合、ものすごーくはやくなりました。

しかし、別の問題がおきました。
実ははじめ、スクリプト側に値を渡すときに、ruby.defineVariableを使っていて、毎回、newしていたので、別にいいやと考えていたのですが、グローバル変数であるなら複数回の呼び出しがある場合には、スクリプト側に値を渡すに不向き(値がまざってしまうから)ということになってしまいます。

bsf経由でJrubyを使うときも、同じ問題(初期化コストが馬鹿にならない)がありそうな気がします。

org.jruby.javasupportパッケージのJavaUtilとJavaEmbedUtils 2008/08/31

JRubyです。

しばらく、Javaからスクリプトを呼び出すところで試行錯誤しています。
いろいろ試していてまあこれでいいかなぁと思ったところで、困ったことが。

Javaから生成されたインスタンスを渡すのですが、JRuby側でどうしてもそのインスタンスのメソッドにアクセスできなかったのです。

NoMethodErrorとかでてしまいました。

前できたのにどうしてかなぁと悩んでいましたら、Java側のオブジェクトをJRuby側に変換する際に使用していたユーティリィがJavaUtil.convertJavaToRubyであることに気がつきました。

Java側の機能をそのまま引き継ぎたい場合は、JavaEmbedUtils.javaToRubyを使うのが正しいようです(多分)。

ちなみに,JavaEmbedUtils.javaToRubyの実装みてなるほどとわかるのですが、内部では、JavaEmbedUtils.javaToRubyを使用しています。そこで変換されたオブジェクトがorg.jruby.javasupport.JavaObjectであった場合,Java.wrapでラップするとかいう処理になっています。

あと、JavaEmbedUtils.javaToRubyは、2つ引数と、3つ引数があるのですが、Classを指定する3つ引数をわざわざ使わなくても2つ引数でいいようです。内部で、object.getClass()して3つ引数のメソッドを使っているので。

結論は、僕は、JavaEmbedUtils.javaToRubyを使うでしょうかね。