Я использую 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, но ничего не получалось.