2017-05-23 17 views
346

Próbowałem wyświetlić znacznik na mapie po kliknięciu przycisku mojej aplikacji JavaFX. Co się dzieje, kiedy klikam ten przycisk, piszę pozycję w pliku JSON, ten plik zostanie załadowany do pliku html, który zawiera mapę. Problem polega na tym, że działa doskonale, gdy otwieram stronę HTML w przeglądarce, ale nic nie dzieje się w widoku WWW JavaFX i nie wiem dlaczego!Google Maps & JavaFX: Wyświetlanie znacznika na mapie po kliknięciu przycisku JavaFX

Jest to plik 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> 

Po kliknięciu przycisku wypełnić plik JSON (który działa idealnie), a potem wykonać to, aby odświeżyć webview:

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

Jak już powiedziałem, kiedy otwieram plik w przeglądarce, widzę oczekiwany wynik, ale nie wiem, jaki jest problem z JavaFX. Jeśli jest lepszy sposób to zrobić, proszę powiedz mi.

EDIT:

znalazłem rozwiązanie problemu wysyłając bezpośrednio danych (współrzędne GPS) z JavaFX do JavaScript za pomocą metody executeScript(), więc nie muszę plik json jako most między dwiema platformami. Więc to jest przykładem, jak kod wygląda następująco:

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

A oto 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); 
    } 

Dziękuję za komentarze i odpowiedzi, oraz specjalny rzutach do Reddit.

+47

Dla odniesienia: https://www.reddit.com/r/ProgrammerHumor/comments/6e6wu6/thanks_stackoverflow/ –

+1

Chociaż skrypt nie jest napisany w najlepszy możliwy sposób, nie wydaje się, że jest w nim coś złego. Istnieje kilka możliwości, które mogą sprawić, że nie będzie działać. Upewnij się, że nowy znacznik został dodany do górnej części pliku json. Przekaż 'cache: false' do wywołania ajax w przypadku, gdy jest on buforowany i upewnij się, że kierujesz właściwy plik. Również niektóre dzienniki tu i tam pomogą zidentyfikować problem. –

+1

Czy to możliwe, że obiekt JavaFX ma problemy z używaniem ajax do odbierania połączeń/danych z punktów końcowych obsługiwanych przez inne niż HTTP, takich jak test.json? – Sebastian

Odpowiedz

66

Gdybym miał zgadywać - jedna z dwóch rzeczy się dzieje:

albo) swój JavaFX nie wspiera połączeń site Krzyż ajax lub B) nie czeka na odpowiedź asynchroniczna ajax/coś innego się dzieje źle.

Zróbmy więc wspólnie testy. Po pierwsze możemy to wyczyścić, aby zagnieździć wywołania ajax? Czy możesz dodać niektóre instrukcje console.log, aby dowiedzieć się, co każdy z nich odsyła? Jeśli przegapisz jakieś wyniki, wiemy, dokąd zmierza, a to pomoże nam rozwiązać problemy.

Uwaga Zmieniłem sukces w dodanych słowach, ponieważ sukces jest nieco nieaktualny, a wszystko jest zagnieżdżone, aby wyeliminować pytanie o to, czy do następnego połączenia są wysyłane puste miejsca (problemy z synchronizacją):

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

Oto link na uzyskanie wyjście console.log do System.out w Javie, jeśli jest to problem: JavaFX 8 WebEngine: How to get console.log() from javascript to System.out in java?

... również witam z reddit.

+0

Cześć, więc myślisz, że problem dotyczy wywołań ajaxowych. Ok, spróbuję znaleźć inny sposób wysyłania pozycji GPS do javascript (przy użyciu executescript). –

+0

Nie jest to wywołanie ajaxowe. Problem polega na tym, że nie mogę odświeżyć widoku, aby pokazać nowy znacznik. Kiedy otwieram aplikację, wyświetlana jest mapa, co oznacza, że ​​wywołania ajaxowe działają bez zarzutu. –

16

w linii:

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

chciałbym spróbować sprawdzając ścieżkę do pliku jest poprawna. Odczytując inne odpowiedzi na StackOverflow, wygląda na to, że ma to być odniesienie do katalogu głównego pakietu i albo z wiodącym znakiem "/", albo bez niego. tj. getResource("data/index.html"). Ale, znowu, być może już widzisz błędy związane z getResource() ...

Następnym krokiem w celu debugowania byłoby skomentowanie części, w której piszesz JSON i ręczne napisanie dobrego JSON-a i po prostu spróbuj go pokazać w webView. Im mniej ruchomych części, tym lepiej. Jeśli możesz go uruchomić z wcześniej napisanym JSON-em, możesz założyć, że jest jakiś problem z JSON-em, który piszesz z Javą, a następnie jest ładowany do HTML-a.

Edytuj: Wykopałem trochę głębiej. To może być całkowicie błędne, ale może możesz spróbować ręcznie wywołać funkcję initMap() z Java, którą twoja przeglądarka zwykle wywołuje onload. How to call a JavaScript function from a JavaFX WebView on Button click? ma trochę więcej szczegółów. Wypróbuj this.webView.getEngine().executeScript("initMap()"); po edycji JSON za pomocą przycisku.

Edycja 2 Tak na marginesie, też może mieć sens podzielona initMap do funkcji initMap i updateMap dokonywania mapę, aby rozpocząć, a następnie ustawienie znaczników na mapie. Chociaż to prawie nic nie zepsuje.

+0

Nie, to nie problem, wyświetlam mapę, kiedy otwieram aplikację na linii. Ale gdy kliknę przycisk, chcę umieścić znacznik na mapie. Ale nie mogę odświeżyć mapy, aby pokazać znacznik na niej. –

+1

Ah, gotcha.Źle zrozumiałem. Czy mówisz, że podstawowa strona ładuje się, ale nie ładuje się znaczników? Czy mapa wyświetla się przynajmniej w twoim webView? Myślę, że możesz być na czymś takim, jak wspomniałeś initMap powyżej. Jeśli wywołuje tę funkcję tylko przy ładowaniu strony, prawdopodobnie nie otrzymuje zmian do json. Będziesz musiał odświeżyć stronę w widoku sieciowym lub powiedzieć stronie, aby jakoś ponownie zadzwonić do initMap - może przez ajax? O ile JavaFX nie może wywołać funkcji webView do wywoływania funkcji javascript – Matt

+0

Po uruchomieniu aplikacji ładowane jest wszystko, co istnieje w pliku json. Ale kiedy zmieniam wartość, gdy aplikacja jest otwarta, chcę odświeżyć widok internetowy, aby zobaczyć zmianę. Ale to po prostu nie działa! To jest problem. –

3

Jeśli Twoje kółko myszy jest używane do powiększania mapy, a na ekranie pojawia się znacznik, oznacza to, że robiłem to samo.

Spróbuj ręcznie powiększyć widok mapy, aby przywrócić znaczniki. Musiałem również zastosować tę technikę podczas wyświetlania trasy z usługi Wskazówki, w przeciwnym razie znaczniki punktów drogi nie były wyświetlane poprawnie.

Jest to kod w moim JavaFX klasie kontrolera, aby to zrobić:

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

To użyciu GMapsFX, który jest tylko cienka otoki Java wokół javascript silnik zwraca na WebView JavaFX. Mam nadzieję, że to pomaga.