I am using GluonHQ Maps 1.0.3 in JavaFX and I have a problem painting nodes on the map.
I have a class GridMapController
which has a MapView
called gridMap
. I also have a class GridPaintLayer
that extends the MapLayer
and where all paintings are done. The GridPaintLayer
is added to the GridMapController
's gridMap
with the method gridMap.addLayer(gridPaintLayer)
. This class ( GridPaintLayer
) has a method addNode(NodeInputModel)
to which I pass a node (that contains lat/lon values) that shall be painted. The mentioned gridMap
( MapView
) can be right-clicked, a popup menu opens where I can choose "Create Node". This calls a method createNodeItemClicked()
which is implemented in the GridPaintLayer
(see below). When I click the "Create Node" menu item, everything works fine and a point appears on the map.
In another part of the programm I have an observable object that notifies its observers whenever a node is added. The notification message is handled in the GridMapController
which then calls the addNode()
method from the GridPaintLayer
. But now, when I want the GridPaintLayer's
baseMap
to calculate the the points position on the scene, the method baseMap.getMapPoint(double lat, double lon)
returns null
because the baseMap's scene is null
. So the node cannot be painted. This happens ie when I want to create a node at another part of the application. The observable notifies the GridMapController
(among others) correctly but then the problem appears as described above.
The methods below are both implemented in the GridPaintLayer
class.
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);
}
I have tried several things to "reactivate" the scene but nothing worked. Is there a way to do that properly? I hope I have explained everything clearly. If not, please feel free to ask.
Edit: I am using multiple FXML files. The root 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>
The Splitpane which contains the 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>
The GridMapView.fxml looks like this:
<?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>
I have already tried commenting some statements out to avoid double including the GridMapView but nothing worked.
I solved it. The problem was that I included the GridMapController once in the MainController and once in the GridTabController. I removed the fx:include
from the MainController and now the GridMapController only initializes once. Nevertheless thank you very much, José Pereda, you brought me on the right way.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.