如何从 Handwritten JavaScript 调用 GWT 实例对象的 java 方法?

How to call with a java method of a GWT instance object from Handwritten JavaScript?

我想调用 GWT 对象的方法(打开 GWT 弹出窗口、刷新屏幕或向 GWT 对象发送事件)。 我想知道如何将 GWT 对象的实例放入我的 JavaScript 代码中。

我将 GWT 2.8 与 JSInterop 结合使用。我知道如何创建一个新实例,但我想获得一个已经创建的实例。

在您的 Java 代码中,将实例的方法存储在 public 位置,例如 $wnd.myInstance。稍后,在 Java 脚本代码中,您可以使用 window.myInstance().

访问它

官方 GWT 文档中有一个 complete example 用于静态方法。如果您需要它用于非静态方法,它应该可以进行微小的更改。

  1. GWT 不创建 DOM Element -> GWT Widget 类型的链接,仅创建 GWT Widget -> DOM ElementGWT Widget -> GWT Widget 类型的链接。
  2. 也没有机会在 javascript 代码中直接创建 GWT Widget。如果你想要它,你必须用 JsInterop API 创建一个包装器 class。 示例:

    package com.Whosebug.questions52609313.client;
    
    import com.google.gwt.user.client.ui.PopupPanel;
    import jsinterop.annotations.JsMethod;
    import jsinterop.annotations.JsPackage;
    import jsinterop.annotations.JsType;
    
    @JsType(namespace = JsPackage.GLOBAL, name = "GwtPopupPanel")
    public class PopupPanelJsWrapper {
       private PopupPanel popupPanel = new PopupPanel();
    
    
       @JsMethod
       public void hide() {
           popupPanel.hide();
       }
    
       @JsMethod
       public void show() {
           popupPanel.show();
       }
    }
    

    在 javascript 中使用这个 class:

    var popupPanel = new GwtPopupPanel();
    popupPanel.show();
    popupPanel.hide();
    

考虑到第 1 项,您必须从 Java 到 Java 编写变量的脚本代码。有几种方法:

  • 通过全局状态(全局变量)传输
  • 通过方法参数传递

我创建了简单的 gwt maven 项目来展示这些方法。该项目包含在构建过​​程中运行并使用 HtmlUnit javascript 调用的测试。

项目结构:

JsInterop class MyClass:

package com.Whosebug.questions52609313.client;

import jsinterop.annotations.JsIgnore;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsProperty;
import jsinterop.annotations.JsType;

@JsType(namespace = JsPackage.GLOBAL)
public class MyJsClass {
    @JsProperty
    private String value;
    @JsIgnore
    private int callCounter = 0;

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }


    public String myMethod() {
        callCounter++;
        return "ok";
    }

    public int getCallCounter() {
        return callCounter;
    }
}

Class 全局状态 GlobalVariableExtension

package com.Whosebug.questions52609313.client;

import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsType;

@JsType(isNative = true, namespace = JsPackage.GLOBAL, name = "window")
public class GlobalVariableExtension {
    public static MyJsClass myGlobalVariable;
}

注意:namespaceJsPackage.GLOBALname"window"

我们的包装器 PopupPanelJsWrapper:

package com.Whosebug.questions52609313.client;

import com.google.gwt.user.client.ui.PopupPanel;
import jsinterop.annotations.JsMethod;
import jsinterop.annotations.JsPackage;
import jsinterop.annotations.JsType;

@JsType(namespace = JsPackage.GLOBAL, name = "GwtPopupPanel")
public class PopupPanelJsWrapper {
    private PopupPanel popupPanel = new PopupPanel();


    @JsMethod
    public void hide() {
        popupPanel.hide();
    }

    @JsMethod
    public void show() {
        popupPanel.show();
    }
}

测试classMainTestGwt:

package com.Whosebug.questions52609313.test;

import com.google.gwt.junit.client.GWTTestCase;
import com.Whosebug.questions52609313.client.GlobalVariableExtension;
import com.Whosebug.questions52609313.client.MyJsClass;


public class MainTestGwt extends GWTTestCase {


    @Override
    public String getModuleName() {
        return "com.Whosebug.questions52609313.test";
    }


    private native String passToJs(MyJsClass myVar)/*-{
        myVar.value = "random";
        return myVar.myMethod();
    }-*/;

    public void testPassToJs() {
        MyJsClass toJs = new MyJsClass();
        toJs.setValue("start");
        toJs.myMethod();
        assertEquals("start", toJs.getValue());
        assertEquals(1, toJs.getCallCounter());

        String ok = passToJs(toJs);
        assertEquals("ok", ok);

        assertEquals("random", toJs.getValue());
        assertEquals(2, toJs.getCallCounter());
    }

    private native MyJsClass createFromJs()/*-{
        var myVar = new $wnd.MyJsClass();
        myVar.value = "random";
        myVar.myMethod();
        return myVar;
    }-*/;

    public void testCreateFromJs() {
        MyJsClass fromJs = createFromJs();

        assertNotNull(fromJs);
        assertEquals("random", fromJs.getValue());
        assertEquals(1, fromJs.getCallCounter());
    }

    private native MyJsClass extractGlobalVariable()/*-{
        return $wnd.myGlobalVariable;
    }-*/;

    public void testExtensionGlobal() {

        GlobalVariableExtension.myGlobalVariable = null;
        MyJsClass myJsClassResultNull = extractGlobalVariable();

        assertNull(myJsClassResultNull);

        String qwerty = "qwerty";
        MyJsClass myJsClass = new MyJsClass();
        myJsClass.setValue(qwerty);
        GlobalVariableExtension.myGlobalVariable = myJsClass;
        MyJsClass myJsClassResult = extractGlobalVariable();

        assertNotNull(myJsClassResult);
        assertEquals(myJsClass, myJsClassResult);
        assertEquals(qwerty, myJsClassResult.getValue());

    }
    private native void popupPanelAction()/*-{
        var popupPanel = new $wnd.GwtPopupPanel();
        popupPanel.show();
        popupPanel.hide();


    }-*/;
    public void testCreatePopupPanel(){
        //expect without exceptions
        popupPanelAction();
    }

}

GwtMapsTestSuite:

package com.Whosebug.questions52609313.test;

import com.google.gwt.junit.tools.GWTTestSuite;
import junit.framework.Test;
import junit.framework.TestCase;

public class GwtMapsTestSuite extends TestCase {
    public static Test suite() {
        GWTTestSuite suite = new GWTTestSuite("Test for a Maps Application");
        suite.addTestSuite(MainTestGwt.class);
        return suite;
    }
}

client.gwt.xml:

<module>
    <source path='client'/>
</module>

test.gwt.xml:

<module>
    <inherits name='com.google.gwt.user.User'/>
    <inherits name='com.google.gwt.logging.Logging'/>
    <!-- Logging Configuration -->
    <set-property name="gwt.logging.enabled" value="TRUE"/>
    <set-property name="gwt.logging.logLevel" value="ALL"/>

    <inherits name="com.Whosebug.questions52609313.client"/>
    <source path='test'/>


</module>

pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.Whosebug</groupId>
    <artifactId>questions52609313</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <gwt.version>2.8.0</gwt.version>
        <junit.version>4.12</junit.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>

        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-dev</artifactId>
            <version>${gwt.version}</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.google.gwt</groupId>
            <artifactId>gwt-user</artifactId>
            <version>${gwt.version}</version>
            <scope>provided</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>gwt-maven-plugin</artifactId>
                <version>${gwt.version}</version>
                <configuration>
                    <logLevel>INFO</logLevel>
                    <noServer>false</noServer>
                    <extraJvmArgs>-Xmx1024m</extraJvmArgs>
                    <mode>htmlunit</mode>
                    <testTimeOut>300</testTimeOut>
                    <productionMode>true</productionMode>
                    <generateJsInteropExports>true</generateJsInteropExports>
                </configuration>
                <executions>
                    <execution>
                        <goals>
                            <goal>test</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>