Reustonium
Reustonium

Reputation: 2645

Custom JComponent only Displays on JFrame not JPanel

Can somebody please help me understand why my custom JComponent 'Bar', only displays when added directly to the JFrame, and not when added to a JPanel (which is then added to the JFrame)?

Thanks!

package main;

import java.awt.BorderLayout;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;

public class Board {

    public void start(){
        JFrame frame = new JFrame();
        JButton button1 = new JButton("Button 1");
        Bar statusbar = new Bar();
        JLabel status = new JLabel("Status: ");

        JPanel topPanel = new JPanel();
        topPanel.add(status);
        topPanel.add(statusbar);

        JPanel mainPanel = new JPanel();
        mainPanel.add(button1);
        mainPanel.add(statusbar);

        frame.getContentPane().add(BorderLayout.NORTH, topPanel);
        frame.getContentPane().add(BorderLayout.SOUTH, mainPanel);
        frame.getContentPane().add(BorderLayout.CENTER, statusbar);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(200,100);
        frame.setVisible(true);
    }
}

Here is my Bar Class...

package main;

import java.awt.Graphics;

import javax.swing.JComponent;

public class Bar extends JComponent{
    public void paint(Graphics g){
        g.fillRect(0, 0, 100, 10);
    }
}

Upvotes: 2

Views: 2181

Answers (2)

mre
mre

Reputation: 44250

The dimension of the custom component is (0, 0).

When added to a container with a BorderLayout layout manager, it will expand to fill the available space, and therefore become visible.

When added to a container with a FlowLayout layout manager, it will not expand and will instead remain at its preferred size (i.e. (0, 0)). And therefore, will not become visible, albeit it is still there.

This explains why the custom component is only displayed when added directly to the JFrame, since it uses a BorderLayout layout manager, whereas a JPanel uses a FlowLayout layout manager.

Upvotes: 3

Dmitri
Dmitri

Reputation: 9157

You're adding statusbar to several different places in the component tree, Swing doesn't deal with that well (or at all).

Create a separate Bar instances each time you use it, if you want their display to be synchronized, they should share the same model.

Edit

Ah, on a second glance, the problem here is that you never set a size (or preferred size) for the Bar components, so they get squished to 0 by the layout manager.

Try:

public static class Bar extends JComponent {

    private Bar() {
        setPreferredSize(new Dimension(25, 5));
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.fillRect(0, 0, 100, 10);
    }
}

You should also add a frame.pack() before display.

(the multiple references to the same component thing is still true, too)

Upvotes: 3

Related Questions