Monday, December 31, 2012

Java : Resize Component according to WIndow Resize

Here I post some of my own experiment about layout manager.. specially on about resize-ing.. I mean when we resize the window or frame using mouse, the component inside also resize accordingly to window size..

Below is some my code, and also below is just a bit experiment between 3 layout manager, GridBagLayout, BorderLayout, FlowLayout, all is implement on JFrame (not JPanel). I may do further experiment about this (try to implement on JPanel also with more Layout manager). I will update once I done another experiment.
import java.awt.BorderLayout;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Dimension;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.geom.Rectangle2D;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;


/** Author Dell

*/

public class Resizeable{
    
    public static void main(String[] args) {
        LFrame testFrame = new LFrame();
        
        
    }
}

class LFrame extends JFrame{
    int valueI = 0; /**Assign value here to switch among layout 
                       Assign with value = 0,1,2*/
    LPanel testPanel;
    Double WindowWidth, WindowHeight, WScale, HScale;
    
    private static final int DEFAULT_WIDTH = 300;
    private static final int DEFAULT_HEIGHT = 300;
    public LFrame(){
        setTitle("Test Layout");
        setSize(DEFAULT_WIDTH, DEFAULT_HEIGHT);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        GridBagLayout gridBagLayout = new GridBagLayout();
        BorderLayout borderLayout = new BorderLayout();
        FlowLayout flowLayout = new FlowLayout();
        
        testPanel = new LPanel(this);
        
        switch (valueI) {
            case 0 : setLayout(gridBagLayout);
                     add(testPanel, new GBC(0,0).setWeight(100, 100).setFill(GBC.BOTH));
                     break;
            case 1 : setLayout(borderLayout);
                     add(testPanel, BorderLayout.CENTER);
                     break;
            case 2 : setLayout(flowLayout);
                     add(testPanel);
                     break;
                
        }
        
        addComponentListener(new ComponentListener() {

            @Override
            public void componentResized(ComponentEvent e) {
                WindowWidth = getSize().getWidth();
                WindowHeight = getSize().getHeight();
                WScale = WindowWidth/DEFAULT_WIDTH;
                HScale = WindowHeight/DEFAULT_HEIGHT;

                testPanel.setScale(WScale, HScale);

                showWindowSize();
                testPanel.showPanelSize();
                testPanel.showComponentSizeScale();
                testPanel.showPosition();
                revalidate();
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void componentShown(ComponentEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }

            @Override
            public void componentHidden(ComponentEvent e) {
                //throw new UnsupportedOperationException("Not supported yet.");
            }
        });
        
        setVisible(true);
    }
    
    public void showWindowSize(){
        System.out.println("Window Width : " + getWidth() + " Height : " + getHeight());
    }
    
    public int getWindowWidthSize(){
        return getWidth();
    }
    
    public int getWindowHeightSize(){
        return getHeight();
    }
}

class LPanel extends JPanel{
    LComponent testComponent;
    LFrame aReferFrame;
    Double WScale = 1.0;
    Double HScale = 1.0;
    class LComponent extends JComponent{
        public void paintComponent(Graphics g){
            Graphics2D g2 = (Graphics2D) g;
            
            Rectangle2D rect = new Rectangle2D.Double(0, 0, 150, 150); 
            /**
             *  Set 150 so it easier to predict with bare eyes
             *  Always fill a quarter of WIndows size
             */
            g2.scale(WScale, HScale);
            g2.draw(rect);
        }
    }
    
    public LPanel(LFrame referFrame){
        aReferFrame = referFrame;
        /**
         * aReferFrame is a variable of LFrame
         * It's contain a reference to the Frame I created earlier (above)
         */
        //setPreferredSize(new Dimension(300, 300));
        //setPreferredSize(new Dimension(aReferFrame.getWindowWidthSize(), aReferFrame.getWindowHeightSize()));
        /**
         * setPreferredSize didn't use because I set Fill attribute in GridBagConstraint of this Panel as BOTH,
         * so as default it will put the panel in the largest possible size.
         * I mean this -> add(testPanel, new GBC(0,0).setWeight(100, 100).setFill(GBC.BOTH));
         * For other layout manager, you may try to remove of the comment // for setPreferredSize
         */
        GridBagLayout gridBagLayoutPanel = new GridBagLayout();
        setLayout(gridBagLayoutPanel);
        
        testComponent = new LComponent();
        add(testComponent, new GBC(0, 0).setWeight(100, 100).setAnchor(GBC.CENTER).setFill(GBC.BOTH));
        
    }
    
    public void setScale(Double Wscale, Double Hscale){
        WScale = Wscale;
        HScale = Hscale;
    }
    
    public void showPanelSize(){
        System.out.println("Panel Width : " + getWidth() + " Height : " + getHeight());
    }
    
    public void showComponentSizeScale(){
        System.out.println("Component Width : " + testComponent.getWidth() + " Height : " + testComponent.getHeight());
        System.out.println("Component WScale : " + WScale + " HScale : " + HScale);
    }

    public void showPosition(){
        System.out.println("Panel Position X : " + getX() + " Y : " + getY());
    }
}
/**
 * Below is a Helper class of GridBagConstraint
 */
class GBC extends GridBagConstraints {
    
    public GBC(int gridx, int gridy){
        this.gridx = gridx;
        this.gridy = gridy;
        
    }
    
    public GBC(int gridx, int gridy, int gridwidth, int gridheight){
        this.gridx = gridx;
        this.gridy = gridy;
        this.gridwidth = gridwidth;
        this.gridheight = gridheight;
    }
    
    public GBC setAnchor(int anchor){
        this.anchor = anchor;
        return this;
    }
    
    public GBC setFill(int fill){
        this.fill = fill;
        return this;
    }
    
    public GBC setWeight(double weightx, double weighty){
        this.weightx = weightx;
        this.weighty = weighty;
        return this;
    }
    
    public GBC setInsets(int distance){
        this.insets = new Insets(distance, distance, distance, distance);
        return this;
    }
    
    public GBC setInsets(int top, int left, int bottom, int right){
        this.insets = new Insets(top, left, bottom, right);
        return this;
    }
    
    public GBC setIpad(int ipadx, int ipady){
        this.ipadx = ipadx;
        this.ipady = ipady;
        return this;
    }
}

I try to explain a bit: Start From : (Remember the Layout that I test is Layout for JFrame, so the focus in resizing is the JPanel)
  1. GridBagLayout , in GridBagLayout the panel inside can resize according to windows size.

    In above the test is perform in [setFill(GBC.BOTH)] then when the window in maximize sate. If I put setFill(GBC.VERTICAL) or setFill(GBC.HORIZONTAL) or setFill(GBC.NONE) then the panel size will become one (1) for width (VERTICAL), one (1) for height (HORIZONTAL) or one (1) for both(NONE). This will happen unless you specified the size using setPreferredSize() (the part that I put comment in LPanel class). changing setWeight value didn't do any change because in above the panel only one. So GridBagLayout is very flexible.

  2. BorderLayout, in Border Layout also the panel size can resize according to window size.

    In above I put the LPanel into BorderLayout.CENTER, so the layout manager will automatically set the LPanel in widest size possible (have same behavious as setFill(GBC.BOTH)). In max size of window the Panel will have a quarter of window size. You can do much in Border Layout.

  3. FlowLayout, In Flow Layout you cannot do any change due to a PreferredSize set.

    If you didn't setPreferredSize() for LPanel then the LPanel will have size of one (1). So then you set it up. After you set it up then the size cannot be changed anymore.

    but one thing that I catch is, due to resize of window, the panel didn't change size but the the position do change!! Now I put a tracer method, showPosition(). You may see what happen.. hahaha, I have no explaination regarding this...

    But as I know, Flow Layout will put all component fit in smallest space possible, means all component in one line if possible. If not the Flow Layout will put some component exactly below other component.
That's it that I can tell you, I am not a master in Java, but I keep learning(studing) to be better.

Updated!! : Now, I finally put some additional in a day after the first publish.. ^^.. After a further experiment... I got  a conclusion.. actually I am not very sure in my conclusion because the experiment didn't conducted by follow research method^^. But let me share what I have.

There a some Layout that need the panel being specified in certain size and resulting the panel cannot being re-sized (fixed), they are Flow Layout and Spring Layout.. The rest is able to resize (no need setPreferredSize on Panel)..

My method of testing is simple. I just set the layout using setLayout() on the LPanel what Layout I want to try. Then I add the component (I add 2 components) and in some case if needed I will specified the exact position (e.g. BorderLayout need pre-specified position [PAGE_START, CENTER, LINE_END, etc.])

You may test by yourself if you curious more.. hehe^^ if you find any finding outside of what I have explained then I'll appreciate if you also share through comment below..^^

Hope this can inspire you.

Happy Expressing..!!

No comments:

Post a Comment