java swing双缓冲_Java:如何在Swing中进行双缓冲?

本文探讨了在Java Swing中实现双缓冲的方法,以避免视觉工件并提高动画性能。示例代码展示了一个使用双缓冲在JFrame上绘制平移正方形的场景,并讨论了如何直接修改BufferedImage的像素数据,同时询问了最佳实践,如何时和如何触发重绘以及如何有效地更新缓冲区。
摘要由CSDN通过智能技术生成

编辑两个

为了防止snarky评论和单行答案缺少点:IFF就像调用setDoubleBuffered(true)一样简单,那么如何访问当前的脱机缓冲区,以便我可以开始混乱BufferedImage的底层像素数据?

我花了时间写一段经典的代码(看起来也很有趣),所以我真的很感激答案实际上回答(令人震惊的是)我的问题,并解释什么/这是如何工作,而不是一个人和snarky注释 😉

这是一个工作的代码,在JFrame中弹出一个正方形.我想知道可以用来转换这段代码的各种方法,以便它使用双缓冲.

请注意,我清除屏幕并重绘广场的方式不是最有效的,但这真的不是这个问题(在某种程度上,为了这个例子更好,它有点慢).

基本上,我需要不断地修改一个BufferedImage中的很多像素(因为有某种动画),而且我不希望在屏幕上看到单缓冲的视觉工件.

我有一个JLabel,它的Icon是一个ImageIcon,包含一个BufferedImage.我想修改BufferedImage.

需要做些什么来做这个双重缓冲?

我明白,当我将绘制“图像2”时,将会显示“图像1”.但是,一旦我完成了“图像2”的绘制,我如何“快速”将“图像1”替换为“图像2”?

这是我应该手动做的,就像说,通过交换JLabel的ImageIcon自己?

我应该总是在相同的BufferedImage中绘制,然后在JLabel的ImageIcon的BufferedImage中做一个BufferedImage的像素的快速“blit”? (我猜没有,我看不到我可以用显示器的“垂直空白行”[或等同于平面屏幕“同步”我的意思是“同步”,而不会干扰显示器本身刷新的时刻像素,以防止剪切]).

“重绘”订单怎么办?我想是自己触发这个吗?哪个/我什么时候应该调用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应用程序,它运行在自己的(稍小)窗口中.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值