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

标签 java gwt jsni

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

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

最佳答案

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

    package com.stackoverflow.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 中使用这个类:

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

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

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

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

项目结构:

project

JsInterop 类 MyClass:

package com.stackoverflow.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;
    }
}

全局状态类 GlobalVariableExtension

package com.stackoverflow.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.GLOBAL 并且 name"window"

我们的包装器PopupPanelJsWrapper:

package com.stackoverflow.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();
    }
}

测试类MainTestGwt:

package com.stackoverflow.questions52609313.test;

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


public class MainTestGwt extends GWTTestCase {


    @Override
    public String getModuleName() {
        return "com.stackoverflow.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.stackoverflow.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.stackoverflow.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.stackoverflow</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>

关于java - 如何从手写 JavaScript 调用 GWT 实例对象的 java 方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52609313/

相关文章:

java - Android 用两根手指点击 MapView

java - Spring-Hateoas Traverson 如何从三个表中获取信息

javascript - GWT 如何在不点击按钮的情况下每 5 分钟自动刷新页面?

java - eclipse 中的 GWT 项目

gwt - 将 Java 数组传递到 JavaScript(通过 JSNI)并返回到 Java 结果为空值

java - 使用 Tomcat 的 Eclipse 中的 HTTP 状态 404 错误

java - 如何使用 getRGB 在 java 中获取图像的像素值数组

tomcat - 从 Amazon EC2 上的 CherryPy 网络服务检索数据时出现 CONNECTION_TIMED_OUT 错误

java - 我的 GWT 应用程序没有运行 JSNI 调用的 native 功能。有接盘者吗?

java - GWT 和 JSNI 将 Javascript 按钮添加到 HTML 面板中