【发布时间】:2012-10-29 02:06:09
【问题描述】:
我正在编写一个 Applet 游戏,我希望 Applet 在其中重新调整大小以填充浏览器窗口。我知道这可能与 HTML 有关,现在我只是假设我有一个小程序,它偶尔会强制更改大小。
使用 GridBagLayout,我在重新调整大小时遇到了很多闪烁的问题(在重绘期间它似乎正在清除每个 JPanel - 我已经尝试覆盖每个 JPanel 的 update() 方法)。我决定将我的游戏的大小调整推迟到窗口大小调整完成之后——既是为了避免闪烁,也不必在我的游戏代码中处理许多快速和小规模的调整。
我有这方面的工作代码,我将在下面附上(虽然略有简化)。但是,这仅在窗口在两个方向上拉伸得更大时才有效。如果宽度或高度有一个瞬间缩小,游戏会立即折叠成左上角的一个小方块。
如何解决此问题,让游戏继续正常运行,但在调整大小时让图像暂时被覆盖?
为了解释我的代码,我有一个 JPanel,其中包含我的整个游戏布局,位于顶部 GridBagLayout 的 0,0 位置,没有任何权重。我在位置 1,1 有一个空标签(称为 emptySpace),每个方向的权重为 1.0:
我使用以下代码使游戏窗口占据了整个空间,但在重新调整大小时除外:
public class Isometric extends Applet {
//last measured width/height of the applet
public int APPWIDTH;
public int APPHEIGHT;
boolean resizing = false;
int resizeNum = 0;
//Game extends JPanel
Game game;
JPanel window;
JLabel emptySpace;
//one-time startup
public void init(){
APPWIDTH = this.getWidth();
APPHEIGHT = this.getHeight();
addComponents();
//calls checkSize() every 200ms
Timer timer = new Timer();
timer.schedule(new TimerTask(){
public void run(){
checkSize();
}
},200, 200);
}
private void checkSize(){
//if the dimensions have changed since last measured
if(APPWIDTH != this.getWidth() || APPHEIGHT != this.getHeight()){
APPWIDTH = this.getWidth();
APPHEIGHT = this.getHeight();
resizing = true;
}
else if(resizeNum > 2){ //didn't resize in last 400ms
resizing = false;
resizeNum = 0;
resize();
}
if(resizing){
resizeNum++;
}
}
private void resize(){
APPWIDTH = this.getWidth();
APPHEIGHT = this.getHeight();
//set new preferred size of game container
window.setPreferredSize(new Dimension(APPWIDTH, APPHEIGHT));
GridBagConstraints c = new GridBagConstraints();
c.gridx = 1;
c.gridy = 1;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 1.0;
c.weighty = 1.0;
this.remove(emptySpace); //remove empty space to allow container to stretch to preferred size
this.add(emptySpace, c); //add empty space again now with zero width/height
validate(); //recalculates everything so changes occur properly
}
private void addComponents(){
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
window = new JPanel();
window.setLayout(new GridBagLayout());
window.setPreferredSize(new Dimension(APPWIDTH, APPHEIGHT));
c.anchor = GridBagConstraints.NORTHWEST;
c.fill = GridBagConstraints.BOTH;
c.gridx = 0;
c.gridy = 0;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 0.0;
c.weighty = 0.0;
this.add(window,c);
emptySpace = new JLabel();
c.gridx = 1;
c.gridy = 1;
c.gridwidth = 1;
c.gridheight = 1;
c.weightx = 1.0;
c.weighty = 1.0;
this.add(emptySpace, c);
}
//app close
public void destroy(){
System.exit(0);
}
}
【问题讨论】:
-
我用“双缓冲”标签标记了这个。我没有在此处包含任何代码,但我正在努力使其双缓冲,并且我认为要完成我想要的,我可能必须采用双缓冲图像并只绘制将适合屏幕...当然,我必须克服组件仍然缩小的问题,因为首选尺寸太大。
-
使用
JApplet而不是旧的java.awt.Applet。 Swing 的JApplet将使您在调整大小时更顺畅地重新绘制。 -
@Reimeus 我会试试看是否有帮助。但我仍然会遇到这个问题
-
顶级容器不是双缓冲的,最好扩展一个 JPanel(或简单地添加你的组件)并将其添加到 JApplet
-
@Reimeus,这完全解决了闪烁问题。它运作良好,我想我会忘记我的其他计划。如果您将评论改写为答案,我会接受。 =)
标签: java applet resize gridbaglayout doublebuffered