Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Making a JPanel square

Tags:

java

swing

jpanel

If I have a JPanel with multiple subcomponents, how would I make it so that JPanel remains a square despite how its parent is resized? I have tried variations on the following code, but it does not result in the subcomponents also being square.

public void paint(Graphics g){
    if(this.isSquare()){
        Dimension d = this.getSize();
        if(d.height > d.width){
            this.setSize(d.width, d.width);
        } else {
            this.setSize(d.height, d.height);
    }
    super.paint(g);
}

Here is an SSCCE.

The containing parent:

import javax.swing.JFrame;

public class TestFrame extends JFrame{

    public TestFrame(){
        this.add(new TestPanel());
    }

    public static void main(String[] args){
        TestFrame tf = new TestFrame();

        tf.setSize(500, 500);
        tf.setVisible(true);
    }
}

What should be a square JPanel:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.border.LineBorder;


public class TestPanel extends JPanel{
    private boolean isSquare;

    public TestPanel(){
        this.setSquare(true);
        this.setLayout(new BorderLayout());

        JLabel panel1 = new JLabel();
        panel1.setBorder(new LineBorder(Color.RED, 4));
        panel1.setBackground(Color.CYAN);

        JLabel panel2 = new JLabel();
        panel2.setBorder(new LineBorder(Color.BLUE, 4));
        panel2.setBackground(Color.CYAN);


        this.setBorder(new LineBorder(Color.GREEN, 4));
        this.setBackground(Color.CYAN);

        this.add(panel1, BorderLayout.WEST);
        this.add(panel2, BorderLayout.EAST);
    }

    public void paint(Graphics g){
        if(this.isSquare()){
            Dimension d = this.getSize();
            if(d.height > d.width){
                this.setSize(d.width, d.width);
            } else {
                this.setSize(d.height, d.height);
            }
            super.paint(g);
        }
    }

    private boolean isSquare() {
        return isSquare;
    }

    private void setSquare(boolean isSquare) {
        this.isSquare = isSquare;
    }
}
like image 282
MirroredFate Avatar asked Dec 15 '22 11:12

MirroredFate


1 Answers

import java.awt.*;
import javax.swing.*;
import javax.swing.border.EmptyBorder;

public class SoSquare {

    public static void main(String[] args) {
        Runnable r = new Runnable() {

            @Override
            public void run() {
                // the GUI as seen by the user (without frame)
                // A single component added to a GBL with no constraint
                // will be centered.
                JPanel gui = new JPanel(new GridBagLayout());

                gui.setBackground(Color.WHITE);

                SquarePanel p = new SquarePanel();
                p.setBackground(Color.red);
                gui.add(p);

                JFrame f = new JFrame("Demo");
                f.add(gui);
                // Ensures JVM closes after frame(s) closed and
                // all non-daemon threads are finished
                f.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
                // See http://stackoverflow.com/a/7143398/418556 for demo.
                f.setLocationByPlatform(true);

                // ensures the frame is the minimum size it needs to be
                // in order display the components within it
                f.pack();
                f.setSize(400,100);
                // should be done last, to avoid flickering, moving,
                // resizing artifacts.
                f.setVisible(true);
            }
        };
        // Swing GUIs should be created and updated on the EDT
        // http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html
        SwingUtilities.invokeLater(r);
    }
}

/**
 * A square panel for rendering. NOTE: To work correctly, this must be the only
 * component in a parent with a layout that allows the child to decide the size.
 */
class SquarePanel extends JPanel {

    @Override
    public Dimension getPreferredSize() {
        Dimension d = super.getPreferredSize();
        Container c = getParent();
        if (c != null) {
            d = c.getSize();
        } else {
            return new Dimension(10, 10);
        }
        int w = (int) d.getWidth();
        int h = (int) d.getHeight();
        int s = (w < h ? w : h);
        return new Dimension(s, s);
    }
}
like image 144
Andrew Thompson Avatar answered Dec 30 '22 18:12

Andrew Thompson