Safari
Safari

Reputation: 3382

how to make custom sized components in swing

I have 2 Components (which are both derived from jComponent). One is a Map and the other one are Territories within this map as you can see at the picture below.

Map with Territories

The Map is drawn on a fixed size of 1200x800 so far. And for each territorys I have a list of points, which will connected be a the shapes of each country.

Drawing everything working quite good so far. But when I click on a country always the last drawn territory gets called. It seems like every territory is an layer over the whole map. How can I make it work, that if I click on a single territory that only this gets clicked. So that if I click on China, the click event of china gets called?

Below is the Code of the 2 Components in case it helps:

Map.java

public class Map extends JComponent {

    private Collection<Territory> territories;
    public Map(Collection<Territory> territories) {
        super();
        this.territories = territories;
    }

    @Override
    public void paintComponent(Graphics graphics)
    {
        graphics.setColor(new Color(8, 114, 200));
        graphics.fillRect(0, 0, this.getWidth(), this.getHeight());

        for (Territory tmp : this.territories) {
            TerritoryComponent territoryComponent = new TerritoryComponent(tmp);
            this.add(territoryComponent);
        }
        this.updateUI();
    }

}

TerritoryComponent.java

public class TerritoryComponent extends JComponent implements MouseListener {

    private Territory territory;

    public TerritoryComponent(Territory tmp) {
        super();
        this.setSize(this.getMaximumSize());
        this.addMouseListener(this);
        this.territory = tmp;
    }

    @Override
    public void paintComponent(Graphics graphics)
    {
        for (Patch patch : this.territory.getPatches()) {
            ArrayList<Point> points = patch.getPoints();
            int x[] = new int[points.size() + 1];
            int y[] = new int[points.size() + 1];
            for (int i = 0; i < points.size(); i++) {
                x[i] = (int) points.get(i).getX();
                y[i] = (int) points.get(i).getY();
            }
            x[points.size()] = (int) points.get(0).getX();
            y[points.size()] = (int) points.get(0).getY();

            graphics.setColor(new Color(255, 255, 255));
            graphics.fillPolygon(x, y, points.size() + 1);

            graphics.setColor(new Color(52, 52, 52));
            graphics.drawPolyline(x, y, points.size() + 1);
        }

    }

    @Override
    public void mouseClicked(MouseEvent e) {
        System.out.println("clicked " + this.territory.getName());
    }

    @Override
    public void mousePressed(MouseEvent e) {

    }

    @Override
    public void mouseReleased(MouseEvent e) {

    }

    @Override
    public void mouseEntered(MouseEvent e) {

    }

    @Override
    public void mouseExited(MouseEvent e) {

    }
}

Upvotes: 0

Views: 47

Answers (1)

camickr
camickr

Reputation: 324088

And for each territorys I have a list of points,

  1. Create a Polygon Object to represent each of your territories.
  2. Add each Polygon to an ArrayList
  3. In the paintComponent() method you just iterate through the ArrayList to paint each Polygon

if I click on a single territory that only this gets clicked.

In the mouseClicked(...) event you then get the mouse point and your iterate through the ArrayList containing all your Polygons. You can then use the Polygon.contains(...) method to determine which territory you clicked on.

Also don't use the updateUI() method. The method should only be invoked when the LAF is changed. It should especially not be invoked in a painting method as this will cause the component to potentially repaint itself.

Upvotes: 4

Related Questions