Search code examples
javaswinglayout-managerflowlayout

Custom JComponent does not work with flow layout


I created a class extending JComponent and want to use it on a JPanel. If I set its bounds, I can not use it in FlowLayout the way I want; it appears on JPanel as if it was using absolute positioning. If I don't specify the bounds, it does not appear at all. What could be the solution?

Thanks.

JMotor.java:

public class JMotor extends JComponent {

    public void paint(Graphics g) {

        Graphics2D g2 = (Graphics2D) g;
        BufferedImage img = null;

        try {
            img = ImageIO.read(new File("motor.jpg"));
        } 

        catch (Exception e) {

        }

        g2.drawImage(img, 5, 5, this);
        //setBounds(5, 5, 100, 50);
    }
}

Scada.java:

public class Scada {

    JFrame scadaFrame;
    JPanel scadaPanel;

    Scada () {

        scadaFrame = new JFrame("Scada");
        scadaFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        scadaPanel = new JPanel();          

        scadaPanel.add(new JSuruculuMotor());
        scadaPanel.add(new JMotor());

        scadaFrame.setContentPane(scadaPanel);
        scadaFrame.setSize(600,300);    
        scadaFrame.setVisible(true);
    }

    public static void main(String[] args) {

        new Scada();

    }
}

Solution

  • The reason it doesn't work is because FlowLayout respects the preferred size of the component and you have not specified the preferred size of your custom component.

    You need to override the getPreferredSize() method of your class to return its size to the layout managers can do their job.

    Custom painting is done by overriding the paintComponent() method. Also, don't do I/O in a painting method. The image should be read in the constructor of the class.

    However, the question is why are you creating a custom component? Just use a JLabel with an ImageIcon.

    If you want the image to appear 5 pixels from the top/left then you add a Border to the label:

    label.setBorder( new EmptyBorder(5, 5, 5, 5) );