Search code examples
javajframejcomponent

Java - JComponent in polygon shape with background image


I want to have a JComponent on my JFrame, that has a custom shape in form of a polygon. Now i want to add a background image with colors in the same shape and blank color in the rest.

Is there a way to achieve this?

I have this test class:

public class Test extends JButton {
private final Polygon shape;
private final int provinceId;
private ImageIcon img;

public Test(Polygon p, int x, int y, int w, int h, int id, ImageIcon img) {
    this.shape = p;
    this.provinceId = id;
    this.img = img;
    setSize(w, h);
    setLocation(x, y);
    setIcon(img);
    setContentAreaFilled(false);
    addMouseListener(animation());
}

private MouseListener animation() {
    return new MouseListener() {
        public void mouseEntered(MouseEvent e) {
            System.out.println("in");
        }

        public void mouseExited(MouseEvent e) {
            System.out.println("out");
        }

        public void mouseClicked(MouseEvent e) {

        }

        public void mousePressed(MouseEvent e) {

        }

        public void mouseReleased(MouseEvent e) {

        }
    };
}

protected void paintComponent(Graphics g) {
    g.drawPolygon(this.shape);
}

protected void paintBorder(Graphics g) {
    g.drawPolygon(this.shape);
}

public boolean contains(int x, int y) {
    return this.shape.contains(x, y);
}

public boolean isOpaque() {
    return false;
}

public int getId() {
    return this.provinceId;
}

public static void main(String[] args) {
    JFrame f = new JFrame();
    //Polygon p = new Polygon(new int[] {0, 400, 400, 0}, new int[] {0, 0, 300, 300}, 4);
    Polygon p = new Polygon(new int[] {50, 150, 250, 350, 200, 50}, new int[] {0, 0, 50, 200, 300, 200}, 6);
    ImageIcon ico = new ImageIcon("gfx/test.png");
    Test t = new Test(p, 20, 20, 400, 300, 101, ico);
    f.getContentPane().add(t);
    f.setSize(500, 400);
    f.setLayout(null);
    f.setVisible(true);
}

}

but i only get this output: output

My original picture was: wanted output


Solution

  • You can do so by overriding the contains(Point p) method to only return true when p is in the bounds of your custom shape.

    Then you best override isOpaque() to return false.

    And finally you override paintComponent(Graphics g) to paint your component in whatever way you like (e.g. a background image with colors in the shape and blank color in the rest).

    Sample code:

    JPanel panel = new JPanel()
    {
        @Override
        public boolean isOpaque()
        {
            return false;
        }
    
        @Override
        public boolean contains(Point p)
        {
            // Use something that fits your shape here.
            return p.getX() % 2 == 0;
        }
    
        @Override
        public void paintComponent(Graphics g)
        {
            // do some painting
        }
    };