javazoomingjmapviewer

JMapViewer: pan and zoom not set by when map has just loaded


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!


Solution

  • 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.