web-dev-qa-db-fra.com

Google Maps & JavaFX: Afficher le marqueur sur la carte après avoir cliqué sur le bouton JavaFX

J'ai essayé d'afficher un marqueur sur la carte en cliquant sur un bouton de mon application JavaFX. Donc ce qui se passe, c’est que lorsque je clique sur ce bouton, j’écris la position dans un fichier JSON, ce fichier sera chargé dans le fichier html contenant la carte. Le problème est que cela fonctionne parfaitement lorsque j'ouvre la page html dans le navigateur, mais rien ne se passe dans la vue Web de JavaFX, et je ne sais pas pourquoi!

C'est le fichier html:

<!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>

Lorsque je clique sur le bouton, je remplis le fichier JSON (qui fonctionne parfaitement), puis je l'exécute pour actualiser la vue Web:

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

Comme je l'ai déjà dit, lorsque j'ouvre le fichier sur le navigateur, je vois le résultat attendu, mais je ne sais pas quel est le problème avec JavaFX. S'il y a une meilleure façon de le faire, s'il vous plaît dites-le moi.

EDIT:

J'ai trouvé une solution au problème en envoyant directement les données (les coordonnées GPS) de JavaFX à Javascript en utilisant la méthode executeScript (), je n'ai donc pas besoin d'un fichier json comme pont entre les deux plates-formes. Voici donc un exemple de la façon dont le code se présente:

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

Et voici le Javascript:

/*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);
  }

Merci pour vos commentaires et réponses, et un shootout spécial à reddit.

356
Chandler Bing

Si je devais deviner - une des deux choses se passe:

Soit A) votre fichier javaFX ne prend pas en charge les appels ajax entre sites, soit B) il n’attend pas la réponse ajax asynchrone/une autre erreur se produit.

Faisons donc des tests ensemble. Premièrement, pouvons-nous nettoyer cela pour imbriquer les appels ajax? Pouvez-vous ensuite ajouter quelques instructions console.log pour savoir ce que chacune d’elles renvoie? Si vous manquez une sortie, nous savons où cela ne va pas et cela nous aidera à résoudre le problème.

Remarque J'ai remplacé succès par les ajouts "done" car le succès est un peu obsolète et tout est imbriqué pour éliminer la question de savoir si des blancs sont envoyés aux prochains appels (problèmes de synchronisation):

$.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);
});

Voici un lien sur l'obtention de la sortie console.log dans System.out dans Java s'il s'agit d'un problème: JavaFX 8 WebEngine: Comment obtenir console.log () à partir de javascript vers System .out en java?

... Salut aussi de Reddit.

69
David G

Dans la ligne:

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

Je voudrais essayer de vérifier le chemin du fichier est correct. En lisant d’autres réponses sur StackOverflow, il semble que cela soit supposé être relatif à la racine du paquet et avec ou sans le signe '/'. c'est-à-dire getResource("data/index.html"). Mais, encore une fois, vous verriez peut-être déjà des erreurs liées à getResource()...

Mon prochain point de départ, à des fins de débogage, serait de commenter la partie dans laquelle vous écrivez le JSON, écrivez simplement manuellement un bon JSON et essayez simplement de le faire apparaître dans la vue Web. Moins il y a de pièces en mouvement, mieux c'est. Si vous pouvez le faire fonctionner avec votre JSON pré-écrit, vous pouvez en déduire que le problème rencontré avec le JSON que vous écrivez avec Java est en cours de chargement dans le code HTML.

Edit: J'ai creusé un peu plus profondément. Cela peut être à nouveau totalement faux, mais vous pouvez peut-être essayer d'appeler manuellement la fonction initMap() de Java que votre navigateur Web appelle normalement onload. Comment appeler une fonction JavaScript à partir d'un JavaFX WebView en cliquant sur un bouton? a quelques détails supplémentaires. Essayez this.webView.getEngine().executeScript("initMap()"); après avoir modifié le JSON avec votre bouton.

Edit 2 En passant, il pourrait également être judicieux de scinder initMap en initMap et updateMap fonction permettant de commencer par définir la carte, puis de définir les marqueurs sur la carte. Bien que cela ne casse presque rien.

17
Matt

Si vous utilisez la molette de la souris pour agrandir ou réduire la carte et que le marqueur apparaît, vous rencontrez le même problème que moi.

Essayez de zoomer manuellement sur la carte pour restaurer les marqueurs. J'ai également dû utiliser cette technique lors de l'affichage d'un itinéraire à partir du service de localisation, sinon les marqueurs de points de route ne s'affichaient pas correctement.

Voici le code de ma classe de contrôleur Javafx:

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);

Il s’agissait de GMapsFX, qui n’est qu’un mince wrapper Java autour des appels de moteur javascript sur une vue Web JavaFX. J'espère que ça aide.

3
Fraser