Click here to Skip to main content
15,904,934 members
Articles / Programming Languages / Java / Java8
Tip/Trick

Resizing Frame and Controls with the Same Ratio in Java

Rate me:
Please Sign up or sign in to vote.
0.00/5 (No votes)
8 Oct 2019CPOL1 min read 6.6K   45  
This article is about automatic resizing of a frame and its controls with the same ratio in Java.

Introduction

One thing that I missed in layout managers is the ability to make the controls resize automatically and with the same ratio as that of the resized frame. This means that if the user doubles the width of the frame, then the widths of all the controls and even the distances between them are all become double their initial widths. I have created a quick portable solution for this task. Although it might not be perfect, yet I think it is "good enough" as a starting point. I am just a hobbier anyway, and I think it won't hurt to publish it as someone may find it useful.

Background

I have created a HierarchyBoundsListener class that performs the automatic resizing process. This class then should be added to a panel to become active.

Using the code

Nothing much to say about this class, the code could just be copied and pasted in an application called "test".

C++
/* Warning! This listener should be added AFTER the panel with all
   its components have been created and added.
   Note: Several successive resizings may change significantly the sizes of the
   components due to the accumulated rounding errors. */

package test;

import java.awt.Component;
import java.awt.Font;
import java.awt.event.HierarchyBoundsListener;
import java.awt.event.HierarchyEvent;
import javax.swing.JPanel;

/**
 *
 * @author Bilal Gharib
 */
public class ResizeComponentsListener implements HierarchyBoundsListener {
    
    private int InitialPaneWidth;
    private int InitialPaneHeight;   
    private double InitialArea;
    private final boolean ResizeFont;

    public ResizeComponentsListener(
        int InitialPaneWidth, int InitialPaneHeight, boolean ResizeFont) {
        
        this.InitialPaneWidth = InitialPaneWidth;
        this.InitialPaneHeight = InitialPaneHeight;    
        this.InitialArea = InitialPaneWidth * InitialPaneHeight;
        this.ResizeFont = ResizeFont;
    }
            
    @Override
    public void ancestorMoved(HierarchyEvent e) {
        // not used        
    }

    @Override
    public void ancestorResized(HierarchyEvent e) {
                
        JPanel Panel = (JPanel)e.getSource();
        
        double RatioX = (double)Panel.getWidth() / InitialPaneWidth;
        double RatioY = (double)Panel.getHeight() / InitialPaneHeight;
        
        double CurrentArea = Panel.getWidth() * Panel.getHeight();
        double RatioArea = (double)CurrentArea / InitialArea;
        
        double NewX, NewY, NewWidth, NewHeight, NewFontSize;
        Font NewFont;
                
        for(Component c : Panel.getComponents()){            
            NewX = c.getX() * RatioX;
            NewY = c.getY() * RatioY;
            NewWidth = c.getWidth() * RatioX;
            NewHeight = c.getHeight() * RatioY;               
            c.setLocation((int)Math.round(NewX), (int)Math.round(NewY));
            c.setSize((int)Math.round(NewWidth), (int)Math.round(NewHeight));            
            if (ResizeFont){
                NewFontSize = c.getFont().getSize() * RatioArea;
                NewFont = c.getFont().deriveFont((float)Math.round(NewFontSize));
                c.setFont(NewFont);                
            }                                       
        }                
        this.InitialPaneWidth = Panel.getWidth();
        this.InitialPaneHeight = Panel.getHeight();
        this.InitialArea = CurrentArea;   
    }    
}

The following is a complete code of a "test" program that uses this class. It contains a JFrame with some controls. The last line attaches ResizeComponentsListener to the JFrame.

package test;

Java
import java.awt.Color;
import java.awt.Font;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.BorderFactory;
import javax.swing.SwingConstants;

public class Test {

    public static void main(String[] args) {
               
        JFrame f = new JFrame("Java JFrame!");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(500, 300);
        f.setLocation(250, 150);
        f.getContentPane().setLayout(null);
        
        Font fnt = new Font("Tahoma", Font.BOLD, 18);
                        
        JLabel l1 = new JLabel("L");
        l1.setHorizontalAlignment(SwingConstants.CENTER);
        l1.setHorizontalAlignment(SwingConstants.CENTER);
        l1.setBorder(BorderFactory.createLineBorder(Color.black));
        l1.setBounds(10, 10, 100, 70);
        l1.setFont(fnt);
        
        JButton b1 = new JButton("B1");
        b1.setFont(fnt);
        b1.setBounds(120, 10, 100, 70);
        JButton b2 = new JButton("B2");
        b2.setFont(fnt);
        b2.setBounds(390, 10, 100, 70);
        JButton b3 = new JButton("B3"); 
        b3.setFont(fnt);
        b3.setBounds(390, 90, 100, 70);
                           
        f.add(l1);
        f.add(b1);  
        f.add(b2);
        f.add(b3);
        f.setVisible(true); 
        f.getContentPane().addHierarchyBoundsListener(
            new ResizeComponentsListener(500, 300, true));
        
    }   
}

Points of Interest

Note that resizing the font is optional which is passed as a boolean in the constructor. As the warning says this listener should be added after all the controls are created and added to the JFrame. Note also that the listener does not work for controls inside panels inside the JFrame.

I hope this will help. Any suggestions are welcomed.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Lebanon Lebanon
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --