Java: фильтрация повторяющихся событий - PullRequest
4 голосов
/ 27 февраля 2010

Мне было интересно, распространено ли следующее для "обычных" Java-приложений при получении обратного вызова / событий. Эти обратные вызовы могут быть вызваны пользовательским вводом, но также и другими способами, так что он не только связан с событиями пользовательского интерфейса:

public void handleEvent( @NotNull final SomeEvent e ) {
    final boolean process;
    synchronized ( this ) {
        process = !e.equals(filter);
        filter = e;
    }
    if ( process ) {
        ...   
    }
}

В основном по какой-то сложной схеме (очень сложный пользовательский интерфейс, включающий несколько видов одной и той же модели и где пользователь может изменять модель с разных экранов [как в сложных 3D-программах]). У меня много событий, и я заметил, что я могу отфильтровать повторяющиеся события, используя приведенный выше фрагмент. Если событие было обработано и следующее событие, которое наступит, точно совпадает с последним обработанным событием (сохраненным в ссылке filter), то событие / обратный вызов просто игнорируется.

Работает нормально. Мне было интересно, была ли фильтрация повторяющихся событий распространенной техникой?

Ответы [ 3 ]

2 голосов
/ 27 февраля 2010

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

Хотя то, что вы сделали, отфильтрует эти события, оно не решает фундаментальную проблему.

Проблема в том, что эти "ошибки" могут объединяться в бесконечные циклы. Расширяя приведенный выше пример bean-компонента, скажем, у вас есть пользовательский интерфейс, который сбрасывает его редактируемое значение на основе этого поля bean-компонента ... и сброс значения UI также вызовет установщик bean-компонента, потому что там не была проведена надлежащая проверка на наличие дублирования. При первом редактировании значения происходит бесконечный цикл.

Эти примеры очевидны, когда они случаются, но по мере усложнения иерархии уведомлений становится все труднее отследить эти вещи, и они потенциально могут происходить в более прерывистое время.

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

1 голос
/ 27 февраля 2010

Похоже, вы могли дважды зарегистрировать слушателя на одном и том же источнике. Это может вызвать это. Или, возможно, вы зарегистрировали одного слушателя в нескольких экземплярах. Если вы видите странность, ищите бесконечные циклы событий, которые, к сожалению, из-за того, как программы Swing организуются, могут происходить слишком легко. Вы захотите разбить этих слушателей на части.

Я никогда такого не делал и не сталкивался с этим. Как отмечают некоторые люди, определенные элементы управления будут запускать события при корректировке выбора, но есть методы для фильтрации этих вещей.

Синхронизированный (этот) блок тоже подозрительный, так как вы всегда будете вызываться в потоке Swing. Если это не так в вашей программе, то вы нарушаете правило потоков Swing, и это может объяснить проблему. Суть в том, что вам не нужен синхронизированный блок, потому что Swing является однопоточным.

(я предполагаю, что это Swing, как и некоторые другие постеры, но только из вашего кода это неоднозначно).

1 голос
/ 27 февраля 2010

Единственное, о чем я могу думать, это действовать на ListSelectionEvent в зависимости от того, меняется ли выбор по-прежнему (то есть пользователь все еще щелкает и перетаскивает мышь) или представляет ли событие «окончательное» событие выбора; например,

public class MyListSelectionListener implements ListSelectionListener {
  public void valueChanged(ListSelectionEvent evt) {
    // Finished selecting
    if (!evt.getValueIsAdjusting()) {
      JOptionPane.showMessageDialog("Selection Complete!");
    }
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...