Статьи

SWT Mouse Click Реализация

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

SWT Mouse Click

Наборы управляемых событиями виджетов обычно различают низкоуровневые и семантические события. Низкоуровневое событие представляет события системы окон или ввод низкого уровня. Мышь и клавиатура относятся в основном к этой группе.

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

Суть вопроса заключается в контроле конкретного взаимодействия с пользователем . Щелчок по изображению может быть указан как нажатие кнопки мыши, за которой следует нажатие кнопки мыши, не выходя за границы определенных областей изображения. Что делает небольшую, но сильную разницу.

Семантический тип события SWT.Selection например, соответствует спецификации нажатия кнопки, приведенной выше для org.eclipse.swt.widgets.Button управления org.eclipse.swt.widgets.Button . Но его состав на org.eclipse.swt.widgets.Slider совсем другой. Последний ведет себя скорее как определение щелчка изображения:

щелчок мыши-на-слайдер

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

Нажатие кнопки для пользовательских виджетов

Итак, как может выглядеть реализация события нажатия кнопки на (под) компоненте пользовательского SWT-виджета? Рассмотрим, например, Composite состоящий из нескольких меток, и один из них — по любой причине — должен служить триггером действия.

Поведение щелчка может быть реализовано с помощью небольшой оболочки действий, работающей поверх типизированной абстракции события SWT . Он может реализовывать / расширять org.eclipse.swt.events.MouseListener/-MouseAdapter и может быть зарегистрирован в элементах управления, чтобы служить слушателем нажатия кнопки:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
static class ClickBehavior extends MouseAdapter {
 
  private final Runnable action;
 
  ClickBehavior( Runnable action ) {
    this.action = action;
  }
 
  @Override
  public void mouseDown( MouseEvent event ) {
    // TODO: decent implementation
  }
 
  @Override
  public void mouseUp( MouseEvent event ) {
    // TODO: decent implementation
  }
}

Как вы можете видеть, класс ClickBehavior оборачивает Runnable который должен запускаться нажатием на наблюдаемый элемент управления. Для этого первым шагом является проверка того, что произошло нажатие левой кнопки мыши, и указание наблюдателю на готовность к запуску . Простая реализация mouseDown может выглядеть так:

1
2
3
4
5
6
7
public static final int LEFT_BUTTON = 1;
[...]
public void mouseDown( MouseEvent event ) {
  if( event.button == LEFT_BUTTON ) {
    armed = true;
  }
}

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
public void mouseUp( MouseEvent event ) {
  if( armed && inRange( event ) ) {
    action.run();
  }
  armed = false;
}
 
static boolean inRange( MouseEvent event ) {
  Point size
    = ( ( Control )event.widget ).getSize();
  return    event.x >= 0
         && event.x <= size.x
         && event.y >= 0
         && event.y <= size.y;
}

Этой реализации достаточно, чтобы иметь возможность обрабатывать событие «нажатия кнопки», например, в org.eclipse.widgets.Label как показано в следующем фрагменте:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
final Shell shell = [...];
Label label = new Label( shell, SWT.NONE );
label.setText( "Click me!" );
label.addMouseListener(
  new ClickBehavior( new Runnable() {
 
  @Override
  public void run() {
    MessageBox box = new MessageBox( shell );
    box.setMessage( "Label was clicked." );
    box.setText( "Message" );
    box.open();
  }
 
} ) );

И вот, вот как это выглядит во время выполнения:

Наклейка нажмите

Заворачивать

Как объяснено выше, у SWT есть веские причины не использовать реализацию щелчком мыши общего назначения. И данный пример показал, как реализовать простую семантику нажатия кнопки для пользовательских виджетов. Однако есть еще что рассмотреть. Виджеты часто визуально реагируют на нажатие мыши, указывая, например, на то, что они готовы к срабатыванию.

Из-за этого пользовательский код виджета быстро взрывается и имеет тенденцию размывать ответственность, связанную с различными событиями. Для четкого отделения семантики событий от кода визуальных эффектов я обычно извлекаю первый в небольшом вспомогательном классе. У меня даже есть версия общего назначения для событий нажатия кнопки, называемая ButtonClick , которая является частью утилиты SWT репозитория Xiled P2 .

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

  1. Внимательный читатель, возможно, понял, что я опускаю область перетаскивания ползунка, что также добавляет семантику выбора. Это связано с тем, что оно не соответствует поведению щелчка и выходит за рамки данного обсуждения.
  2. Следует отметить, что реальная реализация должна гарантировать, что вооруженный флаг также сбрасывается в случае возникновения исключения во время action.run() во время action.run() .
Ссылка: Реализация клика мышью SWT от нашего партнера JCG Фрэнка Аппеля в блоге Code Affine