スレッドの開始・停止・再開 -- およびActionインタフェース

戻る

::::::::::::::
Cell.java
::::::::::::::
/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class Cell {
    /** サブクラスからのアクセスを許可する */
    protected int x;
    protected int y;

    public Cell( int x, int y ) {
        this.x = x;
        this.y = y;
    }
    /** 次の位置に移動する */
    public void moveNext( int x, int y ) {
        this.x = x;
        this.y = y;
    }
    public void follow( Cell cell ) {
        this.x = cell.getX();
        this.y = cell.getY();
    }

    public int getX() {
        return x;
    }
    public int getY() {
        return y;
    }

}
::::::::::::::
CellList.java
::::::::::::::
import java.util.*;

/**
* <pre>
* $Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
* @author KISHI Yasuhiro
* セルを結合したクラス
* </pre>
*/

public class CellList extends LinkedList implements Runnable {
    private int xMax;
    private int yMax;
    /** 格納するセルの最大個数 */
    private int maxSize = 10;

    public CellList() {
        super();
    }

    public void setBoundary( int x, int y ) {
        this.xMax = x;
        this.yMax = y;
    }

    /** スレッドを開始する */
    public void start() {
        ( new Thread( this ) ).start();
    }

    public void run() {
        while ( true ) {
            // 移動する
            move();

            // 増殖する
            multiply();

            try {
                Thread.sleep( 200 );
            } catch ( Exception exception ) {
                exception.printStackTrace();
            }
        }
    }


    private synchronized void multiply() {
        // 末尾のセルを求める
        Cell tailCell = ( Cell ) this.getLast();
        int currentX = tailCell.getX();
        int currentY = tailCell.getY();
        int nextX;
        int nextY;

        if ( this.size() < maxSize ) {
            nextX = currentX;
            nextY = currentY;

            Random random = new Random();
            int position = Math.abs( random.nextInt() % 4 );
            switch ( position ) {
            case 0:
                // 右に追加
                nextX++;
                break;
            case 1:
                // 下に追加
                nextY++;
                break;
            case 2:
                // 左に追加
                nextX--;
                break;
            case 3:
                // 上に追加
                nextY--;
                break;
            default:
                // Do nothing
                break;
            }

            this.add( new Cell( nextX, nextY ) );

        }
    }

    private void move() {
        Cell headCell = ( Cell ) this.getFirst();
        int currentX = headCell.getX();
        int currentY = headCell.getY();
        int nextX;
        int nextY;

        do {
            nextX = currentX;
            nextY = currentY;
            // 次の移動位置をランダムに与える
            Random random = new Random();
            int direction = Math.abs( random.nextInt() % 4 );
            switch ( direction ) {
            case 0:
                // 右に移動
                nextX++;
                break;
            case 1:
                // 下に移動
                nextY++;
                break;
            case 2:
                // 左に移動
                nextX--;
                break;
            case 3:
                // 上に移動
                nextY--;
                break;
            default:
                // Do nothing
                break;
            }

            if ( isOccupied( nextY, nextY ) ) {
                // 他のセルと同じ場所であれば、そこには進まない
                continue;
            }

        } while ( isOutOfBoundary( nextX, nextY ) );

        headCell.moveNext( nextX, nextY );

        // DEBUG
        // System.out.printf( "%3d : %3d\n", headCell.getX(), headCell.getY() );

        /** 先頭のセルに追従する */
        Cell newCell = new Cell( currentX, currentY ); // 先頭セルの移動前の位置
        for ( int i = 1;i < this.size();i++ ) {
            Cell targetCell = ( Cell ) this.get( i );

            // 現在の位置を保持しておく→後続のセルの移動先
            int x = targetCell.getX();
            int y = targetCell.getY();

            // 新しい位置に移動
            targetCell.follow( newCell );

            newCell = new Cell( x, y );
        }

    }

    /** 他のセルが既にその位置を占有しているかどうか */
    private boolean isOccupied( int x, int y ) {
        boolean occupied = false;
        Iterator iterator = this.iterator();
        while ( iterator.hasNext() ) {
            Cell cell = ( Cell ) iterator.next();

            if ( cell.getX() == x && cell.getY() == y ) {
                occupied = true;
                break;
            }
        }

        return occupied;

    }

    /** 境界をはみ出したかどうか */
    private boolean isOutOfBoundary( int x, int y ) {
        return ( x < 0 || x > xMax || y < 0 || y > yMax );
    }

    static public void main( String[] args ) {
        CellList list = new CellList();
        list.setBoundary( 10, 10 );

        list.add( new Cell( 0, 0 ) );

        list.start();
    }
}
::::::::::::::
CellPainter.java
::::::::::::::
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

import java.util.*;

/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class CellPainter {

    static public synchronized void paint( Graphics g, CellList cellList ) {

        Iterator iterator = cellList.iterator();

        int i = 0;
        while ( iterator.hasNext() ) {
            Cell cell = ( Cell ) iterator.next();
            int x = cell.getX();
            int y = cell.getY();

            if ( i == 0 ) {
                g.setColor( Color.red );
            } else {
                g.setColor( Color.yellow );
            }
            g.fillOval( GridPainter.PITCH * x, GridPainter.PITCH * y, GridPainter.PITCH, GridPainter.PITCH );

            i++;
        }

    }
}
::::::::::::::
Cellula.java
::::::::::::::
import java.util.*;

import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class Cellula extends Cell implements Runnable {
    private int xMax;
    private int yMax;
    CellulaManager manager;

    public Cellula( int x, int y, int xMax, int yMax, CellulaManager manager ) {
        super( x, y );
        this.xMax = xMax;
        this.yMax = yMax;
        this.manager = manager;

        manager.add( this );

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

    /** 境界をはみ出したかどうか */
    private boolean isOutOfBoundary( int x, int y ) {
        return ( x < 0 || x > xMax || y < 0 || y > yMax );
    }

    public void run() {
        while ( true ) {
            migrate();

            beget();

            try {
                Thread.sleep( 100 );

            } catch ( Exception e ) {
                e.printStackTrace();
            }
        }
    }

    /** 増殖させる */
    private void beget() {
        if ( !manager.isAcceptable() ) {
            return ;
        }

        Cellula cellula = new Cellula( x, y, xMax, yMax, manager );
    }


    private void migrate() {
        int currentX = this.getX();
        int currentY = this.getY();
        int nextX;
        int nextY;

        do {
            nextX = currentX;
            nextY = currentY;
            // 次の移動位置をランダムに与える
            Random random = new Random();
            int direction = Math.abs( random.nextInt() % 4 );
            switch ( direction ) {
            case 0:
                // 右に移動
                nextX++;
                break;
            case 1:
                // 下に移動
                nextY++;
                break;
            case 2:
                // 左に移動
                nextX--;
                break;
            case 3:
                // 上に移動
                nextY--;
                break;
            default:
                // Do nothing
                break;
            }

        } while ( isOutOfBoundary( nextX, nextY ) );

        // DEBUG
        // System.out.println(nextX + ":" + nextY);

        moveNext( nextX, nextY );

    }

    public void paint( Graphics g ) {
        g.setColor( Color.red );
        g.fillOval( GridPainter.PITCH * x, GridPainter.PITCH * y, GridPainter.PITCH, GridPainter.PITCH );

    }

}
::::::::::::::
CellulaManager.java
::::::::::::::
import java.util.*;
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/
public class CellulaManager {
    /** 許容最大数 */
    private int permissibleCount;

    java.util.List list;

    public CellulaManager( int permissibleCount ) {
        list = new LinkedList();
        this.permissibleCount = permissibleCount;
    }

    public void add
        ( Cellula cellula ) {
        list.add( cellula );
    }

    public synchronized boolean isAcceptable() {
        return permissibleCount > list.size();
    }

    public synchronized void paintAll( Graphics g ) {

        Iterator iterator = list.iterator();
        while ( iterator.hasNext() ) {
            Cellula cellula = ( Cellula ) iterator.next();
            cellula.paint( g );
        }
    }

}
::::::::::::::
CommandPanel.java
::::::::::::::
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class CommandPanel extends JPanel {
    private JButton startButton, stopButton;
    private JLabel counterLabel;

    public CommandPanel( DrawingPanel dp ) {
        startButton = new JButton( "START" );
        stopButton = new JButton( "STOP" );
        counterLabel = new JLabel();

        this.add( startButton );
        this.add( stopButton );
        this.add( counterLabel );

        //-----------------------------------------------------
        // アクションリスナーの追加
        //-----------------------------------------------------
        Action action = new CommandPanelAction ( dp );

        startButton.setActionCommand( "START" );
        startButton.addActionListener( action );

        stopButton.setActionCommand( "STOP" );
        stopButton.addActionListener( action );

    }

    public JLabel getCounterLabel() {
        return this.counterLabel;
    }
}
::::::::::::::
CommandPanelAction.java
::::::::::::::
import javax.swing.*;
import java.awt.event.*;
import java.net.*;

/**
* <pre>
* $Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
* @author KISHI Yasuhiro
* コマンドパネル上でのアクションを制御するクラス
* </pre>
*/

public class CommandPanelAction extends AbstractAction {
    private DrawingPanel dp;

    public CommandPanelAction( DrawingPanel dp ) {
        this.dp = dp;
    }

    public synchronized void actionPerformed( ActionEvent e ) {
        String actionCommand = e.getActionCommand();

        if ( "START".equals( actionCommand ) ) {
            System.out.println( "STARTがクリックされました!" );
            dp.setRunningStatus( true );
        } else if ( "STOP".equals( actionCommand ) ) {
            System.out.println( "STOPがクリックされました!" );
            dp.setRunningStatus( false );
        }

    }
}
::::::::::::::
DrawingPanel.java
::::::::::::::
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class DrawingPanel extends JPanel implements Runnable {

    private long counter = 0;
    private JLabel counterLabel;
    private boolean runningStatus;
    private Thread thread;
    private CellList cellList;

    private CellulaManager cellulaManager;
    private Cellula cellula;

    public DrawingPanel() {

        // セルリスト
        cellList = new CellList();
        cellList.setBoundary( 80, 60 );
        cellList.add( new Cell( 40, 30 ) );
        cellList.start();

        // Cellula
        cellulaManager = new CellulaManager( 360 );
        cellula = new Cellula( 30, 30, 80, 60, cellulaManager );

        //---------------------------------------------------
        // スレッド開始
        //---------------------------------------------------
        runningStatus = true;
        thread = new Thread( this );
        thread.start();
    }

    /** カウンターラベルの参照を引き渡す */
    public void setReference( JLabel counterLabel ) {
        this.counterLabel = counterLabel;
    }

    /** 稼動・停止の状態を変更する */
    public synchronized void setRunningStatus( boolean status ) {
        this.runningStatus = status;
        System.out.println( "runningStatus = " + runningStatus );

        if ( runningStatus == false && thread != null ) {
            // スレッドのインスタンスを消滅させる必要あり
            thread = null;
        }
        if ( runningStatus == true && thread == null ) {
            // 一度run()メソッドが完了したら再度スタートさせなければいけない
            thread = new Thread( this );
            thread.start();
        }
    }

    public void run() {
        while ( runningStatus ) {

            SwingUtilities.invokeLater(
                new Runnable() {
                    public void run() {
                        repaint();
                    }
                }
            );

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

            counter++;
            if ( counter % 100 == 0 ) {
                System.out.println( counter );
            }

            //-----------------------------------------------------
            // コマンドパネル内のカウンターラベルの値を更新
            //-----------------------------------------------------
            counterLabel.setText( String.valueOf( counter ) );
        }
    }

    public void clearScreen( Graphics g ) {
        int width = getWidth();
        int height = getHeight();

        //--------------------------------------------------
        // 画面クリア
        //--------------------------------------------------
        g.setColor( Color.black );
        g.fillRect( 0 , 0 , width , height );

    }

    public void paintComponent( Graphics g ) {

        int width = getWidth();
        int height = getHeight();

        clearScreen( g );

        // 格子を描画
        GridPainter.paint( g, width, height );

        // セルリストを描画
        CellPainter.paint( g, cellList );

        // Cellula
        cellulaManager.paintAll( g );
    }

}
::::::::::::::
GridPainter.java
::::::::::::::
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

/**
$Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
@author KISHI Yasuhiro
*/

public class GridPainter {

    static public final int PITCH = 10;

    static public void paint( Graphics g, int width, int height ) {
        g.setColor( Color.blue );
        for ( int x = 0;x < width;x += PITCH ) {
            g.drawLine( x, 0, x, height );
        }
        for ( int y = 0;y < height;y += PITCH ) {
            g.drawLine( 0, y, width, y );
        }
    }

}
::::::::::::::
StruggleForSurvival.java
::::::::::::::
import javax.swing.*;

import java.awt.*;
import java.awt.event.*;

/**
* <pre>
* 生存競争をシミュレーションするApplet
* </pre>
* $Id: thread2.html,v 1.1 2009/06/22 16:12:30 kishi Exp kishi $
* @author KISHI Yasuhiro
*/

public class StruggleForSurvival extends JApplet {

    public void init() {

        Container contentPane = getContentPane();

        System.out.println( getWidth() + " : " + getHeight() );

        DrawingPanel dp = new DrawingPanel();
        dp.setPreferredSize( new Dimension( getWidth() , getHeight() - 100 ) );

        CommandPanel cp = new CommandPanel( dp );
        dp.setPreferredSize( new Dimension( getWidth() , 100 ) );

        //------------------------------------------------------------------------------------
        // カウンターラベルの参照先をセット --> スレッドにより値をインクリメントさせていく
        //------------------------------------------------------------------------------------
        dp.setReference( cp.getCounterLabel() );

        // 各パネルを配置
        contentPane.add( dp, BorderLayout.CENTER );
        contentPane.add( cp, BorderLayout.SOUTH );

    }

}




戻る









inserted by FC2 system