0

我正在编写一个 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);
}

}
4

2 回答 2

1

作为一般规则,最好不要将旧的重量级 AWT 与较新的轻量级 Swing 组件混合使用。AWT 组件请求本机系统执行其绘制,并且经常“绘制”应用程序中可能使用的任何 Swing 组件。

Swing 具有增强的绘画模型,可减少闪烁。

在这里,您可以使用JApplet而不是旧的java.awt.Applet. SwingJApplet将在调整大小期间为您提供更平滑的重绘。

另一方面:不要System.exit()从小程序调用。这可能导致整个浏览器被关闭(!)。

于 2012-11-08T20:39:08.420 回答
0

使用组布局。这里链接http://docs.oracle.com/javase/tutorial/uiswing/layout/groupExample.html

尝试水平调整对话框大小以查看布局如何自动调整为新大小。

于 2013-09-05T19:19:45.873 回答