編集 2
卑劣なコメントや 1 行の回答が要点を逃すのを防ぐために: IFFはsetDoubleBuffered(true)を呼び出すのと同じくらい簡単です。次に、現在のオフライン バッファにアクセスして、BufferedImage の基になるピクセル データバッファをいじり始めることができるようにするにはどうすればよいですか?
私は実行中のコードを書くのに時間をかけました(これもちょっと楽しそうです)ので、実際に私の質問に答えて(なんてショックです;)、ワンライナーやスナーキーではなく、これがどのように機能しているのかを説明してくれる回答を本当に感謝していますコメント;)
これは、JFrame を横切って正方形をバウンスする実際のコードです。ダブルバッファリングを使用するようにこのコードを変換するために使用できるさまざまな方法について知りたいです。
画面をクリアして正方形を再描画する方法は最も効率的ではないことに注意してください。ただし、これは実際にはこの質問の目的ではありません(ある意味、この例のためには、やや遅い方が良いです)。
基本的に、BufferedImage 内の多くのピクセルを常に変更する必要があり (ある種のアニメーションを使用するため)、画面上の単一バッファリングによる視覚的なアーティファクトを見たくありません。
Icon が BufferedImage をラップする ImageIcon である JLabel があります。その BufferedImage を変更したい。
これがダブルバッファリングされるようにするには、何をする必要がありますか?
「画像2」を描いている最中に「画像1」が表示されるのはなんとなくわかります。しかし、 「image 2」での描画が完了したら、 「image 1」を「image 2」で「すばやく」置き換えるにはどうすればよいですか?
これは、たとえば JLabel の ImageIcon を自分で交換するなど、手動で行うべきことですか?
常に同じ BufferedImage で描画し、JLabel の ImageIcon の BufferedImage でその BufferedImage のピクセルをすばやく「ブリット」する必要がありますか? (いいえ、これをモニターの「垂直空白行」と「同期」する方法がわかりません[またはフラットスクリーンで同等:つまり、モニター自体がリフレッシュする瞬間に干渉せずに「同期」することを意味しますせん断を防ぐために、ピクセル])。
「塗り直し」の注文はどうですか?これらを自分でトリガーすると思いますか?repaint()または他の何かを呼び出す必要があるのはいつですか?
最も重要な要件は、画像のピクセル データ バッファー内のピクセルを直接変更する必要があることです。
import javax.swing.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferInt;
public class DemosDoubleBuffering extends JFrame {
private static final int WIDTH = 600;
private static final int HEIGHT = 400;
int xs = 3;
int ys = xs;
int x = 0;
int y = 0;
final int r = 80;
final BufferedImage bi1;
public static void main( final String[] args ) {
final DemosDoubleBuffering frame = new DemosDoubleBuffering();
frame.addWindowListener(new WindowAdapter() {
public void windowClosing( WindowEvent e) {
System.exit(0);
}
});
frame.setSize( WIDTH, HEIGHT );
frame.pack();
frame.setVisible( true );
}
public DemosDoubleBuffering() {
super( "Trying to do double buffering" );
final JLabel jl = new JLabel();
bi1 = new BufferedImage( WIDTH, HEIGHT, BufferedImage.TYPE_INT_ARGB );
final Thread t = new Thread( new Runnable() {
public void run() {
while ( true ) {
move();
drawSquare( bi1 );
jl.repaint();
try {Thread.sleep(10);} catch (InterruptedException e) {}
}
}
});
t.start();
jl.setIcon( new ImageIcon( bi1 ) );
getContentPane().add( jl );
}
private void drawSquare( final BufferedImage bi ) {
final int[] buf = ((DataBufferInt) bi.getRaster().getDataBuffer()).getData();
for (int i = 0; i < buf.length; i++) {
buf[i] = 0xFFFFFFFF; // clearing all white
}
for (int xx = 0; xx < r; xx++) {
for (int yy = 0; yy < r; yy++) {
buf[WIDTH*(yy+y)+xx+x] = 0xFF000000;
}
}
}
private void move() {
if ( !(x + xs >= 0 && x + xs + r < bi1.getWidth()) ) {
xs = -xs;
}
if ( !(y + ys >= 0 && y + ys + r < bi1.getHeight()) ) {
ys = -ys;
}
x += xs;
y += ys;
}
}
編集
これは、フルスクリーンの Java アプリケーションではなく、独自の (やや小さい) ウィンドウで実行される通常の Java アプリケーション用です。