2

一般的な目的:javascriptから非静的javaメソッドを呼び出す

説明:JavaアプレットコードのDOMでgwtのウィジェットを検索し、そのjavaメソッドを呼び出す(静的ではない)


JSObject win = JSObject.getWindow(this);
JSObject doc = (JSObject) win.getMember("document");
JSObject gwtWidget = (JSObject) doc.call("getElementsByName", widgetName);

//todo: have possibility to call `exported` java method over here, smth like:
//Object[] params = new Object[1];
//params[0] = widgetName;
//Object result = gwtWidget.call("exportedJavaMethod", params);

//todo: or just call global ($wnd) static JSNI bridge method:
//Object result = win.call("exportedJavaMethod", params);
//

問題は次のとおりです。ウィジェットではなくウィジェットのIDで見つけることができますが、エクスポートされたインスタンス化されたメソッドがないのはDivElementです。

私のウィジェットクラスはエクスポート可能です(gwt-export):


@Export(value="somewidget")
public class SomeWidget extends SimplePanel implements ..., Exportable {
    private final String id = "id_some_widget_" + count++;
    private static int count = 0;

    public SomeWidget () {
        getElement().setAttribute("name", id);
        getElement().setId(id);
    }
    ...

    public static Element getInstanceById(String elementId) {
        Element someWidget= DOM.getElementById(elementId);
        return someWidget;
    }

    public String getSomeInstancedData() {
        return "useful_inner_data" + this.id;
    }

たとえば、DOMに追加された具体的なウィジェットを見つけてgetSomeInstancedData()、JavaScriptで非静的メソッドを呼び出したいと思います。それは可能ですか?

次のようなsmthを想定します。


var someWidget = document.getElementById(widgetId);
alert(someWidget.getSomeInstancedData());

//or:
var someWidgetExported = com.mypackage.widgets.somewidget.getInstanceById(listenerId);
alert(someWidgetExported.getSomeInstancedData());

基本モジュールでは、次のように記述します。


ExporterUtil.exportAll();

このウィジェットを含むView(ViewWithSomeWidget.ui.xml)があります:

..。
ベース:フォーム
base:SomeWidget ui:field ="someWidget"..。
..。
/ base:SomeWidget
..。

SomeWidgetがExportableを実装していない場合、プロジェクトは正常に実行されますが、見つかったウィジェットのDIV要素の非静的メソッドを呼び出すことができませんでした。

その時までに、問題を解決するために、SomeWidgetはExportableを実装しますが、遅延バインディングを使用するClassCastExceptionのため、progectはSomeWidgetでViewをうまく表示しません。


ClassCastException: com.mypackage.widgets.SomeWidgetExporterImpl cannot be cast to com.mypackage.widgets.SomeWidget

それで、おそらくウィジェットのjavascriptオブジェクトを見つけて、それをエクスポートされたjavaメソッドを呼び出す他のメソッドはありますか?いずれにせよ、どんなアイデアでも大歓迎です。

4

3 に答える 3

11

非静的メソッドを起動するjavascript関数を宣言できます。

例えば:

package com.example;
public class Layout extends VLayout() {
    private String nonStaticVar = "nonStaticVar";
    public Layout() {
        declareMethod(this);
    }

    //Method which declares non-static method in javascript
    public native void declareMethod(Layout layout) /*-{
        var layout = layout;
        $wnd.doSomething = function(someString) {
            layout.@com.example.Layout::doSomething(Ljava/lang/String;)(someString);
        }
    }-*/;

    //Non static method which is being called
    public String doSomething(String someString) {
        //Do something, e.g. set var in this instantiated class, or output stuff
        this.nonStaticVar = someString;
        Window.alert(someString);
    }
}

ここで、doSomething( "bla");を呼び出します。from javascriptは、非静的メソッドを呼び出します。

于 2012-09-03T15:04:36.713 に答える
4

ウィジェットメソッドを呼び出すことができる独自のjsmethodをdiv要素に定義できます

@Export(value="somewidget")
public class SomeWidget extends SimplePanel implements ..., Exportable {
    private final String id = "id_some_widget_" + count++;
    private static int count = 0;

    public SomeWidget () {
        getElement().setAttribute("name", id);
        getElement().setId(id);
        attachInstanceHook(getElement());
    }
    ...

    public String getSomeInstancedData() {
        return "useful_inner_data" + this.id;
    }


    private native void attachInstanceHook(Element element) /*-{
        var elem = element;
        var widget = this;
        elem.getWidgetData = function () {
            widget.@your.package.name.SomeWidget::getSomeInstancedData()();
        };

    }-*/;

jsコードは次のようになります。

var someWidget = document.getElementById(widgetId);  //the id of the div element
alert(someWidget.getWidgetData());
于 2012-09-21T07:29:12.997 に答える
1

DOM要素を介してウィジェットをフェッチする代わりに、最初にJavaインスタンスをグローバルスコープに挿入して参照します。

public class SomeWidget extends SimplePanel implements ..., Exportable {

    //...

    public SomeWidget () {
        getElement().setAttribute("name", id);
        getElement().setId(id);

        attachToGlobalScope(id, this);
    }

    private native void attachToGlobalScope(String id, SomeWidget instance) /*-{
        $wnd.shared[id] = instance;
    }-*/;

    //...
}

後で、アプレットAPIレイヤーの対応するフェッチを更新します。

JSObject win = JSObject.getWindow(this);
JSObject shared = (JSObject) win.getMember("shared");
Widget widgetRef = (Widget) shared.getMember(widgetId);

免責事項:このやや曲がったソリューションは、JavaScriptグローバルスコープ変数を中継します。これは一般的に悪い習慣と見なされますが、ここでは唯一の一般的なスコープとして機能するため、オブジェクトの保存に悪用されます。

于 2012-05-05T08:53:01.937 に答える