通过gwt jsni传递java对象时出错

4uqofj5v  于 2021-07-03  发布在  Java
关注(0)|答案(2)|浏览(382)

我有一个gwt项目,它使用googlejavascript图表api来显示java对象的图表。我将java对象转换为json,并通过jsni将它们传递给javascript图表api,这非常有效。
但是现在我想更进一步,换一种方式:当我在一个图表中单击时(我可以通过javascript监听器检测到),我想把这个java对象发送回我的java代码。
我想我已经完成了jsni指南中的所有内容,但是当我单击图表时,javascript控制台中出现了一个错误,我甚至不知道如何读取:

SCRIPT5022: Exception thrown and not caught
File: eval code (21), Line: 5, Column: 7

__gwt_javaInvokes[2] =
  function(thisObj, dispId,p0,p1) {
    var result = __static(dispId, thisObj,p0,p1);
    if (result[0]) {
      throw result[1];
    } else {
      return result[1];
    }
  } function(thisObj, dispId,p0,p1) { var result = __static(dispId, thisObj,p0,p1); if (result[0]) { throw result[1]; } else { return result[1]; } }

这是我的html页面:

<!doctype html>
<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <link type="text/css" rel="stylesheet" href="GwtTest.css">
    <title>GWT Test</title>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript" language="javascript" src="gwttest/gwttest.nocache.js"></script>
  </head>
  <body>

  </body>
</html>

唯一有趣的是我添加了googlechartapi脚本标签。
下面是我试图从java传递到javascript,然后再传递回java的java对象:

package com.example.client;

public class ChartData {
    public String title = "test";

    public String labelOne = "thingOne";
    public String labelTwo = "thingTwo";
    public String labelThree = "thingThree";

    public int valueOne = 100;
    public int valueTwo = 200;
    public int valueThree = 300;
}

最后,这里是我的gwt客户机类:

package com.example.client;

import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.JsArray;
import com.google.gwt.core.client.JsonUtils;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.RootLayoutPanel;
import com.google.gwt.user.client.ui.SimplePanel;
import com.google.gwt.user.client.ui.VerticalPanel;

public class GwtTest implements EntryPoint {

    public void onModuleLoad() {

        RootLayoutPanel rootPanel = RootLayoutPanel.get();

        SimplePanel chartPanel = new SimplePanel();
        chartPanel.getElement().setId("chartDiv");
        chartPanel.setSize("500px", "500px");

        Button button = new Button("Click Me");
        button.addClickHandler(new ClickHandler(){

            @Override
            public void onClick(ClickEvent event) {
                ChartData chartData = new ChartData();
                String json = getChartJson(chartData);
                JsArray<?> chartArrayData = JsonUtils.safeEval(json);
                drawChart(chartArrayData, chartData);
            }
        });

        VerticalPanel vp = new VerticalPanel();
        vp.add(button);
        vp.add(chartPanel);

        rootPanel.add(vp);

        loadChartLibrary();
    }

    private String getChartJson(ChartData chartData){
        String json = "[";
        json += "[\"time\", \"" + chartData.title + "\"]";

        json += ",";
        json += "[\"" + chartData.labelOne + "\"," + chartData.valueOne + "]";

        json += ",";
        json += "[\"" + chartData.labelTwo + "\"," + chartData.valueTwo + "]";

        json += ",";
        json += "[\"" + chartData.labelThree + "\"," + chartData.valueThree + "]";

        json += "]";
        return json;
    }

    private native void loadChartLibrary()/*-{
        $wnd.google.charts.load('current', {packages: ['corechart']});
    }-*/;

    private native void drawChart(JsArray<?> dataArray, ChartData chartData)/*-{
        var data = $wnd.google.visualization.arrayToDataTable(dataArray);
        var chart = new $wnd.google.visualization.ColumnChart($wnd.document.getElementById('chartDiv'));
        chart.draw(data, null);

        $wnd.google.visualization.events.addListener(chart, 'select', selectHandler);

        function selectHandler(e) {
          var selectionArray = chart.getSelection();
          if(selectionArray.length == 0){

          }
          else{
            var row = selectionArray[0].row;
            console.log(row);
            this.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
            console.log("here");
          }
        }

    }-*/;

    public void printChartData(ChartData chartData, int i){
        System.out.println(i + ": " + chartData.valueThree);
    }
}

如果你运行这个代码,你应该看到一个按钮,说点击我。单击该按钮以显示图表。然后单击图表中的条形图。我希望这会触发我的java代码 printChartData() 函数,但是我在javascript控制台中得到了一个错误。
我已经将问题缩小到以下代码:

var row = selectionArray[0].row;
console.log(row);
this.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
console.log("here");

行被正确地打印到控制台,所以我知道我的javascript正在工作。但是后来 "here" 从未打印到控制台,所以我知道错误在我的jsni行中。
我的jsni设置有什么遗漏吗?javascript错误是什么意思?

dgenwo3n

dgenwo3n1#

我认为问题出在使用上 this 在处理器内部。你可能期望 this 作为…的示例 GwtTest 类,但在它指向处理程序的处理程序内部使用。这就是为什么 this.@com.example.client.GwtTest::printChartData 失败。
可以在处理程序外部声明变量并赋值 this 然后在处理程序中使用它。
尝试:

var instance = this;
function selectHandler(e) {
      var selectionArray = chart.getSelection();
      if(selectionArray.length == 0){

      }
      else{
        var row = selectionArray[0].row;
        console.log(row);
        instance.@com.example.client.GwtTest::printChartData(Lcom/example/client/ChartData;I)(chartData, row);
        console.log("here");
      }
    }
cidc1ykv

cidc1ykv2#

ChartData 没有延伸 JavaScriptObject ,所以它抛出一个 ClassCastException 当你打电话的时候 printChartData .
亚当也是对的。使用 this 处理程序内部不工作。。。
下面是一个示例,它是如何工作的,只需重写整个gwttest类。。

public class GwtTest implements EntryPoint {

private ChartData chartData;

public void onModuleLoad() {
    RootLayoutPanel rootPanel = RootLayoutPanel.get();
    SimplePanel chartPanel = new SimplePanel();
    chartPanel.getElement().setId("chartDiv");
    chartPanel.setSize("500px", "500px");
    Button button = new Button("Click Me");
    button.addClickHandler(new ClickHandler() {
        @Override
        public void onClick(ClickEvent event) {
            chartData= ChartData.createJSO("Time", "Time");
            for (int i = 0; i < 4; i++) {
                RowData row = RowData.createJSO("label" + i, 100 + i);
                chartData.add(row);
            }
            drawChart(chartData);
        }
    });
    VerticalPanel vp = new VerticalPanel();
    vp.add(button);
    vp.add(chartPanel);
    rootPanel.add(vp);
    loadChartLibrary();
}

public static class ChartData extends JavaScriptObject {
    protected ChartData() {
    }

    public static native ChartData createJSO(String chartname, String rowTypeDescriton) /*-{
        return [ [ chartname, rowTypeDescriton ] ];
    }-*/;

    public final native RowData get(int index) /*-{
        return this[index + 1];
    }-*/;

    public final native void add(RowData data) /*-{
        this[this.length] = data;
    }-*/;

}

public static class RowData extends JavaScriptObject {

    protected RowData() {
    }

    public static native RowData createJSO(String label, int value) /*-{
        return [ label, value ];
    }-*/;

    public final native String getLabelOne() /*-{
        return this[0];
    }-*/;

    public final native int getValueOne() /*-{
        return this[1];
    }-*/;

}

private native void loadChartLibrary()/*-{
    $wnd.google.charts.load('current', {
        packages : [ 'corechart' ]
    });
}-*/;

private native void drawChart(ChartData dataArray)/*-{
    var self = this;
    var data = $wnd.google.visualization.arrayToDataTable(dataArray);
    var chart = new $wnd.google.visualization.ColumnChart($wnd.document
            .getElementById('chartDiv'));
    chart.draw(data, null);
    $wnd.google.visualization.events.addListener(chart, 'select',
            selectHandler);
    function selectHandler(e) {
        var selection = chart.getSelection();
        for (var i = 0; i < selection.length; i++) {
            var item = selection[i];
            if (item.row != null) {
                self.@com.example.client.GwtTest::printChartData(I)(item.row);
            } 
        }
    }

}-*/;

public void printChartData(int row) {
    System.out.println(chartData.get(row));
}
}

相关问题