窗口模式下的 BufferStrategy 导致持续强烈的白屏闪烁
BufferStrategy in windowed mode causes constant intense white screen flicker
我根据我在 Whosebug 上找到的大量示例将这段代码放在一起。当我 运行 程序时,整个屏幕都在剧烈闪烁。我确定我忽略了一些简单的事情,但到目前为止还无法找到解决方案。主要是在在线论坛阅读的帮助下,我已经调试了几个小时,所以我想是时候问听众了。
public class 屏幕扩展 JComponent {
@Override
public Dimension getPreferredSize(){
Dimension tempDimension = Toolkit.getDefaultToolkit().getScreenSize();
return tempDimension;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)bufferStrategy.getDrawGraphics();
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
if(game==null){
drawSplash(g2D);
}else{
drawBoard(g2D);
}
g2D.dispose();
bufferStrategy.show();
}
}
如果需要任何额外的代码,我可以提供。谢谢你的帮助,Whosebug!
要获得您正在获得的结果,您要么有另一个从 Canvas
延伸的 class,要么正在使用顶级容器中的 BufferStrategy
。无论哪种情况,两者都必须在屏幕上可见。
基本上,他们是在互相争斗,因为他们是两种不同的绘画算法。 Swing 是一种被动绘制算法,根据需要绘制更新,而 BufferStrategy
使用主动算法,需要您根据需要安排对缓冲区的更新。
两者都使用双缓冲算法。
所以,你应该选择一个...
public class Screen extends JComponent {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g.create();
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
if (game == null) {
drawSplash(g2D);
} else {
drawBoard(g2D);
}
g2D.dispose();
}
}
或类似...
public void gameEngine(BufferStrategy strategy) {
// Main loop
while (!done) {
// Prepare for rendering the next frame
// ...
// Render single frame
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics2D g2D = (Graphics2D) strategy.getDrawGraphics();
// Render to graphics
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
if (game == null) {
drawSplash(g2D);
} else {
drawBoard(g2D);
}
// Dispose the graphics
g2D.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());
}
}
这几乎是从 JavaDocs for BufferStrategy
中撕下的
顺便说一句,这...
@Override
public Dimension getPreferredSize(){
Dimension tempDimension = Toolkit.getDefaultToolkit().getScreenSize();
return tempDimension;
}
是一个非常糟糕的设计,你对组件的状态做出的假设可能不符合现实。你应该允许 window 决定它最终想要多大,这可以通过使用 setExtendedState
并传递它 JFrame.MAXIMIZED_BOTH
来实现,这将考虑其他 OS元素,如任务栏或停靠栏
我根据我在 Whosebug 上找到的大量示例将这段代码放在一起。当我 运行 程序时,整个屏幕都在剧烈闪烁。我确定我忽略了一些简单的事情,但到目前为止还无法找到解决方案。主要是在在线论坛阅读的帮助下,我已经调试了几个小时,所以我想是时候问听众了。
public class 屏幕扩展 JComponent {
@Override
public Dimension getPreferredSize(){
Dimension tempDimension = Toolkit.getDefaultToolkit().getScreenSize();
return tempDimension;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D)bufferStrategy.getDrawGraphics();
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
if(game==null){
drawSplash(g2D);
}else{
drawBoard(g2D);
}
g2D.dispose();
bufferStrategy.show();
}
}
如果需要任何额外的代码,我可以提供。谢谢你的帮助,Whosebug!
要获得您正在获得的结果,您要么有另一个从 Canvas
延伸的 class,要么正在使用顶级容器中的 BufferStrategy
。无论哪种情况,两者都必须在屏幕上可见。
基本上,他们是在互相争斗,因为他们是两种不同的绘画算法。 Swing 是一种被动绘制算法,根据需要绘制更新,而 BufferStrategy
使用主动算法,需要您根据需要安排对缓冲区的更新。
两者都使用双缓冲算法。
所以,你应该选择一个...
public class Screen extends JComponent {
@Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
Graphics2D g2D = (Graphics2D) g.create();
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
if (game == null) {
drawSplash(g2D);
} else {
drawBoard(g2D);
}
g2D.dispose();
}
}
或类似...
public void gameEngine(BufferStrategy strategy) {
// Main loop
while (!done) {
// Prepare for rendering the next frame
// ...
// Render single frame
do {
// The following loop ensures that the contents of the drawing buffer
// are consistent in case the underlying surface was recreated
do {
// Get a new graphics context every time through the loop
// to make sure the strategy is validated
Graphics2D g2D = (Graphics2D) strategy.getDrawGraphics();
// Render to graphics
g2D.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER)); //sprites overlap instead of overwrite
if (game == null) {
drawSplash(g2D);
} else {
drawBoard(g2D);
}
// Dispose the graphics
g2D.dispose();
// Repeat the rendering if the drawing buffer contents
// were restored
} while (strategy.contentsRestored());
// Display the buffer
strategy.show();
// Repeat the rendering if the drawing buffer was lost
} while (strategy.contentsLost());
}
}
这几乎是从 JavaDocs for BufferStrategy
顺便说一句,这...
@Override
public Dimension getPreferredSize(){
Dimension tempDimension = Toolkit.getDefaultToolkit().getScreenSize();
return tempDimension;
}
是一个非常糟糕的设计,你对组件的状态做出的假设可能不符合现实。你应该允许 window 决定它最终想要多大,这可以通过使用 setExtendedState
并传递它 JFrame.MAXIMIZED_BOTH
来实现,这将考虑其他 OS元素,如任务栏或停靠栏