Показывать всплывающую подсказку на картах Gluon при нажатии MapPoint

Можно ли показать popup window при выполнении onclick() в точке карты и что при правильном изменении положения масштабирования у кого-то получилось? Используемая библиотека — gluon maps.

Я хочу показать всплывающую подсказку, когда я нажимаю на точку карты, и когда я меняю масштаб, точка карты перемещается в правильное положение, в примере она не позиционируется при масштабировании.

MapPoint point = candidate.getKey();
Node icon = candidate.getValue();
Point2D mapPoint = baseMap.getMapPoint(point.getLatitude(), point.getLongitude());
icon.setVisible(true);
icon.setTranslateX(mapPoint.getX());
icon.setTranslateY(mapPoint.getY());
final Tooltip tp=new Tooltip();
icon.setOnMouseClicked(new EventHandler<MouseEvent>() {
     @Override
     public void handle(MouseEvent t) {
         tp.setText("Pruebas");
         com.sun.glass.ui.Robot robot = com.sun.glass.ui.Application
                    .GetApplication().createRobot();
         tp.show(icon, robot.getMouseX() + 10,
                    robot.getMouseY() + 10);
        }
    });
    icon.setOnMouseExited(new EventHandler<MouseEvent>() {
         @Override
         public void handle(MouseEvent t) {

            //tp.hide();
        }
    });

Было бы целесообразно изменить всплывающую подсказку положения, например точку, где точка положения изменяется при масштабировании? Кто-то пробовал?


person Marian López    schedule 13.12.2017    source источник
comment
Пожалуйста объясните подробнее..   -  person Apurva Kolapkar    schedule 13.12.2017
comment
Я расширил пример, чтобы показать, что я хочу сделать. Спасибо.   -  person Marian López    schedule 13.12.2017
comment
Было бы целесообразно изменить всплывающую подсказку положения, например точку, где точка положения изменяется при масштабировании? Кто-то пробовал?   -  person Marian López    schedule 13.12.2017


Ответы (1)


Поскольку вы имеете в виду класс PoiLayer в демоверсии Gluon Map пакет, вы можете легко изменить его на:

  • обновите положение значка соответствующим образом, когда вы нажимаете на одно место на карте, не требуя обновления масштаба.

  • показать всплывающую подсказку на вашем значке.

Просто добавьте этот метод в PoiLayer, чтобы обновить данную точку до новых координат lat и lon:

public void updatePoint(MapPoint p, double lat, double lon) {
    for (Pair<MapPoint, Node> candidate : points) {
        MapPoint point = candidate.getKey();
        if (point.equals(p)) {
            p.update(lat, lon);
            markDirty();
            break;
        }
    }
}

Обратите внимание на вызов markDirty(), который заставит пройти макет и обновит положение значка.

Если вы добавите Tooltip к значку, вам не нужно будет заботиться об обновлении его положения:

private MapPoint mapPointIcon;

private PoiLayer createDemoLayer() {
    PoiLayer answer = new PoiLayer();
    Node icon = new Circle(7, Color.BLUE);
    Tooltip.install(icon, new Tooltip("Pruebas"));
    mapPointIcon = new MapPoint(40.4, -3.7);
    answer.addPoint(mapPointIcon, icon);

    return answer;
}

Единственная недостающая часть — это получение координат широты и долготы со сцены. Это вопрос охватывает это.

Итак, на его основе вы можете добавить этот метод в класс PoiLayer:

public MapPoint getMapPosition(double x, double y) {
    double z = baseMap.zoom().get();
    double latrad = Math.PI - (2 * Math.PI * (y - baseMap.getTranslateY())) / (Math.pow(2, z) * 256.0);
    double mlat = Math.toDegrees(Math.atan(Math.sinh(latrad)));
    double mlon = (x - this.baseMap.getTranslateX()) / (256.0 * Math.pow(2, z)) * 360.0 - 180.0;
    return new MapPoint(mlat, mlon);
}

Наконец, добавьте слушателя к вашему представлению:

@Override
public void start(Stage stage) throws Exception {
    MapView view = new MapView();
    PoiLayer myDemoLayer = createDemoLayer();
    view.setZoom(4); 
    view.addLayer(myDemoLayer);
    Scene scene = new Scene(view, 600, 700);
    stage.setScene(scene);
    stage.show();

    view.flyTo(0, mapPointIcon, 1.);

    view.setOnMouseClicked(e -> {
        MapPoint position = myDemoLayer.getMapPosition(e.getX(), e.getY());
        myDemoLayer.updatePoint(mapPointIcon, position.getLatitude(), position.getLongitude());
    });
}

Это прекрасно работает, но если у вас есть слой с несколькими точками, вам понадобится способ выбрать, какую точку вы хотите переместить.

ИЗМЕНИТЬ

Основываясь на запросе OP на наличие постоянного всплывающего окна вместо всплывающей подсказки, это очень простая реализация всплывающего окна. Для лучшего решения, ControlsFX рекомендуется PopOver элемент управления.

Это можно добавить в класс PoiLayer:

public void addPoint(MapPoint p, Node icon) {
    final Pair<MapPoint, Node>  pair = new Pair(p, icon);
    icon.setOnMouseClicked(e -> {
        e.consume();
        showPopup(pair);
    });
    points.add(pair);
    this.getChildren().add(icon);
    this.markDirty();
}

private void showPopup(Pair<MapPoint, Node>  pair) {
    Node icon = pair.getValue();
    MapPoint point = pair.getKey();
    final Stage primaryStage = (Stage) icon.getScene().getWindow();
    final Stage popupStage = new Stage();
    popupStage.initStyle(StageStyle.UNDECORATED);
    popupStage.initModality(Modality.APPLICATION_MODAL);
    popupStage.initOwner(primaryStage);

    VBox box = new VBox(5);
    box.setPadding(new Insets(5));
    box.getChildren().addAll(new Label("Popup"),
            new Label("Lat: " + String.format("%2.6fº", point.getLatitude())),
            new Label("Lon: " + String.format("%2.6fº", point.getLongitude())));
    Label close = new Label("X");
    close.setOnMouseClicked(a -> popupStage.close());

    StackPane.setAlignment(close, Pos.TOP_RIGHT);
    final StackPane stackPane = new StackPane(box, close);
    stackPane.setPadding(new Insets(5));
    stackPane.setStyle("-fx-background-color: lightgreen;");

    Scene scene = new Scene(stackPane, 150, 100);
    Bounds iconBounds = icon.localToScene(icon.getBoundsInLocal());
    popupStage.setX(primaryStage.getX() + primaryStage.getScene().getX() + iconBounds.getMaxX() );
    popupStage.setY(primaryStage.getY() + primaryStage.getScene().getY() + iconBounds.getMaxY());
    popupStage.setScene(scene);
    popupStage.show();
}

Всякий раз, когда вы нажимаете на значок, появляется модальное всплывающее окно (вам нужно закрыть его, прежде чем вернуться к карте). Это, конечно, можно изменить, чтобы иметь немодальное и автоматически закрывающееся всплывающее окно.

Пользовательское всплывающее окно

person José Pereda    schedule 13.12.2017
comment
Большое спасибо. Этот код перемещает точку карты положения, но всплывающая подсказка не перемещается рядом с точкой при увеличении карты. - person Marian López; 13.12.2017
comment
Я неправильно объяснил, извините. Я хочу, чтобы окно, подобное карте Google, с информацией появлялось, когда я нажимаю точку на карте. Всплывающая подсказка появляется при наведении указателя мыши после слишком долгого наведения указателя мыши. - person Marian López; 13.12.2017
comment
Итак, вы имеете в виду всплывающее окно, а не всплывающую подсказку :) - person José Pereda; 13.12.2017
comment
Вы пробовали использовать всплывающее окно? Как вы думаете, возможно ли реализовать всплывающее окно? Большое спасибо за Вашу помощь! - person Marian López; 13.12.2017
comment
Да, это легко сделать, сейчас выложу. Если вам нужен действительно хороший элемент управления всплывающими окнами, вам нужно использовать ControlsFX, который также имеет открытый исходный код (но вы добавите большую зависимость в свое мобильное приложение). - person José Pereda; 13.12.2017
comment
Я использовал библиотеку ControlFX для лидера в настольном приложении. Это довольно полезная библиотека. На данный момент я не буду его использовать. Большое спасибо! - person Marian López; 13.12.2017
comment
Я отредактировал свой ответ с очень простой реализацией всплывающего окна. - person José Pereda; 13.12.2017