Пользовательские события GWT


Эй, у меня проблема с тем, как работают пользовательские обработчики событий GWT. Я прочитал довольно много о теме, и это все еще немного туманно. Я читал потоки здесь на Stackoverflow, как этот обработчик пользовательских событий GWT. Может ли кто-нибудь объяснить это в прикладном маннаре, таком как следующее.

У меня есть 2 классов и класс человек. Когда человек сталкивается с блоком, человек запускает событие (onCollision ()), а затем класс блока слушает это событие.

спасибо

4 66

4 ответа:

событий в целом:

события всегда отправляются, чтобы сообщить о чем-то (например, изменение состояния). Давайте возьмем Ваш пример с человеком и стеной. Здесь мы можем представить, что есть игра, где пользователь может ходить как человек в лабиринте. Каждый раз, когда пользователь ударяется о стену, он должен быть проинформирован о столкновении, чтобы он мог реагировать на него (например, стена может отображаться как разрушенная стена). Это может быть достигнуто путем отправки события столкновения, во время столкновения с стена обнаружена. Это событие отправляется человеком, и каждый объект в системе, заинтересованный в событии, получает его и может реагировать на него соответствующим образом. Объекты, которые хотят получать события, должны регистрироваться как заинтересованные в событии.

так события работают в целом в каждой системе или фреймворке (не только в GWT). Для отправки и получения событий в таких системах необходимо определить:

  1. что отправляется (как выглядят события)
  2. кто получает события (приемники событий)
  3. кто отправляет события (отправители событий)

затем вы можете:

  1. Регистрация приемников событий, которые хотят получать события
  2. отправить события

события в GWT:

здесь я покажу пример использования пользовательских событий в GWT. Я буду использовать пример системы, которая отвечает за проверку почтового ящика и сообщить пользователю, если есть новые письма. Предположим, что в системе есть как минимум 2 составляющие:

  • средство проверки сообщений отвечает за проверку почтового ящика и
  • диспетчер сообщений отвечает за отображение новых писем

средство проверки сообщений отправляет события при получении новой почты, а средство отображения сообщений получает эти события.

Шаг 1: Определите события

информация о новой почте будет отправлена как экземпляр MessageReceivedEvent класса. Класс содержит новый почта (для простоты предположим, что это просто String).

полный исходный код этого класса приведен ниже (комментарии ниже исходный код).

public class MessageReceivedEvent extends GwtEvent<MessageReceivedEventHandler> {

    public static Type<MessageReceivedEventHandler> TYPE = new Type<MessageReceivedEventHandler>();

    private final String message;

    public MessageReceivedEvent(String message) {
        this.message = message;
    }

    @Override
    public Type<MessageReceivedEventHandler> getAssociatedType() {
        return TYPE;
    }

    @Override
    protected void dispatch(MessageReceivedEventHandler handler) {
        handler.onMessageReceived(this);
    }

    public String getMessage() {
        return message;
    }
}

MessageReceivedEventHandler - это интерфейс, представляющий приемники событий. Не беспокойтесь об этом в данный момент, это будет обсуждаться позже.

каждый класс, представляющий событие GWT, должен расширяться GwtEvent класса. Этот класс содержит два абстрактных метода, которые должны быть реализованы:getAssociatedType и dispatch. Однако в каждом классе событий они обычно реализуются очень похожим образом.

класс хранит информацию о полученном сообщении (см. конструктор). Каждый приемник событий может получить его с помощью getMessage метод.

Шаг 2: Определите приемники событий

каждый тип событий в GWT связан с интерфейсом, представляющим приемники этого типа событий. В GWT приемники называются обработчиками. В Примере интерфейс приемника событий для MessageReceivedEvent . Исходный код приведен ниже:

public interface MessageReceivedEventHandler extends EventHandler {
    void onMessageReceived(MessageReceivedEvent event);
}

каждый обработчик должен продлить EventHandler интерфейс. Он также должен определить метод, который будет вызываться при возникновении события (он должен принимать хотя бы один параметр - событие). Здесь метод называется onMessageReceived. Каждый приемник может реагировать на событие, реализуя этот метод.

единственным приемником событий в примере является MessageDisplayer компоненты:

public class MessageDisplayer implements MessageReceivedEventHandler {

    @Override
    public void onMessageReceived(MessageReceivedEvent event) {
        String newMessage = event.getMessage();
        // display a new message
        // ...
    }

}

Шаг 3: определение события отправители

в Примере единственным отправителем события является компонент, ответственный за проверку почты -EventChecker:

public class MessageChecker implements HasHandlers {

    private HandlerManager handlerManager;

    public MessageChecker() {
        handlerManager = new HandlerManager(this);
    }

    @Override
    public void fireEvent(GwtEvent<?> event) {
        handlerManager.fireEvent(event);
    }

    public HandlerRegistration addMessageReceivedEventHandler(
            MessageReceivedEventHandler handler) {
        return handlerManager.addHandler(MessageReceivedEvent.TYPE, handler);
    }

}

каждый отправитель событий должен реализовать HasHandlers интерфейс.

наиболее важным элементом здесь является

поскольку этот вопрос и ответ от Piotr GWT добавили поддержку немного другого способа создания пользовательских событий. Эта реализация события является конкретной сборкой, которая будет использоваться с EventBus GWT в пакете com.google.web.bindery.event.shared. Пример построения пользовательского события для GWT 2.4:

import com.google.web.bindery.event.shared.Event;
import com.google.web.bindery.event.shared.EventBus;
import com.google.web.bindery.event.shared.HandlerRegistration;

/**
 * Here is a custom event. For comparison this is also a MessageReceivedEvent.
 * This event extends the Event from the web.bindery package.
 */
public class MessageReceivedEvent extends Event<MessageReceivedEvent.Handler> {

    /**
     * Implemented by methods that handle MessageReceivedEvent events.
     */
    public interface Handler {
        /**
         * Called when an {@link MessageReceivedEvent} event is fired.
         * The name of this method is whatever you want it.
         *
         * @param event an {@link MessageReceivedEvent} instance
         */
        void onMessageReceived(MessageReceivedEvent event);
    }

    private static final Type<MessageReceivedEvent.Handler> TYPE =
        new Type<MessageReceivedEvent.Handler>();

    /**
     * Register a handler for MessageReceivedEvent events on the eventbus.
     * 
     * @param eventBus the {@link EventBus}
     * @param handler an {@link MessageReceivedEvent.Handler} instance
     * @return an {@link HandlerRegistration} instance
     */
    public static HandlerRegistration register(EventBus eventBus,
        MessageReceivedEvent.Handler handler) {
      return eventBus.addHandler(TYPE, handler);
    }    

    private final String message;

    public MessageReceivedEvent(String message) {
        this.message = message;
    }

    @Override
    public Type<MessageReceivedEvent.Handler> getAssociatedType() {
        return TYPE;
    }

    public String getMessage() {
        return message;
    }

    @Override
    protected void dispatch(Handler handler) {
        handler.onMessageReceived(this);
    }
}

событие используется следующим образом:

чтобы зарегистрировать обработчик для этого события с помощью eventbus, вызовите метод статического регистра в MessageReceivedEvent класс:

MessageReceivedEvent.register(eventbus, new MessageReceivedEvent.Handler() {
   public void onMessageReceived(MessageReceivedEvent event) {
     //...do something usefull with the message: event.getMessage();
   }
});

теперь, чтобы запустить событие на вызове eventbus fireEvent С недавно построенным событием:

eventBus.fireEvent(new MessageReceivedEvent("my message"));

другая реализация может быть найдена в собственном GWT EntityProxyChange класс событий. Эта реализация использует альтернативный вариант EventBus. Он использует возможность добавлять обработчики, привязанные к определенному источнику, через addHandlerToSource и может быть вызван через eventBus.fireEventFromSource.

реализация события, приведенная здесь, также более подходит при работе с GWT деятельность.

Я создал свой собственный виджет, расширив составной класс GWT. Я хотел создать свое собственное событие в этом классе. Я хотел, чтобы события были доступны для редактора WindowBuilder GWT.

Я многому научился из ответов на этой странице, но мне пришлось внести некоторые изменения.

Я хотел начать с ответа Hilbrand Bouwkamp, потому что он был новее. Но я столкнулся с парой проблем. 1) этот ответ сделал ссылку на шину событий. Четный автобус является глобальным переменная, принадлежащая основной программе. Неясно, как библиотека виджетов может получить доступ к этому. 2) я не начинал с нуля. Я расширял код библиотеки GWT. Чтобы сделать эту работу, я должен был начать с класса GwtEvent, а не С класса Event.

ответ Петра по существу правильный, но он был очень длинным. Мой класс (косвенно) расширяет класс виджета GWT. Виджет заботится о многих деталях, таких как создание объекта HandlerManager. (Я посмотрел сквозь исходный код, и именно так работают стандартные виджеты, а не с помощью EventBus.)

мне нужно было только добавить две вещи в моем классе виджет, чтобы добавить пользовательский обработчик событий. Они показаны здесь:

public class TrackBar extends Composite {

    public HandlerRegistration addValueChangedHandler(TrackBarEvent.Handler handler)
    {
        return addHandler(handler, TrackBarEvent.TYPE); 
    }   

    private void fireValueChangedEvent()
    {
        final TrackBarEvent e = new TrackBarEvent(value);
        fireEvent(e);
    }

мое новое событие почти точно такое же, как класс событий Петра, показанный выше. Стоит отметить одну вещь. Я начал с getValue (), основываясь на этом примере. Позже я добавил getTrackBar (), чтобы дать гораздо больше информации. Если бы я начинал с нуля, я бы сосредоточился на последнее, а не первое. Полный класс событий показан ниже.

import com.google.gwt.event.shared.EventHandler;
import com.google.gwt.event.shared.GwtEvent;

public class TrackBarEvent extends GwtEvent< TrackBarEvent.Handler >
{
    public interface Handler extends EventHandler {
        void onTrackBarValueChanged(TrackBarEvent event);
    }

    static final Type<TrackBarEvent.Handler> TYPE =
            new Type<TrackBarEvent.Handler>();

    private final int value;

    public TrackBarEvent(int value) {
        this.value = value;
    }

    @Override
    public Type<TrackBarEvent.Handler> getAssociatedType() {
        return TYPE;
    }

    public int getValue() {
        return value;
    }

    public TrackBar getTrackBar()
    {
        return (TrackBar)getSource();
    }

    @Override
    protected void dispatch(Handler handler) {
        handler.onTrackBarValueChanged(this);
    }
}

Если вы случайно используете GWTP рамки поверх GWT, см. этот стек.

GWTP это " полная модель-представление-презентатор рамки для упрощения вашего следующего проекта GWT."