Kaamil Jasani
Kaamil Jasani

Reputation: 464

BoxLayout giving unexpected width for custom component

I have a custom component that is extremely simple. It has a preferred and maximum size of 100x100 and is simply a red rectangle. I am adding this to a JPanel which is using a box layout. I would expect the size of the custom component to be 100x100, but instead, it is 50x100 (always half the maximum width).

Here is the code:

public class Testing extends JFrame {

    class TestComponent extends JComponent {

        @Override
        public Dimension getMaximumSize() {
            return new Dimension(100, 100);
        }

        @Override
        public Dimension getPreferredSize() {
            return new Dimension(100, 100);
        }

        @Override
        protected void paintComponent(Graphics g) {
            super.paintComponent(g);
            Graphics2D g2d = (Graphics2D) g.create();
            g2d.setPaint(Color.RED);
            g2d.fillRect(getX(), getY(), getWidth(), getHeight());
            System.out.println(getWidth());
        }

    }

    private JPanel panel;
    private TestComponent testComponent;

    public Testing() {
        super("Testing");
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setSize(1280, 720);
        setLocationRelativeTo(null);

        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        panel.setBackground(Color.CYAN);
        testComponent = new TestComponent();
        panel.add(testComponent);
        add(panel);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(()->{
            new Testing().setVisible(true);
        });
    }

}

This doesn't happen if instead of my custom component I add a JPanel with its preferred and maximum sizes set.

        panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));
        panel.setBackground(Color.CYAN);
        // testComponent = new TestComponent();
        // panel.add(testComponent);
        JPanel test = new JPanel();
        test.setPreferredSize(new Dimension(100,100));
        test.setMaximumSize(new Dimension(100,100));
        test.setBackground(Color.RED);
        panel.add(test);
        add(panel);

I am not sure what I am missing. Thanks!

Upvotes: 0

Views: 31

Answers (2)

camickr
camickr

Reputation: 324167

I have a custom component that is extremely simple.

A custom component is responsible for determining its:

  1. minimum size
  2. preferred size
  3. maximum size

You only implement the preferred and maximum sizes.

But it still doesn't make sense why the component isn't centered and is half the maximum width.

A BoxLayout attempts to respect the minimum and maximum sizes of the component.

The default minimum size is (0, 0), which appears to be causing confusion for the BoxLayout. I'm not sure why. I would say it is a bug/feature of the BoxLayout.

You need to implement the getMinimumSize() method. This seems to work:

@Override
public Dimension getMinimumSize() {
    return new Dimension(2, 2);
}

Note I tried (1, 1) which didn't work. Again, don't know why.

I would suggest that for your case you may want to use:

@Override
public Dimension getMinimumSize() {
    return getPreferredSize();
}

for both the minimum and maximum methods, since it appears you want the size to be constant.

Upvotes: 1

George Z.
George Z.

Reputation: 6808

Overriding methods getAnyKindOfSize() is not a good practice at general. Try to add the component inside a nested JPanel which uses FlowLayout, and then this JPanel to your BoxLayout-ed panel. Something like this:

testComponent = new TestComponent();
testComponent.setPreferredSize(new Dimension(100, 100));

JPanel flowPanel = new JPanel(new FlowLayout());
flowPanel.add(testComponent);
panel.add(flowPanel);

and:

class TestComponent extends JComponent {

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        Graphics2D g2d = (Graphics2D) g.create();
        g2d.setPaint(Color.RED);
        g2d.fillRect(0, 0, getWidth(), getHeight()); //Notice x, y
    }

}

Upvotes: 0

Related Questions