【问题标题】:Re-size components after window resizes窗口调整大小后重新调整组件大小
【发布时间】: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


【解决方案1】:

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

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

在这里,您可以使用JApplet 而不是旧的java.awt.Applet。 Swing 的JApplet 将使您在调整大小时更顺畅地重新绘制。

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

【讨论】:

  • 略读,但特别是对最后一段 +1。
【解决方案2】:

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

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

【讨论】:

    猜你喜欢
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-25
    • 1970-01-01
    • 1970-01-01
    • 2014-03-14
    • 2012-01-24
    相关资源
    最近更新 更多