0

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

}
Porthos3
  • 381
  • 5
  • 19
  • I marked this with the "double buffered" tag. I did not include any of that code in here, but I am working on making it double buffered as well, and I think to accomplish what I am wanting, I may have to take the double-buffered image and only draw the part that will fit on-screen... Of course, then, I have to overcome the issue of the component still shrinking because the preferred size is too large. – Porthos3 Nov 08 '12 at 19:40
  • Use `JApplet` rather than the old `java.awt.Applet`. Swing's `JApplet` will give you smoother repainting during resizing. – Reimeus Nov 08 '12 at 19:49
  • @Reimeus I will try that and see if it helps. But I will still be running into this problem – Porthos3 Nov 08 '12 at 19:50
  • Top level containers ain't double buffered, better to extend a JPanel (or somply added your components to it) and add that to the JApplet – MadProgrammer Nov 08 '12 at 20:05
  • @Reimeus, that completely fixed the flickering problem. It works well enough I think I will forget about my other plans. If you rephrase your comment as an answer, I will accept it. =) – Porthos3 Nov 08 '12 at 20:27
  • Applets are not typically intended to be resized. It is possible to use `width`/`height` attributes of `100%` but some browsers ignore them, while other browser/JRE combos will resize the space assigned to the applet, without resizing the applet itself (read 'big gray border around small applet'). My experiments on this matter can be seen [here](http://pscode.org/test/resize/). If you want a resizable GUI, code a frame and launch it using [Java Web Start](http://stackoverflow.com/tags/java-web-start/info). – Andrew Thompson Nov 09 '12 at 00:00

2 Answers2

1

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(!).

Reimeus
  • 158,255
  • 15
  • 216
  • 276
0

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.

Maulzey
  • 4,100
  • 5
  • 22
  • 30