わかりましたので、ボタンがクリックされるたびにカウンターに値を追加する簡単なプログラムを作成しました。ここで、「自動」ボタンをクリックしたときにカウンターの値を増やす「自動」ボタン機能を追加したいと思います。画面に各カウンター値を表示しないため、ループが完了すると値が更新されるため、問題が発生します。これが私のコードです。
import Java.awt.FlowLayout;
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import Java.util.concurrent.TimeUnit;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Gui extends JFrame{
private static final long serialVersionUID = 1L;
private JButton uselesButton;
private JButton autoButton;
private FlowLayout layout;
private long counter = 0;
public Gui() {
super("Button");
layout = new FlowLayout(FlowLayout.CENTER);
this.setLayout(layout);
uselesButton = new JButton(String.format("Pressed %d times", counter));
add(uselesButton);
uselesButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
counter++;
uselesButton.setText(String.format("Pressed %d times", counter));
}
});
autoButton = new JButton("Auto");
add(autoButton);
autoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for(long i =0; i < 99999999;i++) {
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e1) {
System.out.println("ERROR");
}
counter = i;
uselesButton.setText(String.format("Pressed %d times", counter));
}
}
});
}
}
私は初心者であることを覚えておいてください...
使用方法についてのチュートリアルをご覧ください Swing Timer そして、私の解決策を見てください:
import Java.awt.FlowLayout;
import Java.awt.event.ActionEvent;
import Java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
public class Gui extends JFrame {
private static final long serialVersionUID = 1L;
private JButton uselesButton;
private JButton autoButton;
private FlowLayout layout;
private long counter = 0;
private javax.swing.Timer timer;
public Gui() {
super("Button");
layout = new FlowLayout(FlowLayout.CENTER);
setLayout(layout);
setDefaultCloseOperation(3);
setSize(300, 300);
setLocationRelativeTo(null);
//initialing swing timer
timer = new javax.swing.Timer(100, getButtonAction());
autoButton = new JButton("Auto");
add(autoButton);
autoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
if (!timer.isRunning()) {
timer.start();
} else {
timer.stop();
}
}
});
}
private ActionListener getButtonAction() {
ActionListener action = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
autoButton.setText(String.format("Pressed %d times", ++counter));
if (counter > 1000) {
timer.stop();
}
}
};
return action;
}
public static void main(String... args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
new Gui().setVisible(true);
}
});
}
}
ここでの問題は、システムがループにあるため、変更をペイントできないことです。そのためには、新しいスレッドを開く必要があります。新しいスレッドがループを行い、メインスレッドがフォームを再描画します。
もう1つ、メインスレッドでスリープ状態にしないでください。 sleep(10)
の代わりに10ミリ秒ごとに刻むタイマーを使用できます ここ は例です
このループ内に入ると、コードがGUIスレッド(EDT)をブロックするため(GUIがハングし、ボタンは完了するまで更新されません)、別のワーカースレッド内にコードを追加する必要があります。
autoButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
new Thread(new Runnable() {
@Override
public void run() {
for(long i =0; i < 99999999;i++) {
try {
TimeUnit.MILLISECONDS.sleep(10);
} catch (InterruptedException e1) {
System.out.println("ERROR");
}
counter = i;
Java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
uselesButton.setText(String.format("Pressed %d times", counter));
}
});
}
}
}).start();
}
});