アレイを通して細胞の成長を示すプログラムを作っています。取得したので、スタートボタンを押すと、配列はwhile(true){}ループで10秒ごとに更新されます。それに関する問題は、一時停止ボタンを押してループを停止できるようにしたいのですが、ループ中に、どのコントロールも使用できません。フレームを更新するには、orerの無限ループ以外のものが必要です。
私は少し初心者ですが、現在javaクラスにいます。だから私は言語をある程度理解しています。
アレイを通して細胞の成長を示すプログラムを作っています。取得したので、スタートボタンを押すと、配列はwhile(true){}ループで10秒ごとに更新されます。それに関する問題は、一時停止ボタンを押してループを停止できるようにしたいのですが、ループ中に、どのコントロールも使用できません。フレームを更新するには、orerの無限ループ以外のものが必要です。
私は少し初心者ですが、現在javaクラスにいます。だから私は言語をある程度理解しています。
配列を処理するには、別のスレッドを使用することをお勧めします。スレッドセーフオブジェクトを使用していることを確認し(Javaドキュメントを確認)、開始するときにスレッドオブジェクトで.start()を呼び出すだけです。setPaused(true)を介して一時停止できるように、ポインタを保持します
このようなもの....
class MyArrayUpdater extends Thread {
private volatile boolean enabled = true;
private volatile boolean paused = true;
@Override
public void run() {
super.run();
try {
while (enabled) {
if (!paused) {
// Do stuff to your array here.....
}
Thread.sleep(1);
}
} catch (InterruptedException ex) {
// handle ex
}
}
public void setEnabled(boolean arg) {
enabled = arg;
}
public void setPaused(boolean arg) {
paused = arg;
}
}
必要なのは、コンポーネントの状態(この場合は細胞の成長)を変更するタイマーを使用してから、を呼び出すことです。JComponent.repaint()
このタイマーをキャンセルして一時停止してから再開するには、新しいタイマーを作成するだけです。
したがって、次の2つのメソッドを定義できます。
private Timer timer;
...
public void startPaiting() {
timer = new Timer();
timer.schedule( new TimerTask(){
public void run(){
changeState();
repaint();
}
},0, 10000 ); // 10 s.
}
public void pause(){
timer.cancel();
}
次に、[一時停止/再開]ボタンで、次の[一時停止/startPaiting]メソッドを呼び出します。
if( e.getActionCommand().equals("Pause")){
growPanel.pause();
setText("Resume");
} else {
growPanel.startPaiting();
setText("Pause");
}
実行を確認するための完全なソースコードは次のとおりです。
import javax.swing.*;
import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.*;
import java.util.Timer;
import java.util.TimerTask;
public class Grow {
public static void main( String [] args ) {
JFrame frame = new JFrame();
final GrowPanel growPanel = new GrowPanel();
frame.add( growPanel );
frame.add( new JPanel(){{
add( new JButton("Pause"){{
addActionListener( new ActionListener(){
public void actionPerformed( ActionEvent e ){
if( e.getActionCommand().equals("Pause")){
growPanel.pause();
setText("Resume");
} else {
growPanel.startPaiting();
setText("Pause");
}
}
});
}});}}, java.awt.BorderLayout.SOUTH );
frame.setSize( 400, 300 );
frame.setVisible( true );
}
}
class GrowPanel extends JComponent {
private int x;
private int y;
private Timer timer;
GrowPanel() {
x = 10;
y = 10;
startPaiting();
}
public void startPaiting() {
timer = new Timer();
timer.schedule( new TimerTask(){
public void run(){
changeState();
repaint();
}
},0, 100 ); // or 10000 which is 10 s.
}
public void pause(){
timer.cancel();
}
public void paintComponent( Graphics g ){
g.fillOval( x, y, 10, 10 );
}
private void changeState(){
x+=10;
if( x >= 400 ) {
y+=10;
x = 0;
}
if( y >= 300 ){
y = 10;
}
}
}
これらの「ボタン」がSwingボタンの場合、これを行う方法は次のとおりです。[スタート]ボタンで、10秒ごとに更新を行う新しいjavax.swing.Timerオブジェクトを作成します。次に、[一時停止]ボタンでそのタイマーを停止します。
シミュレーションをスレッドで実行したい(Runnable Interfaceを探してください)。次に、このスレッドにメッセージを渡して、一時停止、続行、および停止できます。
個人的には、またはよりもクラスを使用するTimer
方が好きです。タイマークラスは、コードの定期的な実行とキャンセルの両方を処理します。Thread
Thread.sleep()
コードは次のようになります。
TimerTask myTask = new TimerTask() {
public void run() {
// here goes my code
}
};
Timer timer = new Timer();
timer.schedule(myTask, 0 /*starts now*/, 10 * 1000 /* every 10 seconds */);
// whenever you need to cancel it:
timer.cancel();
うん。イベントディスパッチャスレッドで描画を行っているようです。イベント(ボタンを押す)は、最後に呼び出されたときからコントロールを戻さなかったため、呼び出される機会がありません...
あなたが探しているのはマルチスレッドです。データ処理を取得して2番目のスレッドに配置し、非同期で実行し、メインスレッドを使用してユーザー入力を確認します。
もちろん、これには2つのスレッド間で通信するためにセマフォを使用することも必要になる場合があります。あなたはどのレベルのクラスにいますか?これらのトピックの両方をすでにカバーしましたか?
wait()/ notify()機構を見てください。簡単に言うと、スレッドは10秒間待機できますが、外部イベントが発生したことが通知されます。
この問題を処理する別の方法は、ジョブのBlockingQueueを使用することです。