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/…
Mateen Ulhaq

1
แม้ว่าสคริปต์จะไม่ได้ถูกเขียนในวิธีที่ดีที่สุดเท่าที่จะเป็นไปได้ มีความเป็นไปได้สองอย่างที่อาจทำให้ใช้งานไม่ได้ ตรวจสอบให้แน่ใจว่ามีการเพิ่มเครื่องหมายใหม่ที่ด้านบนของไฟล์ json ส่งผ่านcache: falseไปยังการโทร ajax ในกรณีที่แคชและตรวจสอบให้แน่ใจว่าคุณกำหนดเป้าหมายไฟล์ที่ถูกต้อง นอกจากนี้ยังมีบันทึกบางส่วนที่นี่และจะช่วยระบุปัญหา
Gökhan Kurt

1
เป็นไปได้ไหมว่าสิ่งที่ JavaFX มีปัญหาในการใช้ ajax เพื่อรับสาย / ข้อมูลจากจุดสิ้นสุดที่ไม่ใช่ HTTP ที่ให้บริการเช่น test.json ของคุณ
เซบาสเตียน

@ เซบาสเตียนอะไรที่ทำให้ฉันบ้าคือเมื่อฉันเปิดแอปไฟล์ json จะถูกโหลดอย่างถูกต้องและฉันเห็นผลลัพธ์ที่คาดหวัง ปัญหาคือเมื่อฉันอัปเดตไฟล์ json ด้วยค่าอื่น (ในขณะที่แอปเปิด) มันไม่ต้องการรีเฟรชเพื่อแสดงเครื่องหมายใหม่! ดังนั้นจึงไม่มีปัญหากับการโทร ajax แต่มันจะเป็นสิ่งที่โทรกลับ? เนื่องจาก initMap () ถูกเรียกในขณะที่หน้ากำลังโหลด
Chandler Bing

@ GökhanKurtคุณจะอ่านคำตอบข้างต้นได้ไหม
Chandler Bing

คำตอบ:


70

ถ้าฉันต้องเดา - หนึ่งในสองสิ่งเกิดขึ้น:

A) javaFX ของคุณไม่รองรับการโทร ajax ข้ามไซต์หรือ B) ไม่รอการตอบสนอง 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 (โดยใช้ executescript)
Chandler Bing

ไม่มีไม่ใช่โทร ajax ปัญหาคือฉันไม่สามารถรีเฟรชมุมมองเว็บเพื่อแสดงเครื่องหมายใหม่ เมื่อฉันเปิดแอพแผนที่จะแสดงขึ้นซึ่งหมายความว่าการโทร ajax นั้นใช้ได้ดี
Chandler Bing

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ฟังก์ชั่นสำหรับทำให้แผนที่เริ่มต้นด้วยจากนั้นตั้งเครื่องหมายบนแผนที่ แม้ว่านี่จะเป็นการทำลายอะไรก็ตาม


ไม่นั่นไม่ใช่ปัญหาเลยฉันแสดงแผนที่เมื่อฉันเปิดแอพให้บรรทัดนั้น แต่เมื่อฉันคลิกที่ปุ่มฉันต้องการใส่เครื่องหมายบนแผนที่ แต่ฉันไม่สามารถรีเฟรชแผนที่เพื่อแสดงเครื่องหมายบนมัน
Chandler Bing

1
อ้า gotcha ฉันเข้าใจผิด. คุณกำลังบอกว่าหน้าพื้นฐานกำลังโหลดอยู่ แต่ไม่มีการโหลดเครื่องหมาย? แผนที่แสดงใน webView ของคุณเป็นอย่างน้อยหรือไม่? ฉันคิดว่าคุณอาจจะทำบางสิ่งบางอย่างตามที่คุณกล่าวไว้ใน initMap ด้านบน หากเป็นการเรียกใช้ฟังก์ชันนั้นเมื่อโหลดหน้าเว็บเท่านั้นมันอาจไม่ได้รับการแก้ไข json คุณจะต้องรีเฟรชหน้าเว็บภายใน webview หรือบอกหน้าให้เรียก initMap อีกครั้งว่า - อาจจะผ่าน ajax? ยกเว้นว่า JavaFX จะได้รับ webView เพื่อเรียกใช้ฟังก์ชันจาวาสคริปต์
Matt

เมื่อแอปเปิดทุกอย่างที่มีอยู่ในไฟล์ json จะถูกโหลด แต่เมื่อฉันเปลี่ยนค่าในขณะที่เปิดแอปฉันต้องการรีเฟรชมุมมองเว็บเพื่อดูการเปลี่ยนแปลง แต่มันใช้งานไม่ได้! ปัญหานี้เป็นปัญหา.
แชนด์เลอร์ Bing

1
ดูการแก้ไขของฉัน - การเพิ่มการโทรด้วยตนเองจาก Java ไปยังฟังก์ชัน initMap ช่วยได้หรือไม่
Matt

4

หากล้อเมาส์ของคุณใช้เพื่อซูมแผนที่ออกหรือเข้าและเครื่องหมายปรากฏขึ้นแสดงว่าคุณกำลังประสบปัญหาเดียวกับที่ฉันทำ

ลองซูม mapview ด้วยตนเองเพื่อเรียกคืนเครื่องหมาย ฉันต้องใช้เทคนิคนี้เมื่อแสดงเส้นทางจาก Directions Service มิฉะนั้นตัวบ่งชี้ waypoint ไม่แสดงอย่างถูกต้อง

นี่คือรหัสในคลาสควบคุม 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 ซึ่งเป็นเพียงตัวห่อหุ้มจาวาบาง ๆ รอบโปรแกรมจาวาสคริปต์ที่เรียกใช้บน JavaFX WebView หวังว่ามันจะช่วย

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.