Question

I have a custom JPanel, which the paintComponent method is overridden to paint an image.

I want to insert several of these custom panels vertically centered in a container. To do this I created a jpanel with BoxLayout.X_AXIS as layout manager.

representation

This works great and shows what I want, but I would like to add margins between the custom panels.

The EmptyMargins are just ignored, and the tricky part is that I can't (or would not like to...) add struts or boxes between them because I need to get each custom panel from a loop which takes all components of the container and cast them into CustomPanel.

See the problem ? If I add struts between the panels there will be a cast exception and EmptyBorders aren't working... Any ideas welcome!

Note : I'm open to other layout manager propositions ! ;-)

Here is the code :

public class StackExemple {

public StackExemple() {

    JFrame frame = new JFrame();
    frame.setPreferredSize(new Dimension(600, 300));

    JPanel container = new JPanel();
    container.setPreferredSize(new Dimension(600, 300));
    container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));

    CustomPanel customPanel1 = new CustomPanel();
    CustomPanel customPanel2 = new CustomPanel();
    CustomPanel customPanel3 = new CustomPanel();

    container.add(customPanel1);
    container.add(customPanel2);
    container.add(customPanel3);

    frame.getContentPane().add(container);
    frame.pack();
    frame.setVisible(true);

    //Loop which takes the custompanels
    for(Component comp : container.getComponents()) {
        CustomPanel panel = (CustomPanel)comp;
        //DO SOMETHING

        System.out.println("Hello World");
    }
}

private class CustomPanel extends JPanel{

    private BufferedImage image;

    public CustomPanel() {
        setPreferredSize(new Dimension(100, 100));
        setMinimumSize(getPreferredSize());
        setMaximumSize(getPreferredSize());
        setBorder(BorderFactory.createEmptyBorder(0,50,0,0));
        setBackground(Color.RED);

//      try {
//          image = ImageIO.read(ClassLoader.getSystemClassLoader().getResource("Ressources/img.png"));
//      } catch (IOException ex) {
//           System.out.println("Ooops... ");
//      }
    }

    @Override
    protected void paintComponent(Graphics g)
    {
        super.paintComponent(g);
//      int x = (this.getWidth() - image.getWidth()) / 2;
//      int y = (this.getHeight() - image.getHeight()) / 2;
//      g.drawImage(image, x, y, null);
    }
}
}
Was it helpful?

Solution

enter image description here

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.image.BufferedImage;
import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class StackExemple {

    public StackExemple() {
        JFrame frame = new JFrame();
        JPanel container = new JPanel();
        container.setLayout(new BoxLayout(container, BoxLayout.X_AXIS));
        CustomPanel customPanel1 = new CustomPanel(Color.blue);
        CustomPanel customPanel2 = new CustomPanel(Color.red);
        CustomPanel customPanel3 = new CustomPanel(Color.green);
        container.add(customPanel1);
        container.add(customPanel2);
        container.add(customPanel3);
        frame.getContentPane().add(container);
        frame.pack();
        frame.setVisible(true);
        for (Component comp : container.getComponents()) {
            CustomPanel panel = (CustomPanel) comp;
            System.out.println("Hello World");
        }
    }

    private class CustomPanel extends JPanel {

        private BufferedImage image;

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

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

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

        public CustomPanel(Color c) {
            setBorder(BorderFactory.createCompoundBorder(
                    BorderFactory.createEmptyBorder(10, 10, 10, 10), 
                    BorderFactory.createLineBorder(Color.black, 1)));
            //setBorder(BorderFactory.createCompoundBorder(
            //BorderFactory.createLineBorder(Color.black, 1), 
            //BorderFactory.createEmptyBorder(10, 10, 10, 10)));
            setBackground(c);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                StackExemple stackExemple = new StackExemple();
            }
        });
    }
}

OTHER TIPS

The underlying reason that the border appears to not be respected is that the panel by default is opaque, that is it guarantees to fill each pixel of its area with a fully solid background color. The area covered by the border is part of the panel's area, so must be filled with the panel's background as well.

As you seem to be doing custom painting anyway, you might consider to report its opaqueness as false and only paint the background (and/or the background image) inside the bordered area:

// in constructor
setOpaque(false);

@Override
protected void paintComponent(Graphics g) {
    // take over background filling inside the border
    Insets insets = getInsets();
    g.setColor(getBackground());
    g.fillRect(insets.left, insets.top, 
            getWidth() - insets.left - insets.right, 
            getHeight() - insets.top - insets.bottom);

    super.paintComponent(g);
    // for a background image, you would need to take the insets
    // into account as well 
    // int x = (this.getWidth() - image.getWidth()) / 2;
    // int y = (this.getHeight() - image.getHeight()) / 2;
    // g.drawImage(image, x, y, null);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top