シミュレーションモデル本体(ここではXXXmodel.javaとし、クラス名も同名とする)を作成する。必須のものは以下のとおり。
/** * シミュレーションモデルの本体 **/ import java.io.*; import java.util.*; public class XXXmodel { // クラス内グローバル変数の定義 protected int alpha; protected double beta; public int N=5; public double x[], y[]; /******* Constructor ****************/ XXXmodel(int a, double b) { x = new double[N]; y =new double[N]; setParameters(a, b); } /** end of Constructor */ /** パラメータの設定 */ public void setParameters(int a, double b) { alpha = a; beta = b; } /** 初期条件 */ public void setInitialCondition() { } /** 時間変化プロセス */ public boolean updateSystem() { for(int i=0; i<N; i++) { // サンプル x[i] = Math.random(); y[i] = Math.random(); } return true; } }
/** * ボタン、スライダなどでパラメータ設定するサンプル * step2: ボタンやスライダにリスナーをつける * step3: シミュレーション動画用ウィンドウを開く(別スレッド) * step4: シミュレーション本体 XXXmodelを実装し * スタートボタンのリスナー内でオブジェクト生成 * run()において繰り返し実行 **/ import java.awt.*; import javax.swing.*; import java.awt.event.*; // リスナー用 import javax.swing.event.*; // Runnableインターフェイスを装着(インプリメント)step3 public class sample_gui extends JPanel implements Runnable { /******* step4: thread variables ***************/ private Thread myTh; private boolean halt_; /******* implementing simulation model *********/ private XXXmodel XXX; /** グラフィック関係変数 */ JButton startBtn, stopBtn, exitBtn; // ボタン JLabel label_1, label_2; // ラベル JSlider slider_1, slider_2; // スライダ /** 各種グローバル */ static int maxSize = 600; // width of window in pixels static double scale_2 = 100; // スライダ2の値の単位 /** step3: シミュレーション描画用 中身はdrawFigure.javaで定義 */ drawFigure simulationFrame; /************* コンストラクタ ************************/ sample_gui() { /** step3: シミュレーションフレームの生成 */ simulationFrame = new drawFigure(500); // サイズを引数に /** パラメータ初期値 */ int ini_1 = 500, ini_2 = 10; /** ボタン生成 */ startBtn = new JButton("start"); stopBtn = new JButton("stop"); exitBtn = new JButton("終了"); /** スライドバー生成 (値は整数)*/ slider_1 = new JSlider(JSlider.HORIZONTAL, 0, 1000, ini_1); slider_2 = new JSlider(JSlider.HORIZONTAL, 0, 100, ini_2); /** ラベル生成 */ label_1 = new JLabel(String.valueOf(ini_1)); label_2 = new JLabel(String.valueOf(ini_2/scale_2)); /** スライダーやボタンにリスナーをつける */ // step3 + 4 startBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { /** * startボタンが押されたら、ゲームオブジェクトを作成し、 * スレッドをスタートさせる */ /** step4: get parameters and create simulation object ***/ int a = slider_1.getValue(); double b = (double) slider_2.getValue()/scale_2; XXX = new XXXmodel(a,b); thread_start(); } }); exitBtn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ae) { System.exit(0); } }); slider_1.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { label_1.setText(Integer.toString(slider_1.getValue())); } }); slider_2.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { label_2.setText(Double.toString(slider_2.getValue()/scale_2)); } }); /***********************************************/ /** パネルにスライドバー、ラベルを貼る */ JPanel panel_operation = new JPanel(); //ボタン3つを一つのJPanelに panel_operation.add(startBtn); panel_operation.add(stopBtn); panel_operation.add(exitBtn); JPanel panel_1 = new JPanel(); // ラベル、スライダ、値表示を一つのJpanelに panel_1.add(new JLabel("パラメータ1")); panel_1.add(slider_1); panel_1.add(label_1); JPanel panel_2 = new JPanel(); panel_2.add(new JLabel("パラメータ2")); panel_2.add(slider_2); panel_2.add(label_2); /** 親パネルにボタンと、スライドバー・ラベル を並べる */ JPanel p = new JPanel(); p.setLayout(new GridLayout(2, 2)); // 2行2列に設定 p.add(panel_operation); // 上で作ったJPanelを並べる p.add(panel_1); p.add(panel_2); add(p, BorderLayout.NORTH); // 親フレームに置く } /** main */ public static void main(String[] args) { // パラメータセットのGUIを作成し、表示 JFrame setParamFrame = new JFrame("パラメータセット"); // 親フレーム sample_gui ctr = new sample_gui(); // このクラスの実体を作る(実体名: ctr) setParamFrame.getContentPane().add(ctr, BorderLayout.CENTER); // 親フレームに「実体」を貼る setParamFrame.setSize(750, 100); // フレームの大きさ設定 setParamFrame.setLocation(600, 20); // フレームを置く位置 setParamFrame.setVisible(true); // 見えるようにする } /*********************step3での追加 *****************************/ /** GUIで操作できるようにrunnableインターフェイスに基づいてスレッドを操作をする */ public void thread_start() { /** startボタンにより呼び出す */ halt_ = false; myTh = new Thread(this); myTh.start(); /** start()によりrun()が実行される */ } public void stop() { /** stopボタンで呼び出す */ halt_ = true; myTh.interrupt(); } /** 新しいスレッドの実体 */ public void run() { for(int i=0; i< 10; i++) { XXX.updateSystem(); simulationFrame.drawCircles(XXX); // arg. is the simulation model object } } } /** * step5での課題: * ストップボタンで中断 * 再スタートボタンで再開 * スタートボタンで、パラメータを読み込んで新規にスタート */
描画メソッドは、シミュレーション本体オブジェクトを引数を通じて受け取り、車の位置などの値を参照して描画するように書き換える。
/** シミュレーションのスナップショット描画 */ import java.io.*; import java.awt.*; // uses the abstract windowing toolkit import javax.swing.*; import javax.imageio.ImageIO; // スナップショットのセーブなどに利用 import java.awt.image.BufferedImage; public class drawFigure extends JPanel { Graphics g; // 車の配置などを書き込むカンバス JFrame gWin; double screenWidth; int frameTop, frameLeft; // platform-dependent width of frame's top and left int marginX=20, marginY=20; /** コンストラクタ */ drawFigure(int fSize) { screenWidth = (double) fSize; // シミュレーション本体画面の初期化 gWin = new JFrame("Trafic Flow Model"); gWin.setLocation(20, 150); // screen coordinates of top left corner gWin.setResizable(false); gWin.setVisible(true); // show it! /** 下30ピクセルは文字出力用inset*/ Insets theInsets = gWin.getInsets(); gWin.setSize(fSize + theInsets.left + theInsets.right + marginX*2, fSize + theInsets.top + marginY*2+ theInsets.bottom+30); this.frameTop = theInsets.top; this.frameLeft = theInsets.left; this.g = gWin.getGraphics(); // 画像をここに書き込む } public void drawCircles(XXXmodel XXX) { // step4: arg. is the simulation model // 画面を白で塗りつぶす g.setColor(new Color(255,255,255)); g.fillRect(0, 0, gWin.getWidth(),gWin.getHeight()); // 適当に丸を書く for(int n = 0; n< XXX.N ;n++){ double centerX = XXX.x[n]; double centerY = XXX.y[n]; this.g.setColor(new Color(255,0,0)); // 色の指定 double nX = screenWidth * centerX +this.frameLeft+this.marginX; double nY = screenWidth * centerY +this.frameTop + this.marginY; this.g.fillOval((int) nX, (int) nY, 30, 30); } // 1秒休む try{ Thread.sleep(1000); }catch (InterruptedException e){ } } }
1. あるオブジェクト内の変数は、多くの場合、外から書き換えられないようにprivateあるいはprotect宣言しておき、その値を外から参照するためのメソッド(getterメソッドと通称)を用意する。ここでは簡便のためにpublic宣言しておく。