EDIT ДВАJava: как сделать двойную буферизацию в Swing?
Для предотвращения элегантных комментариев и одну строки отвечает пропускает пункт: IFF это так просто, как вызов setDoubleBuffered (правда), то как я могу получить доступ к текущему автономному буферу так что я могу начать возиться с базовым файловым буфером BufferedImage?
Я нашел время, чтобы написать пробег кода (который тоже выглядит забавным), поэтому я действительно ценю ответы, которые отвечают (что шокирует) мой вопрос и объясняют, что/как это работает вместо одного -liners и snarky comments;)
Вот фрагмент кода, который отскакивает квадрат через JFrame. Я хотел бы узнать о различных способах, которые можно использовать для преобразования этого фрагмента кода, чтобы он использовал двойную буферизацию.
Обратите внимание, что способ, которым я очищаю экран и перерисовывать квадрат, не самый эффективный, но на самом деле это не тот вопрос, о котором идет речь (в некотором смысле, это лучше для этого примера,).
В принципе, мне нужно постоянно изменять много пикселей в BufferedImage (например, иметь какую-то анимацию), и я не хочу видеть визуальные артефакты из-за однобуферизации на экране.
У меня есть JLabel, чья иконка является ImageIcon, обертывающей BufferedImage. Я хочу изменить этот BufferedImage.
Что нужно сделать, чтобы это стало двойным буфером?
Я понимаю, что как-то «изображение 1» будет показано, в то время как я буду рисовать на «изображение 2». Но как только я закончил рисовать на «image 2», как мне «быстро» заменить «image 1» от «image 2»?
Является ли это чем-то, что я должен делать вручную, скажем, путем замены самого ImageIcon JLabel?
Должен ли я всегда рисовать в том же BufferedImage, а затем быстро «блистать» из этих пикселей BufferedImage в BufferedImage ImageIcon от JLabel? (Я думаю, нет, и я не вижу, как я могу «синхронизировать» это с «вертикальной пустой линией» монитора [или эквивалентом в плоском экране: я имею в виду, чтобы «синхронизировать», не мешая моменту, когда сам монитор обновляет его пикселей, чтобы предотвратить сдвиг]).
Как насчет заказов «перекрасить»? Предполагаю ли я сам их инициировать? Который/когда именно я должен позвонить repaint() или что-то еще?
Важнейшим требованием является то, что я должен изменять пиксели непосредственно в 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;
}
}
EDIT
Это не для приложения Java полноэкранного, но регулярное приложение Java, работает в своем собственном (несколько малых) окна.
По умолчанию используется качание по умолчанию. Это не AWT. – camickr
Все еще ждет, когда кто-то опубликует фактический код, который мы можем проверить, чтобы увидеть, стоит ли двойная буферизация. – camickr
Я думаю, вы неправильно поняли качели. Вы не можете получить доступ к (немодифицированному) автономному буферу. Swing пропустит буфер до вашего родителя, и ваш родитель изменит его. ... Чтобы делать то, что вы хотите, вы должны * отключить * swing doublebuffering и сделать это, скажем, BufferedImage. Если вы хотите сделать настоящий битбит, вам придется использовать «тяжеловесный» компонент в AWT. –