Google Maps & JavaFX: Hiển thị điểm đánh dấu trên bản đồ sau khi nhấp vào nút JavaFX


359

Tôi đã cố gắng hiển thị một điểm đánh dấu trên bản đồ khi tôi nhấp vào Nút của ứng dụng JavaFX của mình. Vì vậy, những gì xảy ra là khi tôi nhấp vào nút đó, tôi viết vị trí trong tệp JSON, tệp này sẽ được tải trong tệp html chứa bản đồ. Vấn đề là nó hoạt động hoàn hảo khi tôi mở trang html trong trình duyệt, nhưng không có gì xảy ra trong chế độ xem web của JavaFX và tôi không biết tại sao!

Đây là tệp 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>

Khi tôi nhấp vào nút, tôi điền vào tệp JSON (hoạt động hoàn hảo) và sau đó tôi thực hiện điều này để làm mới webview:

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

Như tôi đã nói trước đây, khi tôi mở tệp trên trình duyệt, tôi thấy kết quả mong đợi, nhưng tôi không biết vấn đề với JavaFX là gì. Nếu có một cách tốt hơn để làm điều này xin vui lòng cho tôi biết.

BIÊN TẬP:

Tôi đã tìm ra giải pháp cho vấn đề bằng cách gửi trực tiếp dữ liệu (tọa độ GPS) từ JavaFX sang Javascript bằng phương thức execScript (), vì vậy tôi không cần tệp json làm cầu nối giữa hai nền tảng. Vì vậy, đây là một ví dụ về cách mã trông như thế nào:

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

Và đây là 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);
  }

Cảm ơn bạn đã bình luận và câu trả lời của bạn, và một loạt đá luân lưu đặc biệt để reddit.



1
Mặc dù kịch bản không được viết theo cách tốt nhất có thể, nhưng dường như không có gì sai với nó. Có một vài khả năng có thể làm cho nó không hoạt động. Đảm bảo rằng điểm đánh dấu mới được thêm vào đầu tệp json. Chuyển cache: falseđến cuộc gọi ajax trong trường hợp nó được lưu trong bộ nhớ cache và đảm bảo bạn nhắm mục tiêu đúng tệp. Ngoài ra một số nhật ký ở đây và sẽ giúp xác định vấn đề.
Gökhan Kurt

1
Có thể là, điều JavaFX có vấn đề khi sử dụng ajax để nhận cuộc gọi / dữ liệu từ các điểm cuối được cung cấp không phải HTTP như test.json của bạn?
Sebastian

@Sebastian Điều khiến tôi phát điên là khi tôi mở ứng dụng, tệp json được tải chính xác và tôi thấy kết quả mong đợi. Vấn đề là khi tôi cập nhật tệp json với một giá trị khác (trong khi ứng dụng đang mở) thì nó không muốn làm mới để hiển thị điểm đánh dấu mới! Vì vậy, không có vấn đề với các cuộc gọi ajax. Nhưng nó có thể là điều gọi lại? bởi vì initMap () được gọi trong khi trang đang tải
Chandler Bing

@ GökhanKurt bạn sẽ đọc câu trả lời ở trên
Chandler Bing

Câu trả lời:


70

Nếu tôi phải đoán - một trong hai điều đang xảy ra:

A) javaFX của bạn không hỗ trợ các cuộc gọi ajax trên trang web chéo hoặc B) nó không chờ phản hồi ajax không đồng bộ / có gì đó không ổn.

Vì vậy, hãy làm một số thử nghiệm cùng nhau. Đầu tiên chúng ta có thể dọn sạch cái này để lồng các cuộc gọi ajax không? Sau đó, bạn có thể thêm vào một số câu lệnh console.log để tìm hiểu những gì từng được gửi lại không? Nếu bạn bỏ lỡ một số đầu ra, chúng tôi biết nó sẽ sai ở đâu và điều đó sẽ giúp chúng tôi sửa chữa mọi thứ.

Lưu ý Tôi đã thay đổi thành công thành các bổ sung 'hoàn thành' vì thành công hơi lỗi thời và mọi thứ được lồng vào nhau để loại bỏ câu hỏi xung quanh liệu có bất kỳ khoảng trống nào được gửi đến các cuộc gọi tiếp theo (vấn đề đồng bộ hóa):

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

Đây là một liên kết về việc nhận đầu ra console.log vào System.out trong Java nếu đây là một vấn đề: JavaFX 8 WebEngine: Làm cách nào để lấy console.log () từ javascript sang System.out trong java?

... Cũng xin chào từ reddit.


Xin chào, vì vậy bạn nghĩ rằng vấn đề là với các cuộc gọi ajax. Ok, tôi sẽ cố gắng tìm một cách khác để gửi các vị trí GPS đến javascript (sử dụng executescript).
Chandler Bing

Không, nó không phải là cuộc gọi ajax. Vấn đề là tôi không thể làm mới webview để hiển thị điểm đánh dấu mới. Khi tôi mở ứng dụng, bản đồ được hiển thị có nghĩa là các cuộc gọi ajax hoạt động tốt.
Chandler Bing

18

Trong dòng:

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

Tôi sẽ thử kiểm tra lại đường dẫn đến tập tin là chính xác. Đọc các câu trả lời khác trên StackOverflow, có vẻ như điều này được cho là có liên quan đến gốc gói và có hoặc không có '/' hàng đầu. tức getResource("data/index.html"). Nhưng, một lần nữa, có lẽ bạn đã thấy các lỗi liên quan đến getResource()...

Mục đích tiếp theo của tôi, với mục đích gỡ lỗi, sẽ là nhận xét phần bạn viết JSON và chỉ cần viết thủ công một số JSON tốt và chỉ cần cố gắng làm cho nó hiển thị trong webView. Càng ít bộ phận chuyển động, càng tốt. Nếu bạn có thể làm cho nó hoạt động với JSON được viết sẵn của mình thì bạn có thể cho rằng đó là một số vấn đề với JSON mà bạn đang viết bằng Java và sau đó nó được tải vào HTML.

Chỉnh sửa: Tôi đào sâu hơn một chút. Điều này có thể hoàn toàn sai một lần nữa nhưng có lẽ bạn có thể thử gọi thủ công initMap()hàm từ Java mà trình duyệt web của bạn thường gọi onload. Làm cách nào để gọi một hàm JavaScript từ JavaView WebView trên Nút bấm? có thêm một số chi tiết. Hãy thử this.webView.getEngine().executeScript("initMap()");sau khi bạn chỉnh sửa JSON bằng nút của bạn.

Chỉnh sửa 2 Ngoài ra, cũng có thể có ý nghĩa khi chia initMapthành một initMapupdateMapchức năng để làm cho bản đồ bắt đầu và sau đó đặt các điểm đánh dấu trên bản đồ. Mặc dù điều này hầu như không phá vỡ bất cứ điều gì.


Không, đó không phải là vấn đề, tôi hiển thị bản đồ khi mở ứng dụng cho phép dòng đó. Nhưng khi tôi nhấp vào nút, tôi muốn đặt điểm đánh dấu trên bản đồ. Nhưng tôi không thể làm mới bản đồ để hiển thị điểm đánh dấu trên đó.
Chandler Bing

1
À, gotcha. Tôi đã hiểu nhầm. Bạn đang nói rằng trang cơ bản đang tải nhưng không có điểm đánh dấu nào được tải? Là bản đồ hiển thị trong webView của bạn ít nhất? Tôi nghĩ rằng bạn có thể đang làm gì đó như bạn đã đề cập initMap ở trên. Nếu nó chỉ gọi chức năng đó khi tải trang thì có lẽ nó không được chỉnh sửa cho json. Bạn sẽ phải làm mới trang trong webview hoặc yêu cầu trang gọi lại initMap bằng cách nào đó - có thể thông qua ajax? Trừ khi JavaFX có thể lấy webView để gọi các hàm javascript
Matt

Khi ứng dụng được mở, mọi thứ tồn tại trong tệp json sẽ được tải. Nhưng khi tôi thay đổi một giá trị trong khi ứng dụng đang mở, tôi muốn làm mới webview để xem sự thay đổi. Nhưng nó không hoạt động! Đây là vấn đề.
Chandler Bing

1
Xem chỉnh sửa của tôi - việc thêm một cuộc gọi thủ công từ Java vào hàm initMap có giúp ích không?
Matt

4

Nếu bánh xe chuột của bạn được sử dụng để phóng to bản đồ ra hoặc vào và điểm đánh dấu xuất hiện, thì bạn đang gặp vấn đề tương tự như tôi đã làm.

Hãy thử phóng to thủ công mapview để khôi phục các điểm đánh dấu. Tôi cũng đã phải sử dụng kỹ thuật này khi hiển thị tuyến đường từ Dịch vụ chỉ đường, nếu không, các điểm đánh dấu điểm không hiển thị chính xác.

Đây là mã trong lớp trình điều khiển Javafx của tôi để làm như vậy:

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

Điều này đã sử dụng GMapsFX, đây chỉ là một trình bao bọc Java mỏng xung quanh các lệnh gọi công cụ javascript trên WebView JavaFX. Hy vọng nó sẽ giúp.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.