2008年3月3日月曜日

移転します

今後ここで書いていたようなものはhttp://d.hatena.ne.jp/ellerCode/で書こうと思います。
このブログは残しておきますが、更新は打ち切ります。

2008年1月22日火曜日

HTML内の見出し一覧を取得する(1)

正規表現を用いてHTML内の見出し(h1~h6要素)を取得します。
将来的には目次や索引のように、リンク付きのリスト(ol要素)を出力できるようにしたいところです。
import java.io.*;
import java.util.*;
import java.util.regex.*;
import javax.swing.*;
import javax.swing.filechooser.FileNameExtensionFilter;

public class HTMLIndexMaker {
public static void main(String[] args) {
// ファイルを選択する
File file = selectFile(null);
if (file == null || file.isDirectory() || !file.canRead()) {
// ファイルが選択されなかった・読み込めなかった
System.exit(0);
}

// 選択したファイルを読み込む
String html = getHTML(file);

// 正規表現を用い、見出し要素を取り出す
List<String> list = getList(html);

// 取り出した要素を表示
showList(list);

// 実行終了
System.out.println("finish..." + list.size() + "個の見出しを検出しました");
}

/**
* ダイアログを開きファイルを選択する
* 参照->http://www.javadrive.jp/tutorial/jfilechooser/index.html
* @return 選択したファイル(非選択時はnull)
*/
private static File selectFile(final JFrame frame) {
JFileChooser fileChooser = new JFileChooser();
fileChooser.setMultiSelectionEnabled(false);
FileNameExtensionFilter filter = new FileNameExtensionFilter("HTMLファイル", "html", "htm");
fileChooser.addChoosableFileFilter(filter);

if (fileChooser.showOpenDialog(frame) == JFileChooser.APPROVE_OPTION) {
return fileChooser.getSelectedFile();
} else {
return null;
}
}

/**
* HTMLファイルの内容(テキスト)をStringに読み込む
* HTMLファイルはシフトJIS(MS932)であること
* 参考->http://www.ne.jp/asahi/hishidama/home/tech/java/file.html
*/
private static String getHTML(final File file) {
StringBuffer sb = new StringBuffer();
InputStream is = null;
Reader r = null;
BufferedReader br = null;
try {
is = new FileInputStream(file);
r = new InputStreamReader(is, "MS932");
br = new BufferedReader(r);
while (br.ready()) {
sb.append(br.readLine());
}
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
}
}
if (r != null) {
try {
r.close();
} catch (IOException e) {
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
}
return sb.toString();
}

/**
* Stringを検索し、見出し一覧を作成する
*
* @param html 検索するHTML
* @return 見出し一覧
*/
private static List<String> getList(final String html) {
List<String> list = new ArrayList<String>();
Pattern pattern = Pattern.compile("<h[1-6].+?</h[1-6]>");
Matcher matcher = pattern.matcher(html);
while (matcher.find()) {
list.add(matcher.group());
}
return list;
}

/**
* リストを表示する(デバッグ用)
*
* @param list 見出し一覧
*/
private static void showList(final List<String> list) {
ListIterator li = list.listIterator();
while (li.hasNext()) {
System.out.println(li.next().toString());
}
}
}

2007年12月21日金曜日

時計の表示

時計を表示します。
package {
import flash.display.Sprite;
import flash.display.Shape;
import flash.text.TextField;

public class ClockSample extends Sprite {
// 表示用スプライト
private var child:Sprite;

/**
* コンストラクタ */
public function ClockSample() {
// 文字盤を作る
makeBoard();

// 時計の針をつくる
makeNeedles();
}
/**
* 文字盤を作る */
private function makeBoard():void {
child = new Sprite();
child.graphics.beginFill(0xFFFFFF);
child.graphics.drawRect(-200, -200, 400, 400);
child.graphics.endFill();
child.x = this.stage.stageWidth / 2;
child.y = this.stage.stageHeight / 2;
this.addChild(child);

var i:int;
for(i=1;i<=12;i++) {
var number:Shape = new Shape();
var angle:Number = Math.PI * i / 6.0;
number.graphics.beginFill(0xCCCCCC);
number.graphics.drawRect(-10,-10,20,20);
number.graphics.endFill();
number.x = (child.width * Math.sin(angle)*0.8) * 0.5;
number.y = (child.height * -Math.cos(angle)*0.8) * 0.5;
child.addChild(number);
}
}
/**
* 針を作る */
private function makeNeedles():void {
child.addChild(new NeedleSec());
child.addChild(new NeedleMin());
child.addChild(new NeedleHour());
}
}
}

import flash.display.Shape;
import flash.events.Event;

/**
* 針の基本クラス */
internal class Needle extends Shape
{
public function Needle(length:uint, width:uint, color:uint) {
this.graphics.beginFill(color);
this.graphics.drawRoundRect(-width, -length, width*2, length, width, width);
this.graphics.endFill();
this.x = 0;
this.y = 0;
this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
move();
}
public function onEnterFrame(event:Event):void {
move();
}
public function move():void {}
}
/**
* 時間を指し示す針のクラス */
internal class NeedleHour extends Needle {
public function NeedleHour() {
super(60, 3, 0xFF0000);
}
override public function move():void {
var now:Date = new Date();
this.rotation = (now.hours + now.minutes/60) * 30;
}
}
/**
* 分を指し示す針のクラス */
internal class NeedleMin extends Needle {
public function NeedleMin() {
super(100, 2, 0xFF8000);
}
override public function move():void {
var now:Date = new Date();
this.rotation = now.minutes * 6;
}
}
/**
* 秒を指し示す針のクラス */
internal class NeedleSec extends Needle {
public function NeedleSec() {
super(105, 1, 0x000000);
}
override public function move():void {
var now:Date = new Date();
this.rotation = now.seconds * 6;
}
}

2007年12月8日土曜日

相互作用が働く粒子の運動

相互作用が働く粒子の運動2のJava移植版。アプレットはこちらです。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.*;
import java.util.*;

public class HSPAtom extends JApplet implements Runnable, MouseListener {
private Vector<Particle> particles = new Vector<Particle>();
private float h = 0.0f;
private final int NUM_MEMBERS = 12;
private MyPanel panel;
private Random random = new Random();

/**
* アプレットの初期化
*/
public void init() {
panel = new MyPanel();
add(panel, BorderLayout.CENTER);
makeParticles();
addMouseListener(this);

Thread thread = new Thread(this);
thread.start();
}

/**
* スレッド
*/
public void run() {
Rectangle rect = new Rectangle(getSize());
while(true) {
try {
Enumeration<Particle> e = particles.elements();
while(e.hasMoreElements()) {
Particle particle = e.nextElement();
particle.move(particles, rect);
}
panel.repaint();
Thread.sleep(40);
} catch(Exception e) {

}
}
}

/**
* 粒子を全消去し、新たに一定数の粒子を作成する
* 粒子の色も変更される
*/
private void makeParticles() {
h = random.nextFloat();
particles.clear();
Dimension size = getSize();
for(int i=0; i<NUM_MEMBERS; i++) {
Particle particle = new Particle(
random.nextDouble() * size.width,
random.nextDouble() * size.height);
particles.add(particle);
}
}
public void mouseClicked(final MouseEvent event) {
if(javax.swing.SwingUtilities.isRightMouseButton(event)){
// 右クリックの場合 - 粒子を作成し直す
makeParticles();
} else if(javax.swing.SwingUtilities.isLeftMouseButton(event)){
// 左クリックの場合 - 粒子を追加する
Particle particle = new Particle(
event.getX(), event.getY());
particles.add(particle);
}
}
public void mouseEntered(final MouseEvent event) {}
public void mouseExited(final MouseEvent event) {}
public void mousePressed(final MouseEvent event) {}
public void mouseReleased(final MouseEvent event) {}

/**
* オリジナルのパネル
*/
private class MyPanel extends JPanel{
public void paintComponent(final Graphics g) {
Dimension size = getSize();
Graphics2D g2d = (Graphics2D)g;

// 画面の消去
g.setColor(Color.black);
g.fillRect(0, 0, size.width, size.height);

// 粒子の描画
g2d.setColor(Color.getHSBColor(h, 1.0f, 1.0f));
Enumeration<Particle> e = particles.elements();
while(e.hasMoreElements()) {
Particle particle = e.nextElement();
g2d.fill(particle);
}
}
}
/**
* 粒子を表すクラス
* Ellipse2D.Doubleを拡張し、Graphics2Dのfillメソッドを利用できるようにした
*/
private class Particle extends Ellipse2D.Double {
private double veloX, veloY;
private static final int
RADIUS = 5,
PARTY_DIST = 120;
/**
* コンストラクタ
* @param x 粒子の位置(X座標)
* @param y 粒子の位置(Y座標)
*/
private Particle(double x, double y) {
super(x, y, RADIUS * 2, RADIUS * 2);
}
/**
* 速度計算と移動を同時に行う(厳密には別々に行うべき)
* @param party 自分自身を含むすべての粒子が代入されているVector
* @param size 行動範囲の広さ
*/
private void move(final Vector<Particle> party, final Rectangle area) {
double ax = 0.0, ay = 0.0;
Enumeration<Particle> e = party.elements();
while(e.hasMoreElements()) {
Particle target = e.nextElement();
if(!target.equals(this)) {
double
distance = Math.sqrt(
Math.pow(x - target.x, 2)
+ Math.pow(y - target.y, 2)),
theta = Math.atan2(target.y - y, target.x - x),
speed = Math.abs(distance - PARTY_DIST) * (distance - PARTY_DIST) / 5000;

ax += speed * Math.cos(theta);
ay += speed * Math.sin(theta);
}
}
veloX = 0.9 * (veloX + ax);
veloY = 0.9 * (veloY + ay);

this.x = limit(this.x + veloX, area.x + RADIUS, area.x + area.width - RADIUS);
this.y = limit(this.y + veloY, area.y + RADIUS, area.y + area.height - RADIUS);
}
}
/**
* HSPのlimit関数と同じ
*/
private static double limit(final double value, final double min, final double max) {
return Math.max(min, Math.min(value, max));
}
}

2007年11月8日木曜日

テキストの保存

ファイル選択ダイアログを表示し、ユーザにファイルを選択させる。
Windowsマシン向けに改行コードを\r\nへ変換している点に注意。
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import javax.swing.*;

public class FileDialogTest extends JFrame implements ActionListener {
private JTextArea textarea = new JTextArea();
private JButton button = new JButton("名前を付けて保存(S)");
public static void main(String[] args) {
FileDialogTest frame = new FileDialogTest();
frame.setTitle("text editor sample");
frame.setSize(480, 320);
frame.setVisible(true);
}

public FileDialogTest() {
button.setMnemonic(KeyEvent.VK_S);
button.addActionListener(this);
this.setLayout(new BorderLayout());
this.add(button, BorderLayout.PAGE_END);
this.add(textarea, BorderLayout.CENTER);
}

public void actionPerformed(ActionEvent ae) {
if(ae.getSource().equals(button)) {
JFileChooser fileChooser = new JFileChooser();
if(fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
try {
File file = fileChooser.getSelectedFile();
FileWriter fileWriter = new FileWriter(file);
fileWriter.write(textarea.getText().replaceAll("\n", "\r\n"));
fileWriter.close();
JOptionPane.showMessageDialog(this,
"テキストを" + file.getName() + "に保存しました。");
} catch(Exception e) {}
}
}
}
}

2007年11月3日土曜日

タイマーの表示

秒:ミリ秒を表示するタイマー。一時停止などはついていません。
import java.util.Date;
import javax.swing.*;

public class TimerSample extends JApplet implements Runnable {
private long startTime;
private JLabel lblTimer = new JLabel( "", JLabel.CENTER );

public void init() {
startTime = new Date().getTime();
this.add( lblTimer );
Thread t = new Thread( this );
t.start();
}
public void run() {
while( true ) {
try {
long now = new Date().getTime();
long passedTime = now - startTime;
int passedMilliSec = (int)( passedTime % 1000 ),
passedSec = (int)( passedTime / 1000 );
lblTimer.setText( new Integer( passedSec ).toString() + ":"
+ new Integer( passedMilliSec ).toString() );
Thread.sleep( 100 );
} catch(Exception e) {}
}
}
}