为了防止尖刻的评论和一个在线回答切中要害:IFF它就像调用简单setDoubleBuffered(真),那么我怎么获取当前离线缓冲所以我可以开始搞BufferedImage的底层像素databuffer?我很花时间写一段代码(这看起来还挺有趣),所以我真的很感谢回答实际回答(真是令人震惊;)我的问题和解释什么/这是如何工作,而不是一个和衬里的评论;)
这是一个代码工作,反弹一个正方形跨JFrame。我想知道可以用来转换这段代码的各种方式,以便它使用双缓冲。
请注意,我清除屏幕并重新绘制正方形的方式并不是最有效的方式,但这实际上不是这个问题的关键所在(从某种意义上来说,为了这个例子它有点慢)。
基本上,我需要不断修改BufferedImage中的很多像素(因为有某种动画),而且我不想看到由于屏幕上的单缓冲而导致的视觉失真。
我有一个JLabel的图标是一个ImageIcon包装BufferedImage。我想修改那个BufferedImage。
需要做些什么以使其变为双缓冲?
据我所知,在某种程度上“图像1”将显示,而我将“图像2”来绘制。但是一旦我画完了“image 2”,我该如何“快速”取代“image 1” by “image 2”?
这是我应该手动做的事情,比如说,通过交换JLabel的ImageIcon自己?
我应该总是在相同的BufferedImage中绘图,然后在JLabel的ImageIcon的BufferedImage中执行BufferedImage像素的快速'blit'? (我猜不,我不知道该如何将它与显示器的“垂直空白线”同步[或者与平板显示器相当:我的意思是,在不干扰显示器本身刷新其时刻的情况下'同步'像素,以防止剪切])。
“repaint”命令怎么样?我想自己触发这些吗?哪个/何时应该打电话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;
}
}
编辑
这是不是一个全屏幕的Java应用程序,而是一个普通的Java应用程序在其自己的(有点小)窗口中运行。
Swing默认为双缓冲。这不是AWT。 – camickr 2010-12-13 15:47:27
仍在等待某人发布我们可以测试的实际代码,以了解双缓冲是否值得。 – camickr 2010-12-14 04:18:26
我想你已经误解了摇摆。您无法访问(未修改的)脱机缓冲区。 Swing会通过缓冲区到您的父级,并且您的父级会修改它。 ...要做你想做的事情,你必须*禁用* swing doublebuffering,并用BufferedImage做。如果你想要做真正的“bitblt”,你必须在AWT中使用“重量级”组件。 – 2012-02-02 09:28:34