为何BufferStrategy在渲染循环外调用show()会刷新/无法正常显示?
关于Java Canvas BufferStrategy的问题解答
问题重现
第一段代码调用bs.show()后窗口瞬间黑屏然后无内容:
import java.awt.*; import javax.swing.*; public class Main { static int width = 200; static int height = 200 ; public static void main(String[] args){ JFrame jframe = new JFrame(); Canvas canvas = new Canvas(); BufferStrategy bs; Dimension dim = new Dimension(width,height); canvas.setPreferredSize(dim); jframe.setResizable(false); jframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); jframe.add(canvas); jframe.pack(); jframe.setLocationRelativeTo(null); jframe.setVisible(true); canvas.requestFocus(); bs = canvas.getBufferStrategy(); if(bs == null){ canvas.createBufferStrategy(3); bs = canvas.getBufferStrategy(); } Graphics g = bs.getDrawGraphics(); g.setColor(Color.black); g.fillRect(0,0,canvas.getWidth(),canvas.getHeight()); g.dispose(); bs.show(); } }
改成循环调用bs.show()则能正常显示黑色:
while(true){ bs.show(); }
带休眠的循环也能正常显示(补充异常捕获):
while(true){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } bs.show(); }
问题解答
1. 第一段代码黑色不显示的原因及相关疑问
- 根本原因:不是
bs.show()清空了缓冲区,而是Swing的事件调度线程(EDT)在你调用完bs.show()后,触发了Canvas的自动重绘。Canvas默认的paint方法会清空组件背景(回到默认浅色),直接覆盖了你用BufferStrategy画的黑色。而且main方法执行完毕后,EDT仍会持续处理窗口的重绘请求,导致刚画的黑色瞬间被冲掉。 bs.show()的作用:它仅负责交换缓冲区,把你绘制好的后台缓冲区切换到前台显示,本身不会主动清空任何缓冲区。- 第三段代码能显示的原因:循环里反复调用
bs.show(),相当于每次都把存着黑色内容的后台缓冲区重新切换到前台。哪怕EDT触发重绘清空了当前前台内容,下一次bs.show()又会把黑色缓冲区换上来,所以你能持续看到黑色,和休眠时长无关。
2. 无需循环让黑色持续显示的方法
有两种简单可行的方式:
- 方式一:关闭Canvas的自动重绘
创建Canvas后添加一行代码,阻止Swing自动触发重绘:
同时要确保main线程不提前结束,可在代码末尾加阻塞逻辑:canvas.setIgnoreRepaint(true);// 监听窗口关闭事件,确保程序正常退出 jframe.addWindowListener(new WindowAdapter() { @Override public void windowClosed(WindowEvent e) { System.exit(0); } }); // 让main线程持续阻塞 try { Thread.join(); } catch (InterruptedException e) { e.printStackTrace(); } - 方式二:重写Canvas的paint方法
直接在paint方法里绘制黑色,贴合Swing的重绘机制,每次重绘都会重新生成黑色背景:Canvas canvas = new Canvas() { @Override public void paint(Graphics g) { g.setColor(Color.black); g.fillRect(0, 0, getWidth(), getHeight()); } };
内容的提问来源于stack exchange,提问作者jacob12
相关产品推荐
相关产品推荐

