Coder Perfect

After pressing the JavaFX button, Google Maps will display a marker on the map.

Problem

When I click on a Button in my JavaFX application, I want a marking to appear on the map. So, when I click that button, I’m writing the position in a JSON file, which is then loaded into the html file containing the map. The problem is that it works perfectly when I open the html page in the browser, but nothing happens in the JavaFX’s web view, and I don’t know why !

The html file is as follows:

<!DOCTYPE html>
<html>
  <head>
  <title>Simple Map</title>
  <meta name="viewport" content="initial-scale=1.0">
  <meta charset="utf-8">
  <style>
  /* Always set the map height explicitly to define the size of the div
   * element that contains the map. */
  /*#map {
    height: 100%;
  }*/
  #map{width:100%;height:100%;margin:auto;}
  /* Optional: Makes the sample page fill the window. */
  html, body {
    height: 100%;
    margin: 0;
    padding: 0;
  }
</style>
</head>
<body>
<div id="map"></div>
<script>
  var map;
  var marker;
  // Multiple Markers
  var markers = [];
  var pos = {lat: 46.662388, lng: 0.3599617};
  var itinerary_markers = [];

  function initMap() {

    var currentLat, currentLng;//Latitude et longtitude courante

    $.ajax({
      url: 'https://maps.googleapis.com/maps/api/geocode/json?address=My+ADDRESS&key=MY_KEY',
      async: false,
      dataType: 'json',
      success: function (data) {
        currentLat = data.results[0].geometry.location.lat;
        currentLng = data.results[0].geometry.location.lng;
      }
    });

    map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: currentLat, lng: currentLng},
      zoom: 15,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });


    /*MARQUEUR*/ 
    $.ajax({
        async: false,
        url: 'test.json',
        data: "",
        accepts:'application/json',
        dataType: 'json',
        success: function (data) {
            for (var i = 0; i < data.hydrants.length; i++) {
                markers.push( data.hydrants[i]);
            }
        }
    });

      var posi = new google.maps.LatLng(markers[0].Lat, markers[0].Lng);
      marker = new google.maps.Marker({
          position: posi,
          map: map,
          //title: markers[i][0]
          title: markers[0].Name
        });

  }
</script>

<script
    src="https://code.jquery.com/jquery-3.2.1.min.js"
    integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="
    crossorigin="anonymous">
</script>


<script src="https://maps.googleapis.com/maps/api/js?key=MY_KEY&callback=initMap&language=fr"
async defer></script>

</body>
</html>

I fill the JSON file (which works wonderfully) when I click the button, and then I run this to refresh the webview:

this.webView.getEngine().load(getClass().getResource("/data/index.html").toString());

As I previously stated, when I load the file in a browser, I get the desired result, however I’m not sure what the issue with JavaFX is. Please let me know if there is a better method to do this.

EDIT:

I found a solution to the problem by sending directly the data (the GPS coordinates) from JavaFX to Javascript using the executeScript() method, so I don’t need a json file as bridge between the two platforms. So this is an example of how the code looks like:

eng.executeScript("updateMarker(" + lat + ", " + lng + ")");//eng is a WebEngine instance

The Javascript is as follows:

/*The initial latitude and longtitude*/
var currentLat = the latitude;
var currentLng = the longtitude;

function initMap() {

    map = new google.maps.Map(document.getElementById('map'), {
      center: {lat: currentLat, lng: currentLng},
      zoom: 15,
      mapTypeId: google.maps.MapTypeId.ROADMAP
    });

    var posi = new google.maps.LatLng(currentLat, currentLng);
    marker = new google.maps.Marker({
        position: posi,
        map: map,
        visible: false
    });
  }

/*The method that is I call from JavaFX*/
function updateMarker(_lat, _lng){
    marker.setPosition({lat: _lat, lng: _lng});
    map.setCenter(new google.maps.LatLng(_lat, _lng));
    marker.setVisible(true);
  }

Thank you for your responses and remarks, with a shout-out to reddit.

Asked by Chandler Bing

Solution #1

Your words will be rewritten by QuillBot. Start by typing or copying something into this box, then hit the enter key.

Either your javaFX does not support cross-site ajax calls, or it does not wait for the asynchronous ajax response, or something else is wrong.

So let’s get together and do some testing. First and foremost, can we tidy this up to nest the ajax calls? Can you then add some console.log statements to see what each is returning? If you don’t get certain output, we’ll know what’s wrong and be able to repair it.

Because success is a little out of date, I’ve updated it to the ‘done’ additions, and everything is nested to eliminate the concern of whether any blanks are being put in to the next calls (synchronicity issues):

$.ajax({
    url: 'https://maps.googleapis.com/maps/api/geocode/json?address=My+ADDRESS&key=MY_KEY',
    async: false,
    dataType: 'json'
}).done(function(data) {
    currentLat = data.results[0].geometry.location.lat;
    currentLng = data.results[0].geometry.location.lng;
    console.log(currentLat);
    console.log(currentLng);
    // Multiple Markers
    var markers = [];
    var pos = {lat: 46.662388, lng: 0.3599617};
    var itinerary_markers = [];
    var map = new google.maps.Map(document.getElementById('map'), {
        center: {lat: currentLat, lng: currentLng},
        zoom: 15,
        mapTypeId: google.maps.MapTypeId.ROADMAP
    });
    console.log(map);
    /*MARQUEUR*/ 
    $.ajax({
        async: false,
        url: 'test.json',
        data: "",
        accepts:'application/json',
        dataType: 'json'
    }).done(function(data) {
        for (var i = 0; i < data.hydrants.length; i++) {
            markers.push( data.hydrants[i]);
        }
        console.log(markers);
        var posi = new google.maps.LatLng(markers[0].Lat, markers[0].Lng);
        console.log(posi);
        var marker = new google.maps.Marker({
            position: posi,
            map: map,
            //title: markers[i][0]
            title: markers[0].Name
        });
        console.log(marker);
    }).fail(function(jqXHR, testStatus){
        console.log(textStatus);
    });
}).fail(function(jqXHR, testStatus){
    console.log(textStatus);
});

If this is an issue, here’s how to get the console.log output into System.out in Java: How do I get console.log() from javascript to System.out in JavaFX 8 WebEngine?

…And a warm welcome from Reddit.

Answered by David G

Solution #2

In the line:

this.webView.getEngine().load(getClass().getResource("/data/index.html").toString());

I’d double-check the file’s path to make sure it’s correct. Reading other answers on StackOverflow, it looks like this is supposed to be relative to the package root and either with or without the leading ‘/’. i.e. getResource(“data/index.html”). But, then again, maybe you would already be seeing errors related to getResource()…

For debugging purposes, my next step would be to block out the section where you write the JSON and manually create some good JSON and see if it shows up in the webView. It’s better if there are fewer moving parts. If it works with your pre-written JSON, it’s likely that there’s a problem with the JSON you’re writing in Java and then having it loaded into HTML.

n from a JavaFX component When a button is pressed, does a WebView appear? has some additional information. Give it a shot. webView.getEngine(). after you’ve edited the JSON with your button, executeScript(“initMap()”);

2nd Edit As an aside, splitting initMap into an initMap and updateMap function for creating the map and then setting the markers on the map could make sense. Even yet, this isn’t exactly breaching any rules.

Answered by Matt

Solution #3

If you use your mouse wheel to zoom the map out or in and the marker shows, you’re having the same problem as me.

To restore the markers, manually zoom the mapview. When presenting a route via the Directions Service, I had to use this technique because the waypoint markers were not displaying correctly otherwise.

To do so, I have the following code in my Javafx controller class:

KeyFrame kf1 = new KeyFrame(Duration.seconds(0.75), e -> map.setZoom(map.getZoom() - 1));
KeyFrame kf2 = new KeyFrame(Duration.seconds(1.5), e -> map.setZoom(map.getZoom() + 1));
Timeline timeline = new Timeline(kf1, kf2);
Platform.runLater(timeline::play);

GMapsFX, a thin Java wrapper around javascript engine calls on a JavaFX WebView, was used for this. Hopefully, it has been of assistance.

Answered by Fraser

Post is based on https://stackoverflow.com/questions/44130442/google-maps-javafx-display-marker-on-the-map-after-clicking-javafx-button