Google Maps & JavaFX: отображение маркера на карте после нажатия кнопки JavaFX

359

Я пытался отобразить маркер на карте, когда я нажимал на кнопку приложения JavaFX. Так что происходит, когда я нажимаю на эту кнопку, я записываю позицию в файл JSON, этот файл будет загружен в HTML-файл, который содержит карту. Проблема в том, что он прекрасно работает, когда я открываю HTML-страницу в браузере, но в веб-представлении JavaFX ничего не происходит, и я не знаю почему!

Это 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>

Когда я нажимаю кнопку, я заполняю файл JSON (который работает отлично), а затем выполняю это, чтобы обновить веб-просмотр:

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

Как я уже говорил ранее, когда я открываю файл в браузере, я вижу ожидаемый результат, но я не знаю, в чем проблема с JavaFX. Если есть лучший способ сделать это, пожалуйста, скажите мне.

РЕДАКТИРОВАТЬ:

Я нашел решение этой проблемы, отправив непосредственно данные (координаты GPS) из JavaFX в Javascript с помощью метода executeScript (), поэтому мне не нужен файл json в качестве моста между двумя платформами. Итак, это пример того, как выглядит код:

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

А вот и 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);
  }

Спасибо за ваши комментарии и ответы, а также специальную перестрелку для Reddit.

Чендлер Бинг
источник
48
Для справки: reddit.com/r/ProgrammerHumor/comments/6e6wu6/…
Матин Улхак
1
Хотя сценарий написан не лучшим образом, в этом нет ничего плохого. Есть пара возможностей, которые могут заставить его не работать. Убедитесь, что новый маркер добавлен в верхнюю часть файла json. Перейдите cache: falseк вызову ajax, если он кешируется, и убедитесь, что вы выбрали правильный файл. Также некоторые журналы здесь и там помогут выявить проблему.
Гекхан Курт
1
Может ли быть так, что у JavaFX есть проблемы с использованием ajax для получения вызовов / данных от не обслуживаемых HTTP конечных точек, таких как ваш test.json?
Себастьян
@Sebastian Что сводит меня с ума, так это то, что когда я открываю приложение, файл json загружается правильно, и я вижу ожидаемый результат. Проблема в том, что когда я обновляю json-файл другим значением (когда приложение открыто), он просто не хочет обновляться, чтобы отобразить новый маркер! Таким образом, нет никаких проблем с вызовами ajax. Но это может быть вещь обратного вызова? потому что initMap () вызывается во время загрузки страницы
Chandler Bing
@ GökhanKurt вы бы прочитали ответ выше
Чендлер Бинг

Ответы:

70

Если бы мне пришлось угадывать - происходит одно из двух:

Либо A) ваш javaFX не поддерживает межсайтовые вызовы ajax, либо B) он не ожидает асинхронного ответа ajax / что-то еще идет не так.

Итак, давайте проведем некоторое тестирование вместе. Во-первых, можем ли мы это очистить, чтобы вкладывать вызовы ajax? Тогда вы можете добавить несколько операторов console.log, чтобы узнать, что каждый из них отправляет обратно? Если вы пропустите какой-либо вывод, мы знаем, где он идет не так, и это поможет нам все исправить.

Заметьте, я изменил успех на дополнения «сделано», потому что успех немного устарел, и все вложено, чтобы устранить вопрос о том, отправляются ли какие-либо пропуски при следующих вызовах (проблемы синхронности):

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

Вот ссылка на получение вывода console.log в System.out на Java, если это является проблемой: JavaFX 8 WebEngine: Как получить console.log () из javascript в System.out в java?

... Также привет от Reddit.

Дэвид Г
источник
Привет, так что вы думаете, что проблема с вызовами ajax. Хорошо, я попытаюсь найти другой способ отправки GPS-позиций в javascript (используя executetescript).
Чендлер Бинг
Нет, это не призывы Аякса. Проблема в том, что я не могу обновить веб-просмотр, чтобы показать новый маркер. Когда я открываю приложение, отображается карта, что означает, что вызовы ajax работают нормально.
Чендлер Бинг
18

В соответствии:

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

Я бы попробовал дважды проверить правильность пути к файлу. Читая другие ответы по StackOverflow, похоже, что это должно быть относительно корня пакета и с или без начального '/'. то есть getResource("data/index.html"). Но, опять же, может быть, вы уже видели ошибки, связанные с getResource()...

Следующим шагом в целях отладки было бы закомментировать часть, в которой вы пишете JSON, и просто вручную написать хороший JSON и просто попытаться показать его в webView. Чем меньше движущихся частей, тем лучше. Если вы можете заставить его работать с вашим предварительно написанным JSON, тогда вы можете предположить, что это некоторая проблема с JSON, который вы пишете с Java, а затем он загружается в HTML.

Редактировать: я вырыл немного глубже. Это может быть совершенно неправильно, но, возможно, вы можете попробовать вручную вызвать initMap()функцию из Java, которую ваш веб-браузер обычно вызывает onload. Как вызвать функцию JavaScript из JavaFX WebView при нажатии кнопки? имеет еще несколько деталей. Попробуйте this.webView.getEngine().executeScript("initMap()");после редактирования JSON с вашей кнопкой.

Редактировать 2 Кроме того, может быть, имеет смысл разделить initMapна функцию initMapи updateMapдля создания карты для начала, а затем установить маркеры на карте. Хотя это вряд ли что-нибудь сломает.

Matt
источник
Нет, это не проблема, я отображаю карту, когда открываю приложение, назначающее эту строку. Но когда я нажимаю на кнопку, я хочу поставить маркер на карте. Но я не могу обновить карту, чтобы показать на ней маркер.
Чендлер Бинг
1
Ах, понял. Я неправильно понял. Вы говорите, что основная страница загружается, но маркеры не загружаются? Карта, по крайней мере, отображается в вашем webView? Я думаю, что вы можете быть к чему-то, как вы упомянули initMap выше. Если он вызывает эту функцию только при загрузке страницы, то, вероятно, он не получает правки в json. Вам нужно обновить страницу в веб-просмотре или сказать странице, чтобы она снова как-то вызывала initMap - может быть через ajax? Если только JavaFX не может заставить WebView вызывать функции javascript
Мэтт
Когда приложение открыто, загружается все, что существует в файле json. Но когда я изменяю значение, когда приложение открыто, я хочу обновить веб-просмотр, чтобы увидеть изменения. Но это просто не работает! Это проблема.
Чендлер Бинг
1
Смотрите мое редактирование - помогает ли добавление ручного вызова из Java в функцию initMap?
Мэтт
4

Если ваше колесо мыши используется для уменьшения или уменьшения карты, и появляется маркер, то вы столкнулись с той же проблемой, что и я.

Попробуйте вручную увеличить масштаб просмотра карты, чтобы восстановить маркеры. Я также должен был использовать эту технику при отображении маршрута из службы маршрутов, в противном случае маркеры путевых точек отображались некорректно.

Это код в моем классе контроллера Javafx для этого:

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

Для этого использовался GMapsFX, который является просто тонкой оболочкой Java для вызовов движка javascript в JavaFX WebView. Надеюсь, это поможет.

Фрейзер
источник