通过将Java对象发送到JavaScript,从javascript向javaFX发送文本

时间:2017-01-16 14:21:50

标签: javascript json javafx webview

编辑: 添加用于鼠标点击的事件处理程序并在webview上滚动将有助于解决此问题。我的问题是当缩放或点击(平移)对象寡妇改变时。

         browser.addEventHandler(MouseEvent.MOUSE_CLICKED,
                new EventHandler<MouseEvent>() {
                    @Override public void handle(MouseEvent e) {
                    jsobj.setMember("java", new Bridge());
                    e.consume();
                    }
        });


        browser.setOnScroll(new EventHandler<ScrollEvent>() {
            @Override public void handle(ScrollEvent event) {
                jsobj.setMember("java", new Bridge());
                event.consume();
            }
        });

这方面似乎有很多问题和答案,但我不能用它们来解决这个问题。

https://docs.oracle.com/javase/8/javafx/embedded-browser-tutorial/js-javafx.htm

Invoke java using JavaScript inside JavaFX. Is it possible?)*

使用JavaFx WebView ...

我正在尝试向Java发送JavaScript个对象,而不是让JavaScript发送object或运行Java方法。

我正在等待......

if (newState == Worker.State.SUCCEEDED)

创建java对象并将其发送给JavaScript?

JSObject jsobj = (JSObject) browser.getEngine().executeScript("window");
                        jsobj.setMember("java", new Bridge());

什么是窗口功能?

编辑:

这是最小版本。

HTML

<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
  html { height: 100% }
  body { height: 100%; margin: 0px; padding: 0px }
  #map_canvas { height: 100%; background-color: #666970; }
</style>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false">
</script>
<script type="text/javascript">

  function initialize() {
    var latlng = new google.maps.LatLng(40.7128, -74.0059);
    var myOptions = {
      zoom: 14,
      center: latlng,
      mapTypeId: google.maps.MapTypeId.HYBRID,
      mapTypeControl: false,
      navigationControl: false,
      streetViewControl: false,
      backgroundColor: "#666970"
    };

    document.addMarker = function addMarker(x, y, name) {

        var latlng = new google.maps.LatLng(x, y);

        var marker = new google.maps.Marker({
          label: name,
          position: latlng,
          map: document.map
        });

        marker.addListener('click', function() {
         java.exit2();
        });

      }

    document.geocoder = new google.maps.Geocoder();
    document.map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);

  }
</script>
</head>
<body onload="initialize()">
  <div id="map_canvas" style="width:100%; height:100%"></div>
</body>
</html>

的java:

package application;

import java.net.URL;

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.concurrent.Worker;
import javafx.concurrent.Worker.State;
import javafx.stage.Stage;
import netscape.javascript.JSObject;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);

            WebView browser = new WebView();
            URL url = getClass().getResource("map.html");
            browser.getEngine().load(url.toExternalForm());
            root.setCenter(browser);

            browser.getEngine().getLoadWorker().stateProperty().addListener(
                    new ChangeListener<State>() {
                      @Override public void changed(ObservableValue ov, State oldState, State newState) {
                          if (newState == Worker.State.SUCCEEDED) {

                            browser.getEngine().executeScript(
                                    "document.addMarker("
                                            //lat
                                            +"40.7128"+","
                                            //long
                                            +"-74.0059"+","
                                            //marker name
                                            +"'"+"new_york"+"'"
                                            +")"
                                    );  

                            JSObject jsobj = (JSObject) browser.getEngine().executeScript("window");
                            jsobj.setMember("java", new Bridge());
                          }

                    }
             });

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public class Bridge{
        public void exit2() {
            System.out.println("test");
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}

尝试运行程序时出现此错误。如上所述。

如果我将javafx发送命令的line 41更改为javascript,那么“name”会被"'"包围。它不会发送错误,但它从不调用java类

如......

错误且未显示标签 - &gt; +"new_york"

无错误 - 显示标签但是,调用java类不起作用 - &gt; +"'"+"new_york"+"'"

如果我完全删除名称arg,则一切正常。但我需要标签上的文字,即从java发送到JavaScript。

错误:

Exception in thread "JavaFX Application Thread" netscape.javascript.JSException: ReferenceError: Can't find variable: new_york
    at com.sun.webkit.dom.JSObject.fwkMakeException(JSObject.java:137)
    at com.sun.webkit.WebPage.twkExecuteScript(Native Method)
    at com.sun.webkit.WebPage.executeScript(WebPage.java:1473)
    at javafx.scene.web.WebEngine.executeScript(WebEngine.java:982)
    at application.Main$1.changed(Main.java:34)
    at application.Main$1.changed(Main.java:1)
    at com.sun.javafx.binding.ExpressionHelper$SingleChange.fireValueChangedEvent(ExpressionHelper.java:182)
    at com.sun.javafx.binding.ExpressionHelper.fireValueChangedEvent(ExpressionHelper.java:81)
    at javafx.beans.property.ReadOnlyObjectPropertyBase.fireValueChangedEvent(ReadOnlyObjectPropertyBase.java:74)
    at javafx.beans.property.ReadOnlyObjectWrapper.fireValueChangedEvent(ReadOnlyObjectWrapper.java:102)
    at javafx.beans.property.ObjectPropertyBase.markInvalid(ObjectPropertyBase.java:112)
    at javafx.beans.property.ObjectPropertyBase.set(ObjectPropertyBase.java:146)
    at javafx.scene.web.WebEngine$LoadWorker.updateState(WebEngine.java:1260)
    at javafx.scene.web.WebEngine$LoadWorker.dispatchLoadEvent(WebEngine.java:1371)
    at javafx.scene.web.WebEngine$LoadWorker.access$1200(WebEngine.java:1253)
    at javafx.scene.web.WebEngine$PageLoadListener.dispatchLoadEvent(WebEngine.java:1240)
    at com.sun.webkit.WebPage.fireLoadEvent(WebPage.java:2434)
    at com.sun.webkit.WebPage.fwkFireLoadEvent(WebPage.java:2278)
    at com.sun.webkit.network.URLLoader.twkDidFinishLoading(Native Method)
    at com.sun.webkit.network.URLLoader.notifyDidFinishLoading(URLLoader.java:844)
    at com.sun.webkit.network.URLLoader.lambda$didFinishLoading$99(URLLoader.java:835)
    at com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Unknown Source)

1 个答案:

答案 0 :(得分:0)

JavaScript中的marker变量的JSON中存在错误:

    var marker = new google.maps.Marker({
      label: name;
      position: latlng,
      map: document.map
    });

应该是

    var marker = new google.maps.Marker({
      label: name,
      position: latlng,
      map: document.map
    });

此外,您要求Web引擎加载HTML后,在之后在Web引擎上注册侦听器。您无法保证在加载完成时将安装侦听器(如果加载非常快,则可以在安装侦听器之前完成,因此不会调用侦听器)。同样,在附加回调之前,您正在执行脚本。这是你的Main类的一个版本,它具有更符合逻辑的代码排序(为了简单和可读性,我也进行了清理):

package application ;

import java.net.URL;

import javafx.application.Application;
import javafx.concurrent.Worker;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import netscape.javascript.JSObject;


public class Main extends Application {
    @Override
    public void start(Stage primaryStage) {
        try {
            BorderPane root = new BorderPane();
            Scene scene = new Scene(root,400,400);

            WebView browser = new WebView();
            root.setCenter(browser);

            browser.getEngine().getLoadWorker().stateProperty().addListener((ov, oldState, newState) -> {
                  if (newState == Worker.State.SUCCEEDED) {

                      JSObject jsobj = (JSObject) browser.getEngine().executeScript("window");
                      jsobj.setMember("java", new Bridge());

                      // document.addMarker(latitude, longitude, markerName) :
                      String script = "document.addMarker(40.7128, -74.0059, 'new_york')";

                      browser.getEngine().executeScript(script);  

                  }
            });

            URL url = getClass().getResource("map.html");
            browser.getEngine().load(url.toExternalForm());

            primaryStage.setScene(scene);
            primaryStage.show();
        } catch(Exception e) {
            e.printStackTrace();
        }
    }

    public class Bridge{
        public void exit2() {
            System.out.println("test");
        }
    }
    public static void main(String[] args) {
        launch(args);
    }
}