EDIT HAIJava: làm thế nào để làm đệm đôi trong Swing?
Để ngăn chặn ý kiến snarky và một dòng câu trả lời thiếu điểm: IFF nó cũng đơn giản như gọi setDoubleBuffered (true), sau đó làm thế nào để tôi nhận được quyền truy cập vào bộ đệm ẩn hiện để tôi có thể bắt đầu rối tung với bộ đệm dữ liệu pixel cơ bản của BufferedImage?
Tôi đã dành thời gian để viết một đoạn mã đang hoạt động (có vẻ thú vị), vì vậy tôi thực sự đánh giá cao câu trả lời thực sự trả lời (câu hỏi của tôi) và giải thích cái này hoạt động như thế nào -liners and snarky comments;)
Đây là một đoạn mã hoạt động đã trả về một hình vuông trên JFrame. Tôi muốn biết về các cách khác nhau có thể được sử dụng để chuyển đổi đoạn mã này để nó sử dụng bộ đệm đôi. Lưu ý rằng cách tôi xóa màn hình và vẽ lại hình vuông không phải là hiệu quả nhất nhưng điều này thực sự không phải là câu hỏi này là gì (theo một cách nào đó, tốt hơn là vì ví dụ này là hơi chậm một chút).). Về cơ bản, tôi cần sửa đổi liên tục nhiều pixel trong BufferedImage (như có một số loại hoạt ảnh) và tôi không muốn xem các tạo phẩm trực quan do đệm một lần trên màn hình.
Tôi có một JLabel có Biểu tượng là một ImageIcon gói một BufferedImage. Tôi muốn sửa đổi BufferedImage đó.
Điều gì phải được thực hiện để điều này trở thành bộ đệm đôi?
Tôi hiểu rằng bằng cách nào đó "hình ảnh 1" sẽ được hiển thị trong khi tôi sẽ vẽ trên "hình ảnh 2". Nhưng sau đó khi tôi vẽ xong trên "hình ảnh 2", làm cách nào để "nhanh" thay thế "hình ảnh 1" bởi "hình ảnh 2"?
Đây có phải là điều tôi nên làm theo cách thủ công, chẳng hạn như, bằng cách hoán đổi ImageIcon của JLabel?
Tôi có nên luôn luôn vẽ trong cùng một BufferedImage sau đó làm một 'blit' nhanh chóng của các điểm ảnh BufferedImage trong BufferedImage của ImageLcon của JLabel? (Tôi đoán không và tôi không thấy làm thế nào tôi có thể "đồng bộ" điều này với "dòng trống dọc" của màn hình [hoặc tương đương trong màn hình phẳng: ý tôi là, để 'đồng bộ' mà không can thiệp vào thời điểm màn hình tự làm mới pixel, để ngăn chặn sự cắt xén]).
Còn các lệnh "repaint" thì sao? Tôi có giả sử kích hoạt bản thân mình không? Tôi nên gọi số nào repaint() hoặc cái gì khác?
Yêu cầu quan trọng nhất là tôi phải sửa đổi pixel trực tiếp trong bộ dữ liệu pixel của hình ảnh.
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
Đây là không cho một ứng dụng Java toàn màn hình, nhưng một ứng dụng Java thông thường, chạy trong cửa sổ (hơi nhỏ) của riêng mình.
Swing được đệm đôi theo mặc định. Đây không phải là AWT. – camickr
Vẫn đang chờ ai đó đăng mã thực tế mà chúng tôi có thể kiểm tra xem liệu bộ đệm đôi có xứng đáng với nỗ lực không. – camickr
Tôi đoán bạn đã hiểu nhầm swing. Bạn không thể truy cập bộ đệm ngoại tuyến (chưa được sửa đổi). Swing sẽ vượt qua bộ đệm để cha mẹ của bạn, và cha mẹ của bạn sẽ sửa đổi nó. ... Để làm những gì bạn muốn, bạn phải * disable * swing doublebuffering và làm điều đó với, BufferedImage. Nếu bạn muốn thực sự "bitblt" thực, bạn phải sử dụng thành phần "nặng" trong AWT. –