如何在JavaFX WebView中从Java传JS对象给JS函数显示谷歌地图标记
我之前做过JavaFX WebView集成Google Maps的项目,刚好碰到过类似的Java传JS对象的问题,给你整理一套完整的解决方案,一步步来:
一、先完善前端HTML/JS代码
你提供的JS代码没写完,先把地图初始化逻辑补全,确保setMarker函数能正确接收坐标对象:
<!DOCTYPE html> <html> <head> <style> #map { height: 900px; width: 100%; } </style> <!-- 替换成你自己的Google Maps API密钥 --> <script src="https://maps.googleapis.com/maps/api/js?key=YOUR_GOOGLE_API_KEY"></script> </head> <body> <div id="map"></div> <script> var map; // 初始化地图 function initMap() { map = new google.maps.Map(document.getElementById('map'), { center: {lat: 39.9042, lng: 116.4074}, // 默认设为北京坐标,可按需修改 zoom: 10 }); } // 接收JS对象参数,创建地图标记 function setMarker(coord) { new google.maps.Marker({ position: coord, map: map, title: '自定义标记' // 可按需添加标记标题 }); } // 页面加载完成后自动初始化地图 window.addEventListener('load', initMap); </script> </body> </html>
二、JavaFX端实现:从数据库取坐标+传递JS对象给前端
核心是利用JavaFX的WebEngine和netscape.javascript.JSObject来创建JS可识别的对象,避免直接传Java对象导致的兼容问题。
1. 完整Java示例代码
import javafx.application.Application; import javafx.concurrent.Worker; import javafx.scene.Scene; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; import netscape.javascript.JSObject; import java.sql.Connection; import java.sql.DriverManager; import java.sql.ResultSet; import java.sql.Statement; public class MapMarkerApp extends Application { @Override public void start(Stage primaryStage) { WebView webView = new WebView(); WebEngine webEngine = webView.getEngine(); // 加载本地HTML文件(替换成你的文件路径,也可以加载远程URL) webEngine.load(getClass().getResource("/map.html").toExternalForm()); // 等待页面完全加载后再执行数据库查询和JS调用 webEngine.getLoadWorker().stateProperty().addListener((obs, oldState, newState) -> { if (newState == Worker.State.SUCCEEDED) { // 从数据库读取坐标数据(替换成你的数据库连接信息和查询逻辑) try (Connection conn = DriverManager.getConnection( "jdbc:mysql://localhost:3306/your_database", "your_username", "your_password" ); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("SELECT latitude, longitude FROM marker_points")) { // 获取JS全局对象(window) JSObject jsWindow = (JSObject) webEngine.executeScript("window"); while (rs.next()) { double lat = rs.getDouble("latitude"); double lng = rs.getDouble("longitude"); // 创建JS格式的坐标对象:{lat: xxx, lng: xxx} JSObject jsCoord = (JSObject) webEngine.executeScript("({})"); jsCoord.setMember("lat", lat); jsCoord.setMember("lng", lng); // 调用前端的setMarker函数,传递JS对象参数 jsWindow.call("setMarker", jsCoord); } } catch (Exception e) { e.printStackTrace(); } } }); Scene scene = new Scene(webView, 1200, 950); primaryStage.setTitle("JavaFX Google Maps Marker"); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch(args); } }
2. 备选方案:用JSON字符串传递
如果不想依赖JSObject,也可以把Java坐标对象转成JSON字符串,再在JS里解析:
// 先引入Gson或Jackson库,这里用Gson举例 import com.google.gson.Gson; // ... 省略其他代码 ... // 在数据库查询循环里: double lat = rs.getDouble("latitude"); double lng = rs.getDouble("longitude"); // 把坐标转成JSON字符串 Gson gson = new Gson(); String coordJson = gson.toJson(new Coordinate(lat, lng)); // 调用JS函数,传递JSON并解析 webEngine.executeScript("setMarker(JSON.parse('" + coordJson + "'))"); // 对应的Coordinate类 class Coordinate { public double lat; public double lng; public Coordinate(double lat, double lng) { this.lat = lat; this.lng = lng; } }
三、关键注意事项
- 必须等页面加载完成(
Worker.State.SUCCEEDED)再调用JS函数,否则map对象还未初始化会报错。 - 数据库操作建议放在JavaFX的后台
Task中执行,避免阻塞UI线程(示例为了简洁直接放在回调里,实际项目要优化)。 - JavaFX 11+版本需要在模块路径中包含
javafx.web模块,运行时要配置正确的模块依赖。
内容的提问来源于stack exchange,提问作者Egor
相关产品推荐
相关产品推荐

