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

359

J'ai essayé d'afficher un marqueur sur la carte lorsque je clique sur un bouton de mon application JavaFX. Donc, ce qui se passe, c'est quand je clique sur ce bouton, j'écris la position dans un fichier JSON, ce fichier sera chargé dans le fichier html qui contient la carte. Le problème est qu'il 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!

Voici 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 rafraîchir 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 existe une meilleure façon de procéder, dites-le-moi.

ÉDITER:

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 (), donc je n'ai pas besoin d'un fichier json comme pont entre les deux plates-formes. Voici donc un exemple de l'apparence du code:

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 une fusillade spéciale pour reddit.

Chandler Bing
la source
48
Pour référence: reddit.com/r/ProgrammerHumor/comments/6e6wu6/…
Mateen Ulhaq
1
Bien que le script ne soit pas écrit de la meilleure façon possible, il ne semble pas y avoir de problème. Il y a quelques possibilités qui peuvent faire en sorte que cela ne fonctionne pas. Assurez-vous que le nouveau marqueur est ajouté en haut du fichier json. Passez cache: falseà l'appel ajax dans le cas où il est mis en cache et assurez-vous de cibler le bon fichier. De plus, certains journaux ici et là aideraient à identifier le problème.
Gökhan Kurt
1
Se pourrait-il que la chose JavaFX ait des problèmes à utiliser ajax pour recevoir des appels / données à partir de points de terminaison non HTTP servis comme votre test.json?
Sebastian
@Sebastian Ce qui me rend fou, c'est que lorsque j'ouvre l'application, le fichier json est chargé correctement et je vois le résultat attendu. Le problème est que lorsque je mets à jour le fichier json avec une autre valeur (alors que l'application est ouverte), il ne veut tout simplement pas se rafraîchir pour afficher le nouveau marqueur! Il n'y a donc aucun problème avec les appels ajax. Mais peut-il s'agir du rappel? parce que initMap () est appelé pendant le chargement de la page
Chandler Bing
@ GökhanKurt liriez-vous la réponse ci
Chandler Bing

Réponses:

70

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

Soit A) votre javaFX ne prend pas en charge les appels ajax intersites ou B) il n'attend pas la réponse ajax asynchrone / quelque chose d'autre ne va pas.

Faisons donc des tests ensemble. Tout d'abord, pouvons-nous nettoyer cela pour imbriquer les appels ajax? Ensuite, pouvez-vous ajouter des instructions console.log pour savoir ce que chacune renvoie? Si vous manquez une sortie, nous savons où ça va mal et cela nous aidera à résoudre les problèmes.

Remarque: j'ai changé le succès en ajouts `` terminé '' car le succès est un peu dépassé 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 en Java si c'est un problème: JavaFX 8 WebEngine: Comment obtenir console.log () de javascript à System.out en java?

... Bonjour aussi de reddit.

David G
la source
Salut, vous pensez donc que le problème vient des appels ajax. Ok, je vais essayer de trouver une autre façon d'envoyer les positions GPS en javascript (en utilisant executescript).
Chandler Bing
Non, ce n'est pas les appels ajax. Le problème est que je ne peux pas actualiser la vue Web pour afficher le nouveau marqueur. Lorsque j'ouvre l'application, la carte s'affiche, ce qui signifie que les appels ajax fonctionnent correctement.
Chandler Bing
18

Dans la ligne:

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

J'essaierais de revérifier que le chemin d'accès au fichier est correct. En lisant d'autres réponses sur StackOverflow, on dirait que cela est censé être relatif à la racine du package et avec ou sans le '/'. ie getResource("data/index.html"). Mais, encore une fois, peut-être que vous verriez déjà des erreurs liées à getResource()...

Ma prochaine étape, à des fins de débogage, serait de commenter la partie où vous écrivez le JSON et écrivez simplement manuellement un bon JSON et essayez simplement de le faire apparaître dans la webView. Moins il y a de pièces mobiles, mieux c'est. Si vous pouvez le faire fonctionner avec votre JSON pré-écrit, alors vous pouvez supposer que c'est un problème avec le JSON que vous écrivez avec Java et ensuite il est chargé dans le HTML.

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

Edit 2 En aparté aussi, il peut être judicieux de se diviser initMapen une fonction initMapet updateMapde commencer par la carte, puis de définir les marqueurs sur la carte. Bien que cela ne brise presque rien.

Mat
la source
Non, ce n'est pas le problème, j'affiche la carte lorsque j'ouvre l'application en utilisant cette ligne. Mais quand je clique sur un bouton, je veux mettre un marqueur sur la carte. Mais je ne peux pas rafraîchir la carte pour montrer le marqueur dessus.
Chandler Bing
1
Ah, gotcha. J'ai mal compris. Êtes-vous en train de dire que la page de base est en cours de chargement mais qu'aucun marqueur n'est chargé? La carte apparaît-elle au moins dans votre WebView? Je pense que vous pouvez être sur quelque chose comme vous l'avez mentionné initMap ci-dessus. S'il n'appelle cette fonction qu'au chargement de la page, il n'obtient probablement pas de modifications dans le json. Vous devrez actualiser la page dans la vue Web ou dire à la page d'appeler à nouveau initMap d'une manière ou d'une autre - peut-être via ajax? À moins que JavaFX puisse obtenir la webView pour appeler les fonctions javascript
Matt
Lorsque l'application est ouverte, tout ce qui existe dans le fichier json est chargé. Mais lorsque je modifie une valeur alors que l'application est ouverte, je souhaite actualiser la vue Web pour voir le changement. Mais cela ne fonctionne tout simplement pas! C'est le problème.
Chandler Bing
1
Voir ma modification - l'ajout d'un appel manuel de Java à la fonction initMap aide-t-il?
Matt
4

Si vous utilisez la molette de la souris pour effectuer un zoom avant ou arrière sur 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 Directions, sinon les marqueurs de waypoints ne s'affichaient pas correctement.

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

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

Cela utilisait GMapsFX, qui n'est qu'un mince wrapper Java autour des appels du moteur javascript sur une JavaFX WebView. J'espère que cela aide.

Fraser
la source