EDIT TWOstrong >
Чтобы предотвратить snarky комментарии и однострочные ответы не хватало точки: IFF это так же просто, как вызов setDoubleBuffered (true), то как мне получить доступ к текущему автономному буферу, чтобы я мог начать возиться с базовым пикселем BufferedImage DataBuffer?
Я потратил время на то, чтобы написать пробег кода (который тоже выглядит забавным), поэтому я бы очень благодарен за ответы, которые отвечают (что шокирует) мой вопрос и объясняют, что/как это работает, лайнеры и snarky комментарии;)
Вот фрагмент кода, который отскакивает квадрат через JFrame. Я хотел бы узнать о различных способах, которые могут быть использованы для преобразования этого фрагмента кода, чтобы он использовал двойную буферизацию.
Обратите внимание, что способ очистки экрана и перерисовки квадрата не самый эффективный, но на самом деле это не тот вопрос (в каком-то смысле, лучше для этого примера, чтобы он был несколько медленным).
В принципе, мне нужно постоянно изменять много пикселей в BufferedImage (например, иметь какую-то анимацию), и я не хочу видеть визуальные артефакты из-за однобуферизации на экране.
У меня есть JLabel, чей значок - ImageIcon, обертывающий BufferedImage. Я хочу изменить BufferedImage.
Что нужно сделать, чтобы это стало двойным буфером?
Я понимаю, что покажется "образ 1", пока я рисую "образ 2". Но как только я закончил рисовать "образ 2", как мне "быстро" заменить "изображение 1" на "изображение 2"?
Это что-то, что я должен делать вручную, например, путем замены самого JLabel ImageIcon?
Должен ли я всегда рисовать в том же BufferedImage, а затем быстро "блистать" из этих пикселей BufferedImage в JLabel ImageIcon BufferedImage? (Я думаю, нет, и я не вижу, как я мог бы "синхронизировать" это с монитором "вертикальная пустая строка" [или эквивалент в плоском экране: я имею в виду, чтобы "синхронизировать", не мешая моменту, когда сам монитор обновляет его пикселей, чтобы предотвратить сдвиг]).
Как насчет "перекрасить" заказы? Предполагаю ли я сам их инициировать? Который/когда я должен называть перерисовку() или что-то еще?
Наиболее важным требованием является то, что я должен изменять пиксели непосредственно в databuffer пикселей пикселей.
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, работающего в собственном (несколько маленьком) окне.