Google Maps e JavaFX: visualizza l'indicatore sulla mappa dopo aver fatto clic sul pulsante JavaFX


359

Ho provato a visualizzare un indicatore sulla mappa quando faccio clic su un pulsante della mia applicazione JavaFX. Quindi quello che succede è quando faccio clic su quel pulsante, scrivo la posizione in un file JSON, questo file verrà caricato nel file html che contiene la mappa. Il problema è che funziona perfettamente quando apro la pagina html nel browser, ma non succede nulla nella vista web di JavaFX e non so perché!

Questo è il file 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>

Quando faccio clic sul pulsante, riempio il file JSON (che funziona perfettamente) e quindi eseguo questo per aggiornare la visualizzazione Web:

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

Come ho detto prima, quando apro il file sul browser vedo il risultato atteso, ma non so quale sia il problema con JavaFX. Se c'è un modo migliore per farlo, per favore dimmelo.

MODIFICARE:

Ho trovato una soluzione al problema inviando direttamente i dati (le coordinate GPS) da JavaFX a Javascript usando il metodo executeScript (), quindi non ho bisogno di un file json come bridge tra le due piattaforme. Quindi questo è un esempio di come appare il codice:

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

Ed ecco il 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);
  }

Grazie per i vostri commenti e risposte, e uno speciale sparatoria a reddit.



1
Sebbene la sceneggiatura non sia scritta nel miglior modo possibile, non sembra esserci nulla di sbagliato. Ci sono un paio di possibilità che potrebbero non funzionare. Assicurarsi che il nuovo marcatore venga aggiunto all'inizio del file json. Passa cache: falsealla chiamata ajax nel caso sia memorizzata nella cache e assicurati di scegliere come target il file giusto. Anche alcuni registri qua e là potrebbero aiutare a identificare il problema.
Gökhan Kurt,

1
Potrebbe essere che la cosa JavaFX abbia problemi nell'uso di ajax per ricevere chiamate / dati da endpoint serviti non HTTP come il tuo test.json?
Sebastian,

@Sebastian Quello che mi fa impazzire è che quando apro l'app il file json viene caricato correttamente e vedo il risultato atteso. Il problema è quando aggiorno il file json con un altro valore (mentre l'app è aperta) semplicemente non vuole aggiornare per visualizzare il nuovo marcatore! Quindi non ci sono problemi con le chiamate Ajax. Ma può essere la cosa di richiamata? perché initMap () viene chiamato durante il caricamento della pagina
Chandler Bing

@ GökhanKurt leggeresti la risposta sopra
Chandler Bing,

Risposte:


70

Se dovessi indovinare, sta accadendo una delle due cose:

A) il tuo javaFX non supporta le chiamate ajax tra siti o B) non sta aspettando la risposta ajax asincrona / qualcos'altro sta andando storto.

Facciamo alcuni test insieme. In primo luogo possiamo ripulirlo per annidare le chiamate ajax? Quindi è possibile aggiungere alcune istruzioni console.log per scoprire che cosa ciascuna sta rispedendo? Se manchi qualche output sappiamo dove sta andando storto e questo ci aiuterà a sistemare le cose.

Nota: ho modificato il successo con le aggiunte "completate" perché il successo è un po 'obsoleto e tutto è annidato per eliminare la domanda se eventuali spazi vuoti vengono inviati alle chiamate successive (problemi di sincronicità):

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

Ecco un link su come ottenere l'output console.log su System.out in Java se questo è un problema: JavaFX 8 WebEngine: Come ottenere console.log () da javascript a System.out in java?

... Ciao anche da reddit.


Ciao, quindi pensi che il problema sia con le chiamate Ajax. Ok, proverò a trovare un altro modo per inviare le posizioni GPS a javascript (usando execescript).
Chandler Bing,

No, non sono le chiamate Ajax. Il problema è che non riesco ad aggiornare la visualizzazione Web per mostrare il nuovo marker. Quando apro l'app, viene visualizzata la mappa, il che significa che le chiamate ajax funzionano correttamente.
Chandler Bing,

18

Nella linea:

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

Vorrei provare a ricontrollare che il percorso del file sia corretto. Leggendo altre risposte su StackOverflow, sembra che questo dovrebbe essere relativo alla radice del pacchetto e con o senza il '/' iniziale. vale a dire getResource("data/index.html"). Ma, di nuovo, forse potresti già vedere errori relativi a getResource()...

Il mio prossimo passo a, per scopi di debug, sarebbe quello di commentare la parte in cui scrivi JSON e semplicemente scrivere manualmente un buon JSON e provare solo a farlo apparire in webView. Meno parti in movimento, meglio è. Se riesci a farlo funzionare con il tuo JSON pre-scritto, puoi presumere che sia un problema con il JSON che stai scrivendo con Java e quindi che sia caricato nell'HTML.

Modifica: ho scavato un po 'più a fondo. Questo potrebbe essere di nuovo totalmente sbagliato, ma forse puoi provare a chiamare manualmente la initMap()funzione da Java che il tuo browser web normalmente chiama onload. Come chiamare una funzione JavaScript da un JavaFX WebView su Click Button? ha qualche dettaglio in più. Prova this.webView.getEngine().executeScript("initMap()");dopo aver modificato JSON con il tuo pulsante.

Modifica 2 Anche a parte, potrebbe essere logico dividere initMapin una funzione initMape updateMapper iniziare la mappa e quindi impostare i marcatori sulla mappa. Anche se questo non rompe quasi nulla.


No non è questo il problema, visualizzo la mappa quando apro l'app e uso quella linea. Ma quando faccio clic su un pulsante, voglio mettere un indicatore sulla mappa. Ma non riesco ad aggiornare la mappa per mostrare l'indicatore su di essa.
Chandler Bing,

1
Ah, capito. Ho frainteso. Stai dicendo che la pagina di base si sta caricando ma nessun marker viene caricato? La mappa viene visualizzata almeno nel tuo webView? Penso che potresti essere su qualcosa come menzionato sopra InitMap. Se sta chiamando solo quella funzione al caricamento della pagina, probabilmente non sta ottenendo modifiche al json. Dovresti aggiornare la pagina all'interno della visualizzazione Web o dire alla pagina di chiamare di nuovo initMap in qualche modo, forse attraverso Ajax? A meno che JavaFX non riesca a far sì che webView chiami le funzioni javascript
Matt,

Quando l'app viene aperta, viene caricato tutto ciò che esiste nel file json. Ma quando cambio un valore mentre l'app è aperta, voglio aggiornare la visualizzazione Web per vedere la modifica. Ma non funziona! Questo è il problema.
Chandler Bing,

1
Vedi la mia modifica - l'aggiunta di una chiamata manuale da Java alla funzione initMap aiuta?
Matt,

4

Se la rotellina del mouse viene utilizzata per ingrandire o rimpicciolire la mappa e viene visualizzato l'indicatore, si verifica lo stesso problema riscontrato.

Prova a ingrandire manualmente la visualizzazione della mappa per ripristinare i marker. Ho anche dovuto utilizzare questa tecnica quando visualizzavo una rotta dal servizio indicazioni stradali, altrimenti i marker di waypoint non venivano visualizzati correttamente.

Questo è il codice nella mia classe di controller Javafx per farlo:

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

Stava usando GMapsFX, che è solo un sottile wrapper Java per le chiamate del motore JavaScript su JavaFX WebView. Speriamo che aiuti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.