Búsqueda de sitios web

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


He estado tratando de mostrar un marcador en el mapa cuando hago clic en un botón de mi aplicación JavaFX. 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 pasa 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, lleno el archivo JSON (lo cual 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, por favor dígamelo.

EDITAR:

Encontré una solución al problema enviando directamente los datos (las coordenadas GPS) de JavaFX a Javascript usando el método executeScript(), así que no necesito un archivo json como puente entre las dos plataformas. Así que 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 tus comentarios y respuestas, y un saludo especial a Reddit.

Respuesta #1

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

O A) tu JavaFX no está soportando llamadas AJAX entre sitios o B) no está esperando la respuesta asíncrona de AJAX/algo más está saliendo mal.

Así que hagamos algunas pruebas juntos. Primero, ¿podemos limpiar esto para anidar las llamadas ajax? Luego, ¿puedes añadir algunas declaraciones console.log para averiguar qué está devolviendo cada una? Si te falta alguna salida, sabremos dónde está fallando y eso nos ayudará a arreglar las cosas.

Nota que he cambiado 'success' a las adiciones 'done' porque 'success' está un poco desactualizado, y todo está anidado para eliminar la duda sobre si se están enviando espacios en blanco a las siguientes llamadas (problemas de sincronización):

$.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 sobre cómo 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 en System.out en Java?

...También hola desde Reddit.

Respuesta #2

En la línea:

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

Intentaría verificar dos veces que la ruta al archivo sea correcta. Al leer otras respuestas en StackOverflow, parece que esto debería ser relativo a la raíz del paquete y con o sin la barra inclinada inicial '/'. Es decir, getResource("data/index.html"). Pero, nuevamente, tal vez ya estarías viendo errores relacionados con getResource()...

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

Edición: Escarbé un poco más. Esto podría estar totalmente equivocado otra vez, pero tal vez puedas intentar llamar manualmente a la función initMap() desde Java, que tu navegador web normalmente llama al cargar la página. ¿Cómo llamar a una función de JavaScript desde un WebView de JavaFX al hacer clic en un botón? tiene algunos detalles más. Intenta this.webView.getEngine().executeScript("initMap()"); después de editar el JSON con tu botón.

Editar 2 Como comentario adicional, también podría tener sentido dividir initMap en una función initMap y una función updateMap para crear el mapa inicialmente y luego establecer los marcadores en el mapa. Aunque esto difícilmente está rompiendo algo.

Artículos relacionados