Как вызвать соответствующие методы Java (для каждой кнопки), написанные в одном классе обработчика событий в GWT?

Я хочу вызывать разные методы (которые находятся в одном классе обработчика событий GWT) при нажатии разных кнопок? Это так:

Скажем, у меня есть 3 кнопки в моем пользовательском интерфейсе:

  1. Кнопка1
  2. Кнопка2
  3. Кнопка3

И я прикрепил один и тот же (Click) EventHandler для каждого из них: ButtonClicker

И внутри метода OnClick() я хотел бы вызвать методы, соответствующие нажатой кнопке. Вот пример кода, чтобы лучше проиллюстрировать, что я пытаюсь сделать:

public class ButtonClicker implements ClickHandler 
{
    public void onClick(ClickEvent event)
    {
        PushButton clickedButton = (PushButton) event.getSource();

        // I could call the corresponding method using if-else condition but I do not want to do that. 
        // Instead, I want some code here, may be using JSNI (using eval in some way) or something like that to call the corresponding method.
        ......      
    }

    private void Button1Click()
    {
        // Code to handle Button1 Click 
    }

    private void Button2Click()
    {
        // Code to handle Button2 Click
    }

    private void Button3Click()
    {
        // Code to handle Button3 Click
    }
}

Заранее спасибо.


person user1730159    schedule 09.04.2013    source источник
comment
Почему вы маршрутизируете все это через один и тот же обработчик событий? Похоже, что это должны быть разные обработчики событий, возможно, подкласс абстрактного обработчика событий с общим кодом.   -  person Taylor    schedule 10.04.2013
comment
Я согласен с тем, что идеально вызывать/писать разные классы обработчиков событий для разных нажатий кнопок. Но мы хотим пойти по этому пути, где у нас будет один единственный класс обработчика событий. Мне было интересно, есть ли способ вызвать соответствующий метод с помощью JSNI или чего-то еще. Любые идеи, пожалуйста?   -  person user1730159    schedule 10.04.2013
comment
То, о чем вы просите, - это очень запутанный и нетрадиционный подход. Это может быть выполнимо с JSNI, но я не рекомендую это. Возможно, если вы объясните, что толкает вас на этот путь, мы сможем предложить лучший способ справиться со всем этим. Кроме того, когда вы говорите, что у вас есть Button1, Button2 и Button3, это классы? имена классов css? имена html-элементов?   -  person Taylor    schedule 10.04.2013
comment
Одна из причин заключается в том, что у меня есть по крайней мере 30+ (разных) кнопок в моем пользовательском интерфейсе, и я не хочу писать разные классы обработчиков событий для каждой из них. И в то же время я хочу избежать громоздкого оператора if-else, который я предвижу в описанном выше подходе.   -  person user1730159    schedule 10.04.2013
comment
Вам не нужен другой обработчик, но вы можете написать а) разные методы для каждого и б) разные вызовы button.addClickHandler плюс проверку для отправки на нужную кнопку? Вам это не кажется противоречивым?   -  person Colin Alworth    schedule 10.04.2013
comment
Для всех моих кнопок, когда я создаю их в цикле, я назначаю обработчик событий следующим образом: button.addClickHandler(new ButtonClicker());   -  person user1730159    schedule 10.04.2013
comment
Так почему бы не использовать классический способ закрытия? wrapper.addClickHandler(new ClickHandler() { public void onClick(ClickEvent event) { // Делайте с этой кнопкой все, что хотите } });   -  person Andrea Boscolo    schedule 10.04.2013
comment
В соответствии с нашими соглашениями по программированию, нам не разрешено замыкание :(   -  person user1730159    schedule 10.04.2013
comment
И вот что/как я ищу. Не уверен, что правильно, но ищу решение в следующих строках: Class ButtonClicker { public void onClick() { PushButton clickedButton = (PushButton) event.getSource(); callJavaMethod(clickedButton.getElement().getId()); } public static native void callJavaMethod(String javaMethodName) /*-{ eval('$wnd.'+ javaMethodName); }-*/; } где javaMethodName будет выглядеть как Button1Click() или Button2Click() и т. д....   -  person user1730159    schedule 10.04.2013


Ответы (1)


Я полагаю, у вас есть очень веские причины пойти по этому запутанному пути, поэтому вот предложение, без суждений:

JavaScriptObject map = createMap(this);

private static native JavaScriptObject createMap(ButtonClicker o) /*-{
   // Note: does not use $entry() as this will be called from GWT code
   return {
       "button1": function() { [email protected]::Button1Click()(); },
       "button2": function() { [email protected]::Button2Click()(); },
       "button3": function() { [email protected]::Button3Click()(); }
     };
}-*/;

private static native void call(JavaScriptObject map, String id) /*-{
  var fn = map[id];
  // TODO: add null-check / fallback behavior
  fn();
}-*/;

@Override
public void onClick(ClickEvent event) {
  call(map, ((UIObject) event.getSource()).getElement().getId());
}
person Thomas Broyer    schedule 10.04.2013
comment
Это сработало (за исключением небольшой заминки с методом вызова — требовалось обернуть тело этого метода между /* и */, так как это был нативный метод.) Не совсем уверен, какие накладные расходы это создает по сравнению с вызовом методов с помощью простого оператора if-else (или переключателя). В любом случае, спасибо за ваше время и решение. - person user1730159; 10.04.2013
comment
Исправлен метод call(), спасибо. Что касается накладных расходов по сравнению с цепочкой if/else, это будет зависеть от JS-движка браузера и количества случаев, но существенной разницы быть не должно. Обратите внимание, что поддержка Java7 должна появиться в следующей версии GWT, и вы сможете использовать strings-in-switch \o/ - person Thomas Broyer; 10.04.2013
comment
Спасибо @Том. В любом случае, просто интересно, возможно ли что-то подобное: (внутри createMap) var x = methodName; var y = 'function() { [email protected]::'+x+'()(); }'; Таким образом, мне не нужен неявный оператор switch (вид), как в приведенной выше функции createMap. - person user1730159; 10.04.2013
comment
Ах нет, невозможно. Кстати, вы знаете UiBinder и его @UiHandler, верно? - person Thomas Broyer; 10.04.2013
comment
Я знаю о UiBinder, но никогда им не пользовался. В любом случае, я думаю, я не могу пойти с этим, так как я думаю, что я должен использовать XML для создания пользовательского интерфейса, что у нас запрещено. - person user1730159; 10.04.2013
comment
Суждение внутри: никаких анонимных классов и никакого UiBinder? ваши стандарты кодирования отстой; стандарты кодирования должны быть направлены на то, чтобы все шли по одному и тому же пути, поэтому это не код одного или код другого (это просто код); это не должно ограничивать вашу выразительность и замедлять вас! - person Thomas Broyer; 11.04.2013