最近,我做了一些SWT定制小部件的开发,偶然发现了一个问题, 为什么没有默认的SWT鼠标单击侦听器? 由于这个主题有时会提出,所以我认为写一两句话来说明背后的理性基础以及如何实现鼠标单击通常不会受到伤害。

SWT鼠标请点击

事件驱动的窗口小部件工具箱通常区分低级事件和语义事件。 低电平事件表示窗口系统出现或低电平输入。 鼠标和键盘输入基本上属于此组。

语义事件又是控件特定的用户交互的结果,并且可能由一个或多个低级事件组成。 例如,可以将按钮单击指定为鼠标下移,然后将其指定为鼠标上 移,而鼠标不会离开控件边界

问题的关键是控件特定的用户交互 可以将图像单击指定为鼠标下移,然后单击鼠标上移而不离开图像特定区域的边界。 差别不大,但意义重大。

语义事件类型SWT.Selection例如,对应于上面为org.eclipse.swt.widgets.Button控件提供的按钮单击规范。 但是它的组成在org.eclipse.swt.widgets.Slider上却大不相同。 后者的行为很像图像单击定义:

SWT鼠标单击实现

显然,没有人愿意为每个控件区域上的鼠标单击事件添加特定的侦听器。 这是更舒适的基础上那些低级别的赛事有一个语义抽象,对关键点或兴趣通知观察者1

单击按钮以自定义小部件

那么,按钮单击事件实现在自定义SWT小部件的(子)组件上看起来如何? 例如,考虑一个由几个标签Composite ,无论出于何种原因,其中一个标签都应作为动作触发。

点击行为可以通过在SWT类型化事件抽象之上运行一个小的动作包装器来实现。 它可以实现/扩展org.eclipse.swt.events.MouseListener/-MouseAdapter并且可以在控件上注册以用作按钮单击侦听器:

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 ,该Runnable应该通过单击观察到的控件来触发。 为此,第一步是验证是否已按下鼠标左键,并标记观察者已准备好触发 一个简单的mouseDown实现可能如下所示:

public static final int LEFT_BUTTON = 1;
[...]
public void mouseDown( MouseEvent event ) {
  if( event.button == LEFT_BUTTON ) {
    armed = true;
  }
}

第二步是检查是否在受监视的控件范围内发生了随后的mouseUp事件。 如果这样(并准备好),则语义条件已经满足并且可以触发该动作2

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上的“按钮单击”事件,如以下代码片段所示:

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鼠标单击实现

包起来

如上所述,SWT省略通用鼠标单击实现是有充分的理由的。 给出的示例显示了如何为自定义窗口小部件实现简单的按钮单击语义。 但是,还有更多需要考虑的地方。 小部件通常会在视觉上对鼠标按下做出反应 ,例如,表明它们已准备好触发。

因此,自定义窗口小部件代码很快就被炸毁,并趋于模糊与事件相关的各种责任。 为了将事件语义与视觉效果代码完全区分开,我通常在小助手类中提取第一个。 我什至有一个用于ButtonClick -click事件的通用版本,称为ButtonClick ,它是Xiliary P2存储库的SWT实用程序功能的一部分。

如果所有与鼠标单击相关的内容引起了对鼠标单击的实际应用的需求:如何使用下面的社交按钮共享知识?

  1. 细心的读者可能已经意识到,我忽略了滑块的拖动区域,该区域也增加了选择语义。 这是因为它与单击行为不匹配,并且将超出本讨论的范围。
  2. 值得一提的是,现实世界中的实现应确保在action.run()期间抛出运行时异常的情况下,也重置武装标志。

翻译自: https://www.javacodegeeks.com/2014/12/swt-mouse-click-implementation.html

相关文章: