javascript - 执行脚本Webview JavaFx

标签 javascript java swing google-maps javafx-webengine

这是我的浏览器 JFrame:

public class Browser extends JFrame {

private final JFXPanel jfxPanel = new JFXPanel();
private WebEngine engine;

private final JPanel panel = new JPanel(new BorderLayout());
private final JLabel lblStatus = new JLabel();

private final JButton btnGo = new JButton("Go");
private final JTextField txtURL = new JTextField();
private final JProgressBar progressBar = new JProgressBar();

public Browser() {
    super();
    initComponents();
}

private void initComponents() {
    createScene();

    ActionListener al = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            loadURL(txtURL.getText());
        }
    };

    btnGo.addActionListener(al);
    txtURL.addActionListener(al);

    progressBar.setPreferredSize(new Dimension(150, 18));
    progressBar.setStringPainted(true);

    JPanel topBar = new JPanel(new BorderLayout(5, 0));
    topBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
    topBar.add(txtURL, BorderLayout.CENTER);
    topBar.add(btnGo, BorderLayout.EAST);

    JPanel statusBar = new JPanel(new BorderLayout(5, 0));
    statusBar.setBorder(BorderFactory.createEmptyBorder(3, 5, 3, 5));
    statusBar.add(lblStatus, BorderLayout.CENTER);
    statusBar.add(progressBar, BorderLayout.EAST);

    panel.add(topBar, BorderLayout.NORTH);
    panel.add(jfxPanel, BorderLayout.CENTER);
    panel.add(statusBar, BorderLayout.SOUTH);

    getContentPane().add(panel);

    setPreferredSize(new Dimension(1024, 600));
    setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
    pack();

}

private void createScene() {

    Platform.runLater(new Runnable() {
        @Override
        public void run() {

            WebView view = new WebView();
            engine = view.getEngine();

            engine.titleProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> observable, String oldValue, final String newValue) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            Browser.this.setTitle(newValue);
                        }
                    });
                }
            });

            engine.setOnStatusChanged(new EventHandler<WebEvent<String>>() {
                @Override
                public void handle(final WebEvent<String> event) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            lblStatus.setText(event.getData());
                        }
                    });
                }
            });

            engine.locationProperty().addListener(new ChangeListener<String>() {
                @Override
                public void changed(ObservableValue<? extends String> ov, String oldValue, final String newValue) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            txtURL.setText(newValue);
                        }
                    });
                }
            });

            engine.getLoadWorker().workDoneProperty().addListener(new ChangeListener<Number>() {
                @Override
                public void changed(ObservableValue<? extends Number> observableValue, Number oldValue, final Number newValue) {
                    SwingUtilities.invokeLater(new Runnable() {
                        @Override
                        public void run() {
                            progressBar.setValue(newValue.intValue());
                        }
                    });
                }
            });

            engine.getLoadWorker()
                    .exceptionProperty()
                    .addListener(new ChangeListener<Throwable>() {

                        public void changed(ObservableValue<? extends Throwable> o, Throwable old, final Throwable value) {
                            if (engine.getLoadWorker().getState() == FAILED) {
                                SwingUtilities.invokeLater(new Runnable() {
                                    @Override
                                    public void run() {
                                        JOptionPane.showMessageDialog(
                                                panel,
                                                (value != null)
                                                        ? engine.getLocation() + "\n" + value.getMessage()
                                                        : engine.getLocation() + "\nUnexpected error.",
                                                "Loading error...",
                                                JOptionPane.ERROR_MESSAGE);
                                    }
                                });
                            }
                        }
                    });

            jfxPanel.setScene(new Scene(view));
        }
    });
}

public void loadURL(final String url) {
    Platform.runLater(new Runnable() {
        @Override
        public void run() {
            File file = new File(url);
            URL url;
            try {
                url = file.toURI().toURL();

                engine.getLoadWorker().stateProperty().addListener(
                        new ChangeListener<State>() {
                    public void changed(ObservableValue ov, State oldState, State newState) {
                        if (newState == State.SUCCEEDED) {
                            engine.executeScript("addPoint(0,-26.487000,151.984000)");
                        }
                    }
                });
                engine.load(url.toString());
            } catch (MalformedURLException ex) {
                Logger.getLogger(Browser.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    });
}
}

这是我的 HTML:

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">

<title>Heatmaps</title>
<style>
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }

    #map {
        height: 100%;
    }
</style>
</head>

<body>
<div id="map"></div>
<script>
    var map;
    var points = [];
    var markers = [];

    function initMap() {
        map = new google.maps.Map(document.getElementById('map'), {
            zoom: 13,
            center: new google.maps.LatLng(-27.487000, 152.984000),
        });
    }

    function addPoint(id, latitude, longitude) {
        markers[id] = new google.maps.Marker({
            draggable: false,
            animation: google.maps.Animation.DROP,
            position: new google.maps.LatLng(latitude, longitude),
            map: map
        });
        var bounds = new google.maps.LatLngBounds();
        markers.forEach(x => {
            bounds.extend(x.getPosition());
        })
        map.fitBounds(bounds);
    }
</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyBp0GrBi5GE3OPPgEm7WdStGH7A2tGuaHk&libraries=visualization&callback=initMap">
</script>

我正在实现一个程序,该程序有一个按钮来加载数据并将其显示为 Google map 中的标记。

我使用Brower的构造函数来传递URL

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {                                         
    Browser browser = new Browser();
    browser.setVisible(true);
    browser.loadURL("C:/Users/User/Desktop/test.html");
}   

并使用函数addPoint添加标记,但后来我得到了这个错误:

Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: ReferenceError: Can't find variable: addPoint

有没有办法从我的java代码中调用方法loadUrl中的函数addPoint,然后加载浏览器?

最佳答案

简短的回答是“你有一个时间问题”。 JavaFx WebEngine 正在误导您。问题是您异步加载谷歌地图 api。 JavaFx加载了html页面,但此时maps对象并未加载。

所以你有两个选择。第一个是,java 正在加载谷歌地图和标记。第二个是,当加载 map 时,javascript 调用 java。

1 个 java 调用全部的示例:

engine.getLoadWorker().stateProperty().addListener(
        new ChangeListener<State>() {
            public void changed(ObservableValue ov, State oldState, State newState) {
                if (newState == State.SUCCEEDED) {
                    //engine.executeScript("addPoint(0,-26.487000,151.984000)");
                    JSObject win = (JSObject) engine.executeScript("window");
                    win.setMember("javaObj", new Bridge(engine));
                    engine.executeScript("javaObj.start()");                                    }
            }
        });
engine.load(url.toString());

新的Bridge.java 导入javafx.scene.web.WebEngine;

public class Bridge {

    private WebEngine engine;

    public Bridge(WebEngine engine) {
        this.engine = engine;
    }

    public void addPoint(String id, String latitude, String longitude) {
        System.out.println("adding value");
        engine.executeScript(""
                + "var id=\"" + id + "\";"
                + "var latitude=\"" + latitude + "\";"
                + "var longitude=\"" + longitude + "\";"
                + "var markers=[];"
                + "markers[id] = new google.maps.Marker({\n"
                + "            draggable: false,\n"
                + "            animation: google.maps.Animation.DROP,\n"
                + "            position: new google.maps.LatLng(latitude, longitude),\n"
                + "            map: map\n"
                + "        });\n"
                + "        var bounds = new google.maps.LatLngBounds();\n"
                + "         var index;\n"
                + "         for (index = 0; index < markers.length; ++index) {\n"
                + "             bounds.extend(markers[index].getPosition());\n"
                + "         } "
                + "        map.fitBounds(bounds);");
    }

    public void doAddPoint() {
        addPoint("0", "-26.487000", "151.984000");
    }

    public void call() {
        engine.executeScript("addPoint(0,-26.487000,151.984000)");
    }

    public void log(String text) {
        System.out.println("log: " + text);
    }

    public void initMap() {
        engine.executeScript(""
                + "var map;"
                //                + "javaObj.log(\"hier0\");"
                + "map = new google.maps.Map(document.getElementById('map'), {\n"
                + "            zoom: 13,\n"
                + "            center: new google.maps.LatLng(-27.487000, 152.984000),\n"
                + "        });\n"
                //                + "javaObj.log(\"hier\");"
                + "javaObj.doAddPoint();"
        );
    }

    public void start() {
        engine.executeScript("var s = document.createElement(\"script\");\n"
                + "                          s.type = \"text/javascript\";\n"
                + "                            s.src = \"https://maps.googleapis.com/maps/api/js?key=AIzaSyBp0GrBi5GE3OPPgEm7WdStGH7A2tGuaHk&libraries=visualization&callback=javaObj.initMap\";\n"
                + "                            $(\"head\").append(s);");

    }
}

基本 HTML 页面:

<!DOCTYPE html>
<html>
<head id="test">
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<script
  src="https://code.jquery.com/jquery-2.2.4.min.js"
  integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
  crossorigin="anonymous"></script>
<title>Heatmaps</title>
<style>
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }

    #map {
        height: 100%;
    }
</style>
</head>
<body>
<p><b>test</b></p>
<div id="map"></div>
</body>
</html>

2 的示例: 对 Browser.java 的更改

engine.getLoadWorker().stateProperty().addListener(
    new ChangeListener<State>() {
        public void changed(ObservableValue ov, State oldState, State newState) {
            if (newState == State.SUCCEEDED) {
                //engine.executeScript("addPoint(0,-26.487000,151.984000)");
                JSObject win = (JSObject) engine.executeScript("window");
                win.setMember("javaObj", new Bridge(engine));
             }
        }
    });
engine.load(url.toString());

新的Bridge.java

public class Bridge {

    private WebEngine engine;

    public Bridge(WebEngine engine) {
        this.engine = engine;
    }
    public void call() {
        //System.out.println("do call");
        engine.executeScript("addPoint(0,-26.487000,151.984000)");
    }
}

对 html 页面的更改:

var initMap =function() {
    map = new google.maps.Map(document.getElementById('map'), {
        zoom: 13,
        center: new google.maps.LatLng(-27.487000, 152.984000),
    });
    javaObj.call();
}

PS:JQuery仅用于加载谷歌地图脚本和调试。我不知道谷歌地图API,所以我不知道为什么 map 放大那么多,但这是另一个问题。

关于javascript - 执行脚本Webview JavaFx,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40155567/

相关文章:

java - JLabel 与 JFrame 不完全一致

javascript - react-native-google-places-autocomplete 给它一个值而不仅仅是默认(初始)值

javascript - 用于解析的正则表达式无法正常工作

java - 如何使用 hibernate 在不迭代的情况下将 List<Object> 插入数据库?

java - 通过在递归方法中将 1 加到 N/2 并将 N/2 加到 N 来计算和 1 到 N

java - 我不希望 JTable 用省略号截断文本

javascript - 如何创建类似 'wheel of fortune' 的效果

javascript - 用字符串中的第一个连字符拆分字符串

java - 使用 JNI 将数据类型从 Java 传递到 C(反之亦然)

java - 为什么按钮/标签/文本未在我的背景上显示/居中?