Swing はシングルスレッド環境です。つまり、すべての更新と対話は単一のスレッド内で実行されます。Swing もスレッドセーフではありません。つまり、UI に対するすべての更新は、そのスレッド (イベント ディスパッチ スレッドまたは ETD) のコンテキスト内で実行する必要があります。
EDT をブロックするコードは、UI の再描画やユーザーからの入力への応答を (とりわけ) 妨げます。
paint
メソッドの完了が許可されておらず、ETD をブロックしているため、ペイント コードが画面を更新することはありません。実際、アプリケーションが「ハング」したように見えます。
paint
メソッドが呼び出された後すぐに戻り、立て続けに繰り返し呼び出される可能性があるのは例外です。
一般的に言えば、 aThread
はおそらく少しやりすぎjavax.swing.Timer
です。これらの状況では、 a のようなものがより適しています。
public class AnimatedBoat {
public static void main(String[] args) {
new AnimatedBoat();
}
public AnimatedBoat() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new AnimationPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class AnimationPane extends JPanel {
private BufferedImage boat;
private int xPos = 0;
private int direction = 1;
public AnimationPane() {
try {
boat = ImageIO.read(new File("boat.png"));
Timer timer = new Timer(40, new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
xPos += direction;
if (xPos + boat.getWidth() > getWidth()) {
xPos = getWidth() - boat.getWidth();
direction *= -1;
} else if (xPos < 0) {
xPos = 0;
direction *= -1;
}
repaint();
}
});
timer.setRepeats(true);
timer.setCoalesce(true);
timer.start();
} catch (IOException ex) {
ex.printStackTrace();
}
}
@Override
public Dimension getPreferredSize() {
return boat == null ? super.getPreferredSize() : new Dimension(boat.getWidth() * 4, boat.getHeight());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
int y = getHeight() - boat.getHeight();
g.drawImage(boat, xPos, y, this);
}
}
}
補足として。またはのpaint
ようなトップレベルのコンテナのメソッドをオーバーライドする必要はめったにありません。これには多くの正当な理由がありますが、最も関心のあるのは、それらがダブルバッファリングされていないという事実です。画面が更新されると、ちらつきが発生する可能性があります。JApplet
JFrame
のようなものを使用して、代わりにそのメソッドJPanel
をオーバーライドすることをお勧めします。paintComponent
を見てみましょう
詳細については
nbJFrame
私の例では を使用しましたが、アニメーション パネルを取得して に配置するのは簡単なことJApplet
です。これが、最上位のコンテナから拡張する必要がない、または拡張したくないもう 1 つの理由です ;)