java - 从 Java 代码将事件发送到 JavaFx webview 节点/元素

标签 java webview webkit click javafx

我需要在网络浏览器上自动执行重复的操作。 为此,我需要执行诸如从 Java 代码向网页发送点击和其他输入之类的操作。

Element e = document.getElementById("someid");
com.sun.webpane.webkit.dom.MouseEventImpl.MouseEventImpl mei = MouseImplExpose.makeSimpleClickDummy(e);
((EventTarget)e).dispatchEvent(mei);

MouseImplExpose 在哪里

package com.sun.webpane.webkit.dom;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

public class MouseImplExpose {
    public static MouseEventImpl makeDummy(Node n){
       // required jdk 7 update 40 ! This function is
        // not available in jdk 7 update 10 :O
        return new MouseEventImpl(((NodeImpl)n).peer );
    }

    public static MouseEventImpl makeSimpleClickDummy(Node n/*, Document d*/){
        //d.getD

        MouseEventImpl impl = new MouseEventImpl(((NodeImpl)n).peer );
        // some fictional values
        impl.initMouseEvent(
                "click", 
                true, 
                true, 

                null, 
                1, 
                958, 
                318, 
                718, 
                208, 
                false, 
                false, 
                false, 
                false, 
                (short)0, 
                (NodeImpl)n);
        return impl;
        // this is how a real MouseEventImpl generated 
        // internally looks :
        /*evt=com.sun.webpane.webkit.dom.MouseEventImpl@ad3b429
        typeArg=click
        canBubbleArg=true
        cancelableArg=true
        viewArg=[object DOMWindow]
        detailArg=1
        screenXArg=958
        screenYArg=318
        clientXArg=718
        clientYArg=208
        ctrlKeyArg=false
        altKeyArg=false
        shiftKeyArg=false
        metaKeyArg=false
        buttonArg=0
        relatedTargetArg=[object HTMLDivElement]*/
    }
}

我从 native 端收到 org.w3c.dom.events.EventException。

我确信一定有一种更简单的方法来做到这一点......

任何提示、提示、指南、链接、评论将不胜感激。 谢谢


我发现这种替代方法有效

System.out.println(webEngine.executeScript("var evt = document.createEvent(\"MouseEvents\");\n"+
"                evt.initMouseEvent(\"click\", true, true, window, 1, 0, 0, 0, 0,\n" +
"                    false, false, false, false, 0, null);\n" +
"\n" +
"                var cb = document.getElementById(\"TheIdOfElementWeWishToClick\");\n" +
"                cb.dispatchEvent(evt);"
+ "%"));

之前我尝试过

System.out.println(webEngine.executeScript("document.getElementById(\"TheIdOfElementWeWishToClick\").click();");

这不起作用,因为“.click()”不适用于 。

最佳答案

建议的解决方案

我建议使用jQuery to trigger the click via the webengine.executeScript() function .

示例代码

import javafx.application.Application;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
import org.w3c.dom.Document;

/** 
 * Embeds jQuery in a document loaded into a WebView.
 * Uses jQuery to run an animation to hide each link in the document as it is clicked.
 */
public class JQueryWebView extends Application {
  public static final String DEFAULT_JQUERY_MIN_VERSION = "1.7.2";
  public static final String JQUERY_LOCATION = "http://code.jquery.com/jquery-1.7.2.min.js";
  public static void main(String[] args) { launch(args); }
  @Override public void start(Stage primaryStage) {
    final WebView webView = new WebView();
    final WebEngine engine = webView.getEngine();
    engine.load("http://docs.oracle.com/javafx/2/get_started/animation.htm");
    engine.documentProperty().addListener(new ChangeListener<Document>() {
      @Override public void changed(ObservableValue<? extends Document> prop, Document oldDoc, Document newDoc) {
        executejQuery(
          engine, 
          "$(\"a\").click(function(event){" +
          "  event.preventDefault();" +
          "  $(this).hide(\"slow\");" +
          "});"
        );
      }
    });
    primaryStage.setScene(new Scene(webView));
    primaryStage.show();
  }

  /**
   * Enables Firebug Lite for debugging a webEngine.
   * @param engine the webEngine for which debugging is to be enabled.
   */
  private static void enableFirebug(final WebEngine engine) {
    engine.executeScript("if (!document.getElementById('FirebugLite')){E = document['createElement' + 'NS'] && document.documentElement.namespaceURI;E = E ? document['createElement' + 'NS'](E, 'script') : document['createElement']('script');E['setAttribute']('id', 'FirebugLite');E['setAttribute']('src', 'https://getfirebug.com/' + 'firebug-lite.js' + '#startOpened');E['setAttribute']('FirebugLite', '4');(document['getElementsByTagName']('head')[0] || document['getElementsByTagName']('body')[0]).appendChild(E);E = new Image;E['setAttribute']('src', 'https://getfirebug.com/' + '#startOpened');}"); 
  }

  /**
   * Executes a script which may reference jQuery function on a document.
   * Checks if the document loaded in a webEngine has a version of jQuery corresponding to 
   * the minimum required version loaded, and, if not, then loads jQuery into the document 
   * from the default JQUERY_LOCATION.
   * @param engine the webView engine to be used.
   * @Param jQueryLocation the location of the jQuery script to be executed.
   * @param minVersion the minimum version of jQuery which needs to be included in the document.
   * @param script provided javascript script string (which may include use of jQuery functions on the document).
   * @return the result of the script execution.
   */ 
  private static Object executejQuery(final WebEngine engine, String minVersion, String jQueryLocation, String script) {
    return engine.executeScript(
      "(function(window, document, version, callback) { "
        + "var j, d;"
        + "var loaded = false;"
        + "if (!(j = window.jQuery) || version > j.fn.jquery || callback(j, loaded)) {"
        + "  var script = document.createElement(\"script\");"
        + "  script.type = \"text/javascript\";"
        + "  script.src = \"" + jQueryLocation + "\";"
        + "  script.onload = script.onreadystatechange = function() {"
        + "    if (!loaded && (!(d = this.readyState) || d == \"loaded\" || d == \"complete\")) {"
        + "      callback((j = window.jQuery).noConflict(1), loaded = true);"
        + "      j(script).remove();"
        + "    }"
        + "  };"
        + "  document.documentElement.childNodes[0].appendChild(script) "
        + "} "
      + "})(window, document, \"" + minVersion + "\", function($, jquery_loaded) {" + script + "});"
    );
  }
  private static Object executejQuery(final WebEngine engine, String minVersion, String script) {
    return executejQuery(engine, DEFAULT_JQUERY_MIN_VERSION, JQUERY_LOCATION, script);
  }

  private Object executejQuery(final WebEngine engine, String script) {
    return executejQuery(engine, DEFAULT_JQUERY_MIN_VERSION, script);
  }
}

附带建议

不建议在用户代码中使用 com.sun 包中的类,因为这些 API 不能保证在 Java 版本之间保持稳定,因此,如果您使用 com.sun API,那么您的应用程序可能无法工作尝试针对不同的 Java 版本运行它。

关于java - 从 Java 代码将事件发送到 JavaFx webview 节点/元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19304713/

相关文章:

firefox - 面具在 Gecko 中不起作用

javascript - 在呈现和绘制 HTML 页面时生成的帧

android - 使用 webview 显示地理位置

jquery - 如何使用 jQuery 判断 CSS3 动画处于哪个阶段?

java - 如何过滤 endeca (ATG) 记录(/浏览页面)

java - 如何扩展Java的SWT标签?

Java:替换第一个位置上除符号 "+"之外的所有非数字符号

java - 如何在 Java2D 中旋转矩形

android - 当使用 webview 启动 Activity 时,应用程序崩溃并显示 "Fatal signal 5 (SIGTRAP), code 1 in tid 13058 (Chrome_InProcRe)"

Java - WebView 什么事件处理(监视)URL 更改 - Android