1

I have a Swing app with a glass pane over a map.

It paints dots at certain positions. When I click somewhere on the map, and the glass pane receives the message CONTROLLER_NEW_POLYGON_MARK I want do display an additional dot at the position specified in the event data (see MyGlassPane.propertyChange).

The glass pane class is called MyGlassPane. Using the debugger I validated that addPointToMark is actually called in propertyChange.

But no additional dots appear on the screen.

How can I change the code so that PointSetMarkingGlassPane.paintComponent is called whenever an event (IEventBus.CONTROLLER_NEW_POLYGON_MARK) is fired?

public class PointSetMarkingGlassPane extends JComponent implements IGlassPane {
    private final ILatLongToScreenCoordinatesConverter latLongToScreenCoordinatesConverter;
    private final List<Point.Double> pointsToMark = new LinkedList<Point.Double>();

    public PointSetMarkingGlassPane(final ILatLongToScreenCoordinatesConverter aConverter) {
        this.latLongToScreenCoordinatesConverter = aConverter;
    }

    protected void addPointToMark(final Point.Double aPoint)
    {
        if (aPoint != null)
        {
            pointsToMark.add(aPoint);
        }
    }

    @Override
    protected void paintComponent(final Graphics aGraphics) {
        for (final Point.Double pointToMark : pointsToMark)
        {
            final Point positionInScreenCoords = latLongToScreenCoordinatesConverter.getScreenCoordinates(pointToMark);
            drawCircle(aGraphics, positionInScreenCoords, Color.red);
        }
    }

    private void drawCircle(Graphics g, Point point, Color color) {
        g.setColor(color);
        g.fillOval(point.x, point.y, 10, 10);
    }

}

public class MyGlassPane extends PointSetMarkingGlassPane implements PropertyChangeListener {
    public MyGlassPane(ILatLongToScreenCoordinatesConverter aConverter) {
        super(aConverter);

        addPointToMark(DemoGlassPane.ARTYOM);
    }

    @Override
    public void propertyChange(PropertyChangeEvent evt) {
        if (IEventBus.CONTROLLER_NEW_POLYGON_MARK.equals(evt.getPropertyName()))
        {
            addPointToMark((Point.Double)evt.getNewValue());
            invalidate();
        }
    }
}
Glory to Russia
  • 17,289
  • 56
  • 182
  • 325
  • if is work in JFrame the isn't reason why not in the case when is placed in GlassPane or JViewport, be sure that without an SSCCE is everything here about guessing – mKorbel Oct 14 '13 at 12:43

2 Answers2

1

As I think invalidate() only flags your component to check sizes and layout. You should call repaint() to repaint your pane.

Also I am wondering why you use propertyChangeListener for mouse clicks. I would prefer just simple mouse listener + MouseAdapter and MouseEvent x, y, buttons state.

Piotr Müller
  • 5,323
  • 5
  • 55
  • 82
  • @mKorbel No, you should not call `super.paintComponent()` explicitly. painting component should take place in event thread, because swing is not thread safe. – Piotr Müller Oct 14 '13 at 12:53
  • alone repaint() only commulating painting without super.paintComponent() – mKorbel Oct 14 '13 at 12:56
  • @mKorbel can you extend that comment? what you mean by 'commulating painitng'? and `without super.paintComponent()`? – Piotr Müller Oct 14 '13 at 13:00
  • super.paintComponent() remove all previous painting, for more info to see posts tagged by java + swing + paintComponent (here), especially posts by camickr, HFOE, MadProgrammer, but there is another issue in OPs code (AFAIK) because PropertyChangeListener will notify interal methods implemented in APIs, then there is 2nd. point that isn't neccessary to call for repaint(), but nobody knows without an SSCCE, endless song, blood_song that we are singing here :-) – mKorbel Oct 14 '13 at 13:06
  • @mKorbel I still think that you are not right. Of course, @Dmitri Pisarenko should add `super.paintComponent(aGraphics)` due to Swing programming practices, **but in `paintComponent` method and not where `invalidate();` currently is**. Adding `super.paintComponent()` doesn't help to resolve this question issue. – Piotr Müller Oct 14 '13 at 13:18
0

invalidate() probably won't help you, as it flags a component for layout changes, not painting changes. Why not call repaint() instead?

For better performance, you could call the repaint method which takes a Rectangle (or four ints representing a rectangle), so that only the newly added point is repainted; I would suggest changing the return type of addPointToMark from void to java.awt.Point, and have it return the result of latLongToScreenCoordinatesConverter.getScreenCoordinates, so MyGlassPane can derive a rectangle from that Point which can then be passed to a repaint method.

VGR
  • 40,506
  • 4
  • 48
  • 63
  • 1
    or super.paintComponent() – mKorbel Oct 14 '13 at 12:50
  • As I understand it, super.paintComponent is only required of subclasses of components with UI delegates, and is not strictly required of direct subclasses of JComponent. I've never actually put that to the test, though. – VGR Oct 14 '13 at 12:54
  • alone repaint() only commulating painting without super.paintComponent(), – mKorbel Oct 14 '13 at 12:56