2

I have two custom images as markers on JMapViewer. I would like the map to set proper pan and zoom so that the two markers are visible on the map display. I have a button that does it. So, what is happening is that the map is not zoomed to these markers when it is loading; but when I click on the button, it does. Is there a way to set the proper pan and zoom at loading?

public class PanelAcars extends javax.swing.JPanel implements JMapViewerEventListener  
{
    private final JMapViewerTree treeMap;

    public PanelAcars() 
    {
        super();
        initComponents(); // GUI components

        treeMap = new JMapViewerTree("Zones");

        // Listen to the map viewer for user operations so components will
        // receive events and update
        map().addJMVListener(this);

        setLayout(new BorderLayout());

        pnlAcarsMapView = new JPanel(new BorderLayout());
        JPanel panelTop = new JPanel();
        JPanel panelBottom = new JPanel();
        JPanel helpPanel = new JPanel();

        add(pnlAcarsMapView, BorderLayout.NORTH);
        add(helpPanel, BorderLayout.SOUTH);
        pnlAcarsMapView.add(panelTop, BorderLayout.NORTH);
        pnlAcarsMapView.add(panelBottom, BorderLayout.SOUTH);

        /* THIS BUTTON WORKS!!! */
        JButton button = new JButton("Zoom...");
        button.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                map().setDisplayToFitMapMarkers();
            }
        });


        final JCheckBox showZoomControls = new JCheckBox("Show zoom controls");
        showZoomControls.setSelected(map().getZoomControlsVisible());
        showZoomControls.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                map().setZoomContolsVisible(showZoomControls.isSelected());
            }
        });
        panelBottom.add(showZoomControls);
        final JCheckBox scrollWrapEnabled = new JCheckBox("Scrollwrap enabled");
        scrollWrapEnabled.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                map().setScrollWrapEnabled(scrollWrapEnabled.isSelected());
            }
        });
        panelBottom.add(scrollWrapEnabled);
        panelBottom.add(button);

        add(treeMap, BorderLayout.CENTER);

        /* Add Airports to the map */
        LayerGroup mapGroupAirports = new LayerGroup("MapAirports");
        Layer mapLayerDep = mapGroupAirports.addLayer("MapDep");
        Layer mapLayerDest = mapGroupAirports.addLayer("MapDest");
        Layer mapLayerAlt = mapGroupAirports.addLayer("MapAlt");


        /* Add Plane to the map */
        Layer mapLayerPlane = new Layer("MapPlane");

        /* Set coordinates */
        Coordinate coordinatesPlane = new Coordinate(49.814284999, 98.642065999);
        Coordinate coordinatesDep = new Coordinate(23.814284999, 45.642065999);

        JMapViewerMarkerCustomImage markerPlane;
        JMapViewerMarkerCustomImage markerDep;

        Image imageMarkerPlane;
        Image imageMarkerDep;

        try 
        {
            imageMarkerPlane = ImageIO.read(this.getClass().getResource("/images/image1.png"));
            markerPlane = new JMapViewerMarkerCustomImage(coordinatesPlane,imageMarkerPlane);
            map().addMapMarker(markerPlane);

            imageMarkerDep = ImageIO.read(this.getClass().getResource("/images/image2.png"));
            markerDep = new JMapViewerMarkerCustomImage(coordinatesDep,imageMarkerDep);
            map().addMapMarker(markerDep);

            // AND THIS IS NOT WORKING AT LOADING!!!
            map().setDisplayToFitMapElements(true, true, true);

        } catch (IOException ex) {
            ex.printStackTrace();
        }


        map().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (e.getButton() == MouseEvent.BUTTON1) {
                    map().getAttribution().handleAttribution(e.getPoint(), true);
                }
            }
        });

        map().addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                Point p = e.getPoint();
                boolean cursorHand = map().getAttribution().handleAttributionCursor(p);
                if (cursorHand) {
                    map().setCursor(new Cursor(Cursor.HAND_CURSOR));
                } else {
                    map().setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
                }
                //if (showToolTip.isSelected()) map().setToolTipText(map().getPosition(p).toString());
            }
        });

    }

Thanks a lot!

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Igor Tupitsyn
  • 1,193
  • 3
  • 18
  • 45

1 Answers1

2

Invoke setDisplayToFitMapMarkers() in your map's implementation of tileLoadingFinished(). Using the boolean variable loaded, which is false by default, the implementation below invokes the method after the first tile loads; the parent implementation will repaint() any subsequent tiles.

private boolean loaded;

private class MyViewer extends JMapViewer {

    @Override
    public void tileLoadingFinished(Tile tile, boolean success) {
        super.tileLoadingFinished(tile, success);
        if (!loaded & success) {
            loaded = true;
            setDisplayToFitMapMarkers();
        }
    }
    …
}

To get a similar result using JMapViewerTree, you'll need to alter the map that is instantiated in the JMapViewerTree constructor. The following changes work with Demo.java:

…
private boolean loaded;
…
public JMapViewerTree(String name, boolean treeVisible) {
    …
    map = new JMapViewer() {
        @Override
        public void tileLoadingFinished(Tile tile, boolean success) {
            super.tileLoadingFinished(tile, success);
            if (!loaded & success) {
                loaded = true;
                setDisplayToFitMapMarkers();
            }
        }
    };
    …
}

As an aside, instead of MouseAdapter, consider extending or replacing the DefaultMapController, as suggested here.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • trashgod. Thanks a lot! It works now. Regarding your second comment, I got a bit confused. I tried to extend `DefaultMapController` instead of `"extends JMapViewer"`, as you suggested. As a result, code gets broken as it cannot find now `super()`, `setLayout`, `add()`, etc. Without it, in method `new DefaultMapController(map)`, map is not found. Thank you! – Igor Tupitsyn Aug 15 '16 at 22:59
  • trashgod. May I ask one more question? To implement `tileLoadingFinished()`, I had to extend the class to JMapViewer instead of Panel. As a result, now I see **two** zoom controls on the map, one being behind the other one. Looks like the second zoom controller is added with this: `add(treeMap, BorderLayout.CENTER)`. However, if I delete this line, my custom markers are not seen anymore. Do you know how I can remove the second zoom control retaining `tileLoadingFinished()`? Thanks a lot! – Igor Tupitsyn Aug 16 '16 at 00:13
  • 1
    It looks like you can let `JMapViewerTree` implement `TileLoaderListener` and invoke `setDisplayToFitMapMarkers()` on the `JMapViewer` returned by `getViewer()`. – trashgod Aug 16 '16 at 01:24
  • trashgod, trying to figure out how to operationalize what you suggested. Moving `setDisplayToFitMarkers()` to `private JMapViewer map(){return tree map.getViewer();}` does not work. – Igor Tupitsyn Aug 16 '16 at 02:05
  • 1
    I see what you mean; I've outlined a change to `JMapViewerTree` above. – trashgod Aug 16 '16 at 06:26
  • Brilliant! Thank you so much for your help! – Igor Tupitsyn Aug 16 '16 at 11:58