Google Maps y JavaFX: muestra el marcador en el mapa después de hacer clic en el botón JavaFX

Resuelto Chandler Bing asked hace 7 años • 0 respuestas

He estado intentando mostrar un marcador en el mapa cuando hago clic en un botón de mi aplicación JavaFX. Entonces lo que sucede es que cuando hago clic en ese botón, escribo la posición en un archivo JSON, este archivo se cargará en el archivo html que contiene el mapa. El problema es que funciona perfectamente cuando abro la página html en el navegador, pero no sucede nada en la vista web de JavaFX, ¡y no sé por qué!

Este es el archivo 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>

Cuando hago clic en el botón, completo el archivo JSON (que funciona perfectamente) y luego ejecuto esto para actualizar la vista web:

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

Como dije antes, cuando abro el archivo en el navegador veo el resultado esperado, pero no sé cuál es el problema con JavaFX. Si hay una mejor manera de hacer esto, dímelo.

EDITAR:

Encontré una solución al problema enviando directamente los datos (las coordenadas GPS) de JavaFX a Javascript usando el método ejecutarScript(), por lo que no necesito un archivo json como puente entre las dos plataformas. Este es un ejemplo de cómo se ve el código:

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

Y aquí está el 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);
  }

Gracias por sus comentarios y respuestas, y un tiroteo especial en reddit.

Chandler Bing avatar May 23 '17 16:05 Chandler Bing
Aceptado

Si tuviera que adivinar, está sucediendo una de dos cosas:

O A) su javaFX no admite llamadas ajax entre sitios o B) no está esperando la respuesta ajax asincrónica/algo más va mal.

Así que hagamos algunas pruebas juntos. En primer lugar, ¿podemos limpiar esto para anidar las llamadas ajax? Entonces, ¿puedes agregar algunas declaraciones de console.log para saber qué envía cada una? Si pierde algún resultado, sabemos dónde está fallando y eso nos ayudará a solucionarlo.

Tenga en cuenta que cambié el éxito por las adiciones "hechas" porque el éxito está un poco desactualizado y todo está anidado para eliminar la pregunta sobre si se enviarán espacios en blanco a las siguientes llamadas (problemas de sincronicidad):

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

Aquí hay un enlace para obtener la salida de console.log en System.out en Java si esto es un problema: JavaFX 8 WebEngine: ¿Cómo obtener console.log() de javascript a System.out en java?

...También saludos desde reddit.

David G avatar May 30 '2017 16:05 David G

En la linea:

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

Intentaría volver a verificar que la ruta al archivo sea correcta. Al leer otras respuestas en StackOverflow, parece que se supone que esto es relativo a la raíz del paquete y con o sin el '/' inicial. es decir getResource("data/index.html"). Pero, de nuevo, tal vez ya estés viendo errores relacionados con getResource()...

Mi siguiente paso, para fines de depuración, sería comentar la parte en la que se escribe el JSON y simplemente escribir manualmente un buen JSON e intentar que aparezca en webView. Cuantas menos piezas móviles, mejor. Si puede hacer que funcione con su JSON preescrito, entonces puede asumir que hay algún problema con el JSON que está escribiendo con Java y luego se carga en HTML.

Editar: profundicé un poco más. Esto podría volver a ser totalmente incorrecto, pero tal vez pueda intentar llamar manualmente a la initMap()función desde Java que su navegador web normalmente llama onload. ¿Cómo llamar a una función de JavaScript desde un WebView JavaFX al hacer clic en un botón? tiene algunos detalles más. Pruebe this.webView.getEngine().executeScript("initMap()");después de editar el JSON con su botón.

Edición 2 Además, también podría tener sentido dividirse initMapen una función initMapy updateMappara crear el mapa para empezar y luego configurar los marcadores en el mapa. Aunque esto no rompe nada.

Matt avatar May 30 '2017 18:05 Matt

Si utiliza la rueda del mouse para acercar o alejar el mapa y aparece el marcador, entonces está experimentando el mismo problema que yo.

Intente hacer zoom manualmente en la vista del mapa para restaurar los marcadores. También tuve que emplear esta técnica al mostrar una ruta desde el Servicio de indicaciones; de lo contrario, los marcadores de puntos de referencia no se mostraban correctamente.

Este es el código en mi clase de controlador Javafx para hacerlo:

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

Esto estaba usando GMapsFX, que es solo un contenedor Java delgado alrededor de las llamadas al motor JavaScript en un WebView JavaFX. Ojalá ayude.

Fraser avatar Jun 02 '2017 09:06 Fraser