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

createImage 2008/07/29

BufferedImageの作り方。
JPanelとかJCompoentあたりにあるcreateImageを使うといのもありですが、下記のようにしてもできました。
createImageはjava.awt Compoentを継承しているクラスにあるメソッドです。

GraphicsEnvironment graphicsEnvironment = GraphicsEnvironment
.getLocalGraphicsEnvironment();
GraphicsDevice graphicsDevice = graphicsEnvironment
.getDefaultScreenDevice();
dbImage = graphicsDevice.getDefaultConfiguration()
.createCompatibleImage(w, h);

poj 2242 - 外接円の半径を求めて 2008/07/28



3点の座標が与えられます。その点をすべて通る円を求めるって感じだと思います。
正直、円周を求める式とかおぼえてないので、wikipediaたよりで、ときました。
あとキーワードは外接円ですかね。



二次元座標上での二点間の距離を求めます。それから外接円の半径を求めます。そうすると、円の半径がわかるのでそれから円周の長さを求めます。

package p2242;

import java.util.Scanner;

public class Main {

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
double x1 = scanner.nextDouble();
double y1 = scanner.nextDouble();
double x2 = scanner.nextDouble();
double y2 = scanner.nextDouble();
double x3 = scanner.nextDouble();
double y3 = scanner.nextDouble();
System.out.printf("%.2f%n", circumradius(x1, y1, x2, y2, x3, y3));
}

}

static double distance(double x1, double y1, double x2, double y2) {
return Math.sqrt(Math.pow(x2 - x1, 2) + Math.pow(y2 - y1, 2));
}

static double circumradius(double x1, double y1, double x2, double y2,
double x3, double y3) {
double a = distance(x1, y1, x2, y2);
double b = distance(x2, y2, x3, y3);
double c = distance(x3, y3, x1, y1);

double A = a * b * c;
double E1 = a + b + c;
double E2 = -a + b + c;
double E3 = a - b + c;
double E4 = a + b - c;
double B = A / Math.sqrt(E1 * E2 * E3 * E4);

return B * 2 * Math.PI;
}
}

netbeansにSyntheticaを適用してみます。 2008/07/25
2008/07/28

netbeans6.1にSyntheticaを適用してみます。

起動時の設定で、
まずクラスパスにsynthetica.jar,syntheticaBlackStar.jarを指定します。
次に、look and feelを指定します。

mac osxでは、

/Applications/NetBeans/NetBeans 6.1.app/Contents/Resources/NetBeans/etc/netbeans.conf

に指定できます。
他のosでもnetbeans.conf に記述すればオッケーです。

--cp:p がクラスパス
--lafでlook and feelを指定します。
netbeans_default_options="--cp:p /tmp/syntheticaBlackStar.jar:/tmp/synthetica.jar --laf de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel"


設定後起動すると下記のような感じで起動できます。


参考

groovyでmixin 2008/07/24


Mixins - Groovy JSR - Codehausをみてるといろいろあって混乱してしまう。

自分がmixinを使いたくなる場面がいまのところ想像できないけど、惹かれるんですよねmixinに。

適当に試してみました。
犬と猫を混合させてみようとしたのですが....

class Dog {
static void bow(t, String s) {
println "bow-wow $s"
}
}
class Cat {
static void mew(t, String s) {
println "mew $s"
}
}

Cat.mixin(Dog)
new Cat().bow('a')
Dog.mixin(Cat)
new Dog().mew()

class DoggyCat {

}

DoggyCat.mixin(Dog, Cat)
new DoggyCat().bow('o_o')
new DoggyCat().mew('o_o')


bow-wow a
mew null
bow-wow o_o
mew o_o

poj 2305 - Basic remains 2008/07/24

簡単にできそうな問題にチャレンジ。
といっても、
Short Coding ~職人達の技法~
やねうらお
4839925232

にのっていた問題ですが。



JavaだとBigIntegerがあるから楽ですね。
えーと、問題はn進数で表された値ふたつで割り算して、その答えをn進数で表現するというものです。

package p2305;

import java.math.BigInteger;
import java.util.Scanner;

public class Main {

public static void main(String[] args) {

Scanner scanner = new Scanner(System.in);
while (scanner.hasNext()) {
int radix = scanner.nextInt();
if(radix==0)break;
String m = scanner.next();
String p = scanner.next();
b(m, p, radix);
}
}

static void b(String mm, String pp, int radix) {

BigInteger m = new BigInteger(mm, radix);
BigInteger p = new BigInteger(pp, radix);
// System.out.println(m.mod(p));
System.out.println(m.mod(p).toString(radix));

}

}

現時点でのeclipseでのGui(swing)の開発について考えたこと 2008/07/23

VEが芳しくないのとNetBeansのUIツールがさくさく動くのを顧みての結論なのですが、メインの開発はeclipseでUIの部分だけはNetBeansでというのが僕の意見です。

で、NetBeansでソースパッケージフォルダを選択して右クリックで、プロジェクトプロパティで外部のソースフォルダを選択して追加することで、ソースフォルダだけ共有してマチスを使って、NetBeansでがりがり開発します。Eclipseにもどってパッケージエクスプローラーをリフレッシュするという具合。

で、Eclipseでプロジェクトに追加するライブラリは、swing-layout.jarぐらいですかね。
xxx.formファイルはどうもNetBeans上でのUIデザイン時に必要なようなので、実行時になくても大丈夫そうです。いったんこの開発の流れですすめるとNetBeansがないとUIの開発はできなくなりそうですが。

poj 3086 Triangular Sums 2008/07/20

3086 -- Triangular Sums
ひさしぶりのpojです。
解けそうな問題(アクセプトされた値が高いもの)をさがしてチャレンジ。

しばし、悩んだけど、テーブルを作成すると簡単。

package p3086;

import java.util.Scanner;

public class Main {

public static void main(String[] args) {

int[] tbl = createTable2();

Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
for(int i=1;i<=n;i++){
int p = scanner.nextInt();
System.out.println(i + " " + p + " " + tbl[p]);
}

}

static int[] createTable2() {
int[] tbl = createTable();
int[] tbl2 = new int[tbl.length - 1];
tbl2[0] = 0;
for (int i = 1; i < tbl2.length; i++) {
tbl2[i] = tbl2[i - 1] + (i * tbl[i + 1]);
}
return tbl2;
}

static int[] createTable() {
int[] tbl = new int[302];
tbl[0] = 0;
for (int i = 1; i < tbl.length; i++) {
tbl[i] = tbl[i - 1] + i;
}
return tbl;
}
}

returnを省略できる言語 2008/07/19

Javaではreturnを省略して書くことができません。
どいうことかといいますと
ある処理が、何らかの値を返すとして、

return 何らかの値;

とは書けても
何らかの値;

という記述はしません。

perl,ruby,groovyとかそういう記述の仕方ができます。

普段とくにそういうことは、そういうもんだと理解して、気にもとめないのですが、
BSFを使ってJavaからスクリプトを実行する場合のそのスクリプトの記述で悩みました。

JRubyを使ったのですが、何気に
new BSFManager().eval("ruby", "(java)", 1, 1, "return 'OK'");

とついついしたわけです。
素直に文字列OKを返してくれるだろうと....
例外がでます。

evalは式を評価してその結果を返すわけです。
returnを書く必要などないわけですが、何故かreturnを書きたくて仕方がない自分(笑)

上記のコードは、
new BSFManager().eval("ruby", "(java)", 1, 1, "'OK'");

でevalがOKを返してくれます。
returnが使えるのは、
new BSFManager().eval("ruby", "(java)", 1, 1, "def a¥n 'OK' ¥n end ¥na()");

メソッド定義した場合のようです。

ちなみに
new BSFManager().eval("ruby", "(java)", 1, 1, "a='OK'");

としてもOKが返されます。

参考

javaからMacアドレス ~ Windows編 2008/07/17
2008/07/22

Javaです。
Windowsです。JavaからMACアドレスの取得についてです。

現時点で思いつくであろう方法は3種類です。
(A)OS付属のコマンドをexecして、パスして取得
(B)Java6を使う
(C)JNIを使ってLibから取得

ベストなのは(B)だと思います。


Java6が使えない環境は、残念ながら(A),(C)ですかね。
Javaだといいつつ、Windows専用アプリを開発してたりのですが、どうもWindowsOSのバージョン(XP、VISTA)でipconfigが返してくれる文字列違ったりしたので、深く追求せず、(C)を採用することにしました。

すでに試みている人がいたので
そのまんまコードを参考にしつつ。

もうここ数年C,C++使っていなかったので、思い出しつつ。
コンパイル環境は、WindowsXPで、BorlandのBCC55を使いました。

ボーランドのコンパイラの使い方は、Borland C++ Compiler 5.5日本語版のインストールの方法が参考になりました。

JNIを使っての開発はここがJavaでHello World JNI編いい感じですね。あとここもcivic site : JNIを使ってみる

javahを使ってごにょごにょと。

その他、WindowsでのMacアドレス取得のための参考

で、僕が一番はまったのは、bcc32のリンカの動作というかコンパイルしてオブジェクト作ったあとのための処理でした。

bcc32を使って、下記のようなエラーがでました。
Error: 外部シンボル 'GetIfTable' が未解決


それで、下記のサイトでの説明が、しっくり。
C入門14

bcc32 -I"C:\Program Files\Java\jdk1.6.0\include" -I"C:\Program Files\Java\jdk1.6.0\include\win32" -tWD GetMacAddress.cpp C:\borland\bcc55\Lib\PSDK\iphlpapi.lib


リブを最後に指定してあげて解決。

以下コードです。

気まぐれなる日々さんのそのまんまだったりしかすが....

Java
class GetMacAddress {
static {
System.loadLibrary("GetMacAddress");
}
public native String getMacAddress();
}


ネイティブコード(Win32)
#include <windows.h>
#include <iphlpapi.h>
#include "GetMacAddress.h"

JNIEXPORT jstring JNICALL Java_GetMacAddress_getMacAddress
(JNIEnv *env, jobject obj) {

char buf[1024];
DWORD d=0 ;

GetIfTable( NULL , &d, FALSE );

PMIB_IFTABLE IfTable = (PMIB_IFTABLE)new char[d] ;

if( IfTable ){
if( GetIfTable( (PMIB_IFTABLE)IfTable,&d,FALSE) == NO_ERROR ){
wsprintf(buf,"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
,(unsigned char)IfTable->table[0].bPhysAddr[0]
,(unsigned char)IfTable->table[0].bPhysAddr[1]
,(unsigned char)IfTable->table[0].bPhysAddr[2]
,(unsigned char)IfTable->table[0].bPhysAddr[3]
,(unsigned char)IfTable->table[0].bPhysAddr[4]
,(unsigned char)IfTable->table[0].bPhysAddr[5]
);
}
}

return env->NewStringUTF(buf);
}



※Javaを使っているのに、Linux、MacOSで動作させることを頭から放棄するのも気概がないというか、センスがないというか残念な話なのですが。

2008-07-22
ふと検索かけたら、自分のブログが検索にひっかかった。
書いたの2年前なんですよね。その間、お仕事で新しいことしていない....Orz...

あと、どうもXP,Vistaで違いがあるようです。

もしかして、取得した値がイーサネットかどうかという判断をさせる必要があるかもしれませんね。ふぅ。

というわけで上記のOKWaveを参考にして、typeとspeedを使ってイーサネットを判断?させてみました。手元の環境では、XP,vistaでうまくいっているようにみえますが、いろいろな環境でためさないと確信できませんね。

とても参考になったサイトは、ここです。

JNIEXPORT jstring JNICALL Java_GetMacAddress_getMacAddress
(JNIEnv *env, jobject obj) {

char buf[1024];
DWORD d=0 ;

GetIfTable( NULL , &d, FALSE );

PMIB_IFTABLE IfTable = (PMIB_IFTABLE)new char[d];

if( IfTable ){
if( GetIfTable( (PMIB_IFTABLE)IfTable,&d,FALSE) == NO_ERROR ){
for(int i=0;i< (int)IfTable->dwNumEntries;i++ ){
int type = (int)IfTable->table[i].dwType;
int speed = (int)IfTable->table[i].dwSpeed;
if( type == 6
&& (10000000000 == speed
|| 1000000000 == speed
|| 100000000 == speed )){
wsprintf(buf,"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x"
,(unsigned char)IfTable->table[i].bPhysAddr[0]
,(unsigned char)IfTable->table[i].bPhysAddr[1]
,(unsigned char)IfTable->table[i].bPhysAddr[2]
,(unsigned char)IfTable->table[i].bPhysAddr[3]
,(unsigned char)IfTable->table[i].bPhysAddr[4]
,(unsigned char)IfTable->table[i].bPhysAddr[5]
);
break;
}
}
}
delete [] IfTable;
}

return env->NewStringUTF(buf);
}

ミリ秒、ナノ秒 2008/07/10

Javaです。
java1.5からSystem.nanoTime()が使えます。

ミリ秒は1000分の1秒です。
ナノ秒は十億分の1秒となります。

ナノ - Wikipedia

すると、1000*1000*1000で割れば秒がもとめられます。


long t = System.nanoTime();
// code....
System.out.println((System.nanoTime() - t) / 1000000000d);

グラデーション - web2.0っぽいの練習 2008/07/07



かっこいいグラデーションを作る簡単な(ある意味、無難な)方法は、HSBのブライトネスを変化させればいいようです。



さらにグラデーションを極めたい場合は、HSBの全てを操作できるといい。

全ての色、そして全体感に対してマッチするグラデーションは、明度、彩度、色相の3つのグラデーションが状況に応じて複雑に組み合わさったものだ。これを体得すれば、リッチなアイコンにも応用することができるだろう。さらには、複数の光源を使ったり、光源の法則をわざと外してみたりすることも有効だ。リアル・グラデーションの作法 | Nitram+Nunca


ちなみに、HSBは色相(Hue)、彩度(Saturation・Chroma)、明度(Brightness・Lightness・Value)だそうです。


コードです。Javaです。
RGBからHSBに変換して、Bだけスライダーで操作するようにしています。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.GradientPaint;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.geom.Rectangle2D;

import javax.swing.JButton;
import javax.swing.JColorChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

public class TestGradient extends JPanel {

public static void main(String[] args) {
final JFrame frame = new JFrame();

final TestGradient panel = new TestGradient();
JPanel controlPanel = new JPanel();
final JSlider slider = new JSlider(0, 255);

JPanel panel2 = new JPanel();

final JButton button = new JButton("choice color");

panel2.add(button);
button.addActionListener(new ActionListener() {

public void actionPerformed(ActionEvent e) {

panel.colStart = JColorChooser.showDialog(frame, "color",
panel.colStart);
panel.setcolEnd(panel.col_b);

}
});

slider.addChangeListener(new ChangeListener() {

public void stateChanged(ChangeEvent e) {

panel.setcolEnd(slider.getValue() / 256f);
}

});

controlPanel.add(slider);

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

frame.getContentPane().add(panel2, BorderLayout.NORTH);
frame.getContentPane().add(controlPanel, BorderLayout.SOUTH);

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setBounds(10, 10, 300, 200);
frame.setTitle("");
frame.setVisible(true);
}

Color colStart = Color.DARK_GRAY;
Color colEnd = colStart;

float col_b = 0f;

void setcolEnd(float b) {
float[] fs = Color.RGBtoHSB(colStart.getRed(), colStart.getGreen(),
colStart.getBlue(), null);

fs[2] = 1f * b;
col_b = b;
colEnd = new Color(Color.HSBtoRGB(fs[0], fs[1], fs[2]));

System.out.println("top:" + colStart);
System.out.println("bottom:" + colEnd);
repaint();
}

public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;

g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);

float center = this.getWidth() / 2f;

GradientPaint gradient = new GradientPaint(center, 0, colStart, center,
this.getHeight(), colEnd, false);
g2.setPaint(gradient);

g2
.fill(new Rectangle2D.Double(0, 20, this.getWidth(), this
.getHeight()));
}

}

InetSocketAddressについて、bindについてのメモ 2008/07/03

Javaです。

おおざっぱなメモです。
おおざっぱです。
ソケット通信する際の受けの部分で、

ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
serverSocketChannel.configureBlocking(false);
serverSocketChannel.socket().bind(inetSocketAddress);

という感じのコードでソケットにバインドさせています。
それで、inetSocketAddressの部分を、
new InetSocketAddress(port)でいくのか、new InetSocketAddress("127.0.0.1", port)でいくのか、はてまたnew InetSocketAddress(InetAddress.getLocalHost().getHostName(), port)
でいくのか。

ためしたのはWindowsでtenlnetで接続を確認
new InetSocketAddress(port)の場合、「telnet マシン名 port」、「telnet 127.0.01 port」で接続できました。

new InetSocketAddress(InetAddress.getLocalHost().getHostName(), port)の場合、「telnet マシン名 port」で接続できました。

結論、ふたつのアプリがソケットでローカル通信でする場合は、new InetSocketAddress(port)でバインドしたほうが無難かなと。

あと、バインドする際にnew InetSocketAddress("127.0.0.1", port)と、new InetSocketAddress(InetAddress.getLocalHost().getHostName(), port)でバインドさせると同時にバインドできますね。

使用しているポートでの二重起動チェックでは注意です。

windowsで使用している(リッスン)ポートを調べるにはコマンドnetstat -anで。
ポート49999をnew InetSocketAddress(InetAddress.getLocalHost().getHostName(), port)でバインドさせますと、
コマンドnetstat -anで、下記のようにみえます。
TCP 0.0.0.0:49999 0.0.0.0:0 LISTENING


ポート49999をnew InetSocketAddress("127.0.0.1", port)でバインドさせますと、
コマンドnetstat -anで、下記のようにみえます。

TCP 127.0.0.1:49999 0.0.0.0:0 LISTENING


参考

追随してsyntheticaにチャレンジ 2008/07/01

Javaです。
周りでsyntheticaを使いはじめているので、ちょっとどんなものかと触ってみました。
ベースになるsynthという技術は、java1.5から導入されたものだそうです。



Syntheticaは下記のサイトからダウンロードできます。ユーザー登録しないといけないです。



Syntheticaを使うメリットは、Synthetica Features (Java Look and Feel)にいろいろ書かれています。

ちなみにライセンスには注意です。 商業利用するにはライセンスを購入しないといけないです。
Synthetica license

こんな感じ、よさが伝わりづらいですが....


以下、コード。
カスタマイズの仕方は、painterを用意して、synth.xmlを修正していく感じでしょうか。


import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.UIManager;

import de.javasoft.plaf.synthetica.SyntheticaBlackStarLookAndFeel;
import de.javasoft.plaf.synthetica.SyntheticaStandardLookAndFeel;

public class TestFrame {

public static void main(String[] args) {

lookAndFeel();

JPanel panel = new JPanel();
panel.add(new JLabel("日本語"));
panel.add(new JButton("test"));
panel.add(new JTextField("日本語テキスト"));
panel.add(new JTextArea("日本語テキスト 日本語テキスト 日本語テキスト"));

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

static void lookAndFeel() {
UIManager.put("Synthetica.window.decoration", Boolean.TRUE);
try {
UIManager.setLookAndFeel(new SyntheticaBlackStarLookAndFeel());
// UIManager.setLookAndFeel(new SyntheticaStandardLookAndFeel());
} catch (Exception e) {
e.printStackTrace();
}
}
}