Рисование точек на MapLayer с использованием GluonHQ Maps с JavaFX не работает - PullRequest
0 голосов
/ 17 мая 2019

Я использую GluonHQ Maps 1.0.3 в JavaFX, и у меня проблема с рисованием узлов на карте.

У меня есть класс GridMapController, в котором MapView называется gridMap. У меня также есть класс GridPaintLayer, который расширяет MapLayer и где все картины сделаны. GridPaintLayer добавляется к GridMapController gridMap методом gridMap.addLayer(gridPaintLayer). Этот класс (GridPaintLayer) имеет метод addNode(NodeInputModel), которому я передаю узел (который содержит значения широты / долготы), который должен быть нарисован. Упомянутый gridMap (MapView) можно щелкнуть правой кнопкой мыши, откроется всплывающее меню, в котором я могу выбрать «Создать узел». Это вызывает метод createNodeItemClicked(), который реализован в GridPaintLayer (см. Ниже). Когда я щелкаю пункт меню «Создать узел», все работает нормально, и на карте появляется точка.

В другой части программы у меня есть наблюдаемый объект, который уведомляет своих наблюдателей при каждом добавлении узла. Уведомление обрабатывается в GridMapController, который затем вызывает метод addNode() из GridPaintLayer. Но теперь, когда я хочу, чтобы GridPaintLayer's baseMap вычислял положение точек на сцене, метод baseMap.getMapPoint(double lat, double lon) возвращает null, потому что сцена baseMap имеет значение null. Таким образом, узел не может быть нарисован. Это происходит, когда я хочу создать узел в другой части приложения. Наблюдаемое уведомляет GridMapController (среди прочих) правильно, но тогда проблема появляется, как описано выше.

Оба метода реализованы в классе GridPaintLayer.

public void addNode(NodeInputModel nodeInputModel) {
    Circle circle = new Circle(7, Color.RED);
    circle.setCursor(Cursor.HAND);
    circle.setVisible(true);

    paintedNodes.put(nodeInputModel, circle);

    Point2D mapPoint = baseMap.getMapPoint(nodeInputModel.getLat(), nodeInputModel.getLon());
    if(mapPoint != null) {
        circle.setTranslateX(mapPoint.getX());
        circle.setTranslateY(mapPoint.getY());
    } else {
        System.out.println("Could not calculate node position, baseMap scene = null: " + (baseMap.getScene() == null));
    }

    AtomicReference<Double> orgSceneX = new AtomicReference<>(0d);
    AtomicReference<Double> orgSceneY = new AtomicReference<>(0d);

    circle.setOnMousePressed(mousePressedEvent -> {...});

    circle.setonMouseClicked(mouseEvent -> {...});

    this.getChildren().add(circle);
    this.markDirty();
}

public void createNodeItemClicked(MouseEvent mouseEvent) {
    // Convert mouseEvent position to geo position
    MapPoint mapPoint = baseMap.getMapPosition(mouseEvent.getX(), mouseEvent.getY());
    LatLon latLon = new LatLon(mapPoint.getLatitude(), mapPoint.getLongitude());
    Point geoPosition = Utils.latlonToPoint(latLon);

    // Create NodeInputModel
    NodeInputModel nodeInputModel = new NodeInputModel();
    nodeInputModel.setGeoPosition(geoPosition);
    // TODO: set the other parameters

    // Add node to Map
    addNode(nodeInputModel);

    // Send update message to GridModel
    UpdateMessage updateMessage =
                    new UpdateMessage(null, Arrays.asList(nodeInputModel), UpdateMessage.UpdateType.ADD);
    gridMapController.sendUpdateMessage(updateMessage);
}

Я пробовал несколько вещей, чтобы "реактивировать" сцену, но ничего не получалось. Есть ли способ сделать это правильно? Надеюсь, я все четко объяснил. Если нет, пожалуйста, не стесняйтесь спрашивать.

Edit: Я использую несколько файлов FXML. Корневой FXML (MainView.fxml):

<VBox   xmlns="http://javafx.com/javafx/8.0.172-ea"
        xmlns:fx="http://javafx.com/fxml/1"
        fx:id="main"
        fx:controller="edu.ie3.controller.main.MainController">

    <fx:include fx:id="io" source="IoView.fxml"/>

    <fx:include fx:id="tool" source="ToolView.fxml"/>

    <HBox prefHeight="${main.height}">
        <!-- vertical button bar for grid info -->
        <ButtonBar fx:id="leftButtonBar" rotate="-90">
            <buttons>
                <Button fx:id="gridInfoButton" text="Grid Info"/>
            </buttons>
        </ButtonBar>

        <SplitPane fx:id="splitPane" prefWidth="${main.width}">
            <fx:include fx:id="gridTab" source="GridTabView.fxml"/>
        </SplitPane>

    </HBox>

    <fx:define>
        <fx:include fx:id="gridInfo" source="GridInfoView.fxml"/>
        <fx:include fx:id="gridMap" source="GridMapView.fxml"/>
        <fx:include fx:id="gridSchema" source="GridSchemaView.fxml"/>
    </fx:define>

</VBox>

Splitpane, который содержит GridMapView:

<TabPane
        xmlns="http://javafx.com/javafx/8.0.172-ea"
        xmlns:fx="http://javafx.com/fxml/1"
        tabClosingPolicy="UNAVAILABLE"
        fx:id="gridTabPane"
        fx:controller="edu.ie3.controller.gridTab.GridTabController">

    <Tab fx:id="gridMapTab" text="Map View">
        <fx:include fx:id="gridMapLayer" source="GridMapView.fxml"/>
    </Tab>

    <Tab fx:id="gridSchemaTab" text="Schema View">
        <fx:include fx:id="gridSchema" source="GridSchemaView.fxml"/>
    </Tab>

</TabPane>

GridMapView.fxml выглядит так:

<?xml version="1.0" encoding="UTF-8"?>

<?import com.gluonhq.maps.MapView?>
<MapView xmlns="http://javafx.com/javafx/8.0.172-ea"
     xmlns:fx="http://javafx.com/fxml/1"
     fx:id="gridMap"
     fx:controller="edu.ie3.controller.gridTab.gridMap.GridMapController">
</MapView>

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

1 Ответ

0 голосов
/ 19 мая 2019

Я решил это. Проблема заключалась в том, что я включил GridMapController один раз в MainController и один раз в GridTabController. Я удалил fx:include из MainController, и теперь GridMapController инициализируется только один раз. Тем не менее, большое спасибо, Хосе Переда, вы привели меня на правильный путь.

...