You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java+JavaScript+JavaFX开发中Google地图显示后消失的问题求助

JavaFX WebView加载谷歌地图后几秒消失的修复方案

我用Java、JavaScript和JavaFX开发桌面应用,其中一个功能是从数据库获取场地地址(街道+城市,无邮编),调用Maps JavaScript API和Geocoding API在地图上显示位置。地图能正确加载位置,但几秒后就完全消失,效果如下:

显示正常时:
地图正常显示

消失后:
地图消失后

当前实现地图显示的Java代码如下:

public void showMap(Venue venue) {
  WebEngine webEngine   = mapView.getEngine();

  Location location     = venue.getLocation();
  String address        = location.toString();
  String encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8);

  String mapHTML = "<html>" +
    "<head>" +
    "<script src=\"https://maps.googleapis.com/maps/api/js?key=API_KEY\"></script>" +
    "<script>" +
    "function initMap() {" +
    "  var geocoder = new google.maps.Geocoder();" +
    "  geocoder.geocode({'address': '" + encodedAddress + "'}, function(results, status) {" +
    "    if (status === 'OK') {" +
    "      var mapOptions = {" +
    "        zoom: 15," +
    "        center: results[0].geometry.location," +
    "        mapTypeId: google.maps.MapTypeId.ROADMAP" +
    "      };" +
    "      var map = new google.maps.Map(document.getElementById('map'), mapOptions);" +
    "      new google.maps.Marker({" +
    "        position: results[0].geometry.location," +
    "        map: map" +
    "      });" +
    "    } else {" +
    "      alert('Geocode was not successful for the following reason: ' + status);" +
    "    }" +
    "  });" +
    "}" +
    "</script>" +
    "</head>" +
    "<body onload='initMap()'>" +
    "<div id='map' style='width:100%;height:100%;'></div>" +
    "</body>" +
    "</html>";

  webEngine.loadContent(mapHTML);
}

问题原因及修复方案

1. 核心问题

WebView加载动态HTML字符串时,可能因DOM树渲染不稳定、谷歌地图异步加载与WebView渲染周期冲突,或是地图容器高度依赖未明确设置的body高度,导致地图渲染后被重置消失。

2. 具体修复步骤

(1)强制设置HTML全屏样式

修改HTML字符串,给html、body和地图容器明确设置全屏样式,确保容器尺寸稳定:

String mapHTML = "<html style='height:100%;margin:0;padding:0;'>" +
  "<head>" +
  "<script src=\"https://maps.googleapis.com/maps/api/js?key=API_KEY\"></script>" +
  "<script>" +
  "function initMap() {" +
  "  var geocoder = new google.maps.Geocoder();" +
  "  geocoder.geocode({'address': '" + encodedAddress + "'}, function(results, status) {" +
  "    if (status === 'OK') {" +
  "      var mapOptions = {" +
  "        zoom: 15," +
  "        center: results[0].geometry.location," +
  "        mapTypeId: google.maps.MapTypeId.ROADMAP" +
  "      };" +
  "      var map = new google.maps.Map(document.getElementById('map'), mapOptions);" +
  "      new google.maps.Marker({" +
  "        position: results[0].geometry.location," +
  "        map: map" +
  "      });" +
  "      // 地图渲染完成后强制锁定容器尺寸" +
  "      google.maps.event.addListenerOnce(map, 'idle', function() {" +
  "        document.getElementById('map').style.height = '100%';" +
  "      });" +
  "    } else {" +
  "      alert('Geocode was not successful for the following reason: ' + status);" +
  "    }" +
  "  });" +
  "}" +
  "</script>" +
  "</head>" +
  "<body style='height:100%;margin:0;padding:0;' onload='initMap()'>" +
  "<div id='map' style='width:100%;height:100%;'></div>" +
  "</body>" +
  "</html>";

(2)避免重复加载WebView内容

在showMap方法开头添加判断,防止频繁调用导致地图被重复加载覆盖:

// 检查当前WebView是否已加载有效地图内容,避免重复加载
if (webEngine.getDocument() != null && webEngine.getDocument().getElementById("map") != null) {
    return;
}

(3)将地理编码移至Java层(可选,稳定性更高)

如果JavaScript异步地理编码与WebView的交互是问题根源,可以改用Java HTTP客户端直接调用Geocoding API,获取经纬度后再传给地图:

// 1. Java层调用Geocoding API获取经纬度
public LatLng geocodeAddress(String address) throws IOException {
    String encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8);
    String url = "https://maps.googleapis.com/maps/api/geocode/json?address=" + encodedAddress + "&key=API_KEY";
    
    HttpClient client = HttpClient.newHttpClient();
    HttpRequest request = HttpRequest.newBuilder()
            .uri(URI.create(url))
            .build();
    
    HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
    JsonObject json = JsonParser.parseString(response.body()).getAsJsonObject();
    
    if ("OK".equals(json.get("status").getAsString())) {
        JsonObject location = json.getAsJsonArray("results")
                .get(0).getAsJsonObject()
                .getAsJsonObject("geometry")
                .getAsJsonObject("location");
        double lat = location.get("lat").getAsDouble();
        double lng = location.get("lng").getAsDouble();
        return new LatLng(lat, lng);
    } else {
        throw new RuntimeException("Geocode failed: " + json.get("status").getAsString());
    }
}

// 2. 修改showMap方法,直接传入经纬度
public void showMap(LatLng latLng) {
    WebEngine webEngine = mapView.getEngine();
    
    String mapHTML = "<html style='height:100%;margin:0;padding:0;'>" +
            "<head>" +
            "<script src=\"https://maps.googleapis.com/maps/api/js?key=API_KEY\"></script>" +
            "<script>" +
            "function initMap() {" +
            "  var mapOptions = {" +
            "    zoom: 15," +
            "    center: new google.maps.LatLng(" + latLng.getLat() + ", " + latLng.getLng() + ")," +
            "    mapTypeId: google.maps.MapTypeId.ROADMAP" +
            "  };" +
            "  var map = new google.maps.Map(document.getElementById('map'), mapOptions);" +
            "  new google.maps.Marker({" +
            "    position: new google.maps.LatLng(" + latLng.getLat() + ", " + latLng.getLng() + ")," +
            "    map: map" +
            "  });" +
            "}" +
            "</script>" +
            "</head>" +
            "<body style='height:100%;margin:0;padding:0;' onload='initMap()'>" +
            "<div id='map' style='width:100%;height:100%;'></div>" +
            "</body>" +
            "</html>";
    
    webEngine.loadContent(mapHTML);
}

(注:需自行实现LatLng类,包含getLat()和getLng()方法)

3. 额外注意事项

  • 确保Google API Key已启用Maps JavaScript API和Geocoding API,且未超出配额限制。
  • 使用Java 11及以上版本的JavaFX,较旧版本对现代JavaScript支持不足。

内容的提问来源于stack exchange,提问作者Mia

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 05:10:03