Question

I am writing an Applet game, in which I would like the Applet to re-size to fill the browser window. I understand that this is possible to do with HTML, and for now am just assuming that I have an applet which will occasionally have size changes forced upon it.

Using GridBagLayout, I have had trouble with having a LOT of flicker during re-sizes (it appears to be clearing each JPanel during redraw - I already tried overriding each JPanel's update() method). I decided to delay the re-size of my game until after the window's re-size is finished - both to avoid flickering and so I don't have to deal with many rapid and small re-sizes in my game code.

I have working code for this, which I will attach (though slightly simplified) below. However, this only works when the window is stretched larger in both directions. If either width or height shrinks even momentarily, the game immediately collapses into a small square in the top-left corner.

How can I fix this behavior, so the game will continue to work normally, but let the image get temporarily covered during a re-size?

To explain my code, I have a single JPanel containing my entire game layout at position 0,0 in the top GridBagLayout without any weight. I have an empty label (called emptySpace) at position 1,1 with a weight of 1.0 in each direction:

layout

I make the Game window take up the entire space except during re-sizes with the following code:

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);
}

}
Was it helpful?

Solution

As a general rule it is better not to mix old heavyweight AWT with the newer lightweight Swing components. AWT components request the native system to perform its painting and often 'paint over' any Swing components that may be used in the application.

Swing has an enhanced painting model which gives you less flicker.

Here, you can use JApplet rather than the old java.awt.Applet. Swing's JApplet will give you smoother repainting during resizing.

On a different note: Don't call System.exit() from the applet. This can potentially lead to the entire browser being closed(!).

OTHER TIPS

Use Group Layout. Here link http://docs.oracle.com/javase/tutorial/uiswing/layout/groupExample.html

Try resizing the dialog horizontally to see how the layout automatically adjusts to the new size.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top