1

目标

我正在尝试为 EclipseText控件实现“选择焦点”行为:

  • 当控件已经聚焦时:

    • 单击和拖动行为正常
  • 当控件没有聚焦时:

    • 单击并拖动以选择文本行为正常

    • 单击而不选择文本将选择所有文本

    • 使用键盘给予焦点将选择所有文本

问题

  • 通过鼠标单击聚焦时,仅选择所有文本SWT.FocusIn不会选择文本。

  • SWT.FocusIn之前 被触发SWT.MouseDown,因此当用户按下鼠标时,无法判断控件是否已经获得焦点。

问题

  1. 为什么 Eclipse 按该顺序触发事件?这对我来说没有任何意义。这是对某些支持的操作系统的限制吗?

  2. 是否有一些解决方法可以用来实现此功能?

4

1 回答 1

4

#eclipse 中有人将我链接到很久以前提出的一个 Eclipse 错误:Can't use focus listener to select all text

使用那里的建议之一,我想出了以下解决方案(在 Windows 中有效,在其他平台上未经测试):

/**
 * This method adds select-on-focus functionality to a {@link Text} component.
 * 
 * Specific behavior:
 *  - when the Text is already focused -> normal behavior
 *  - when the Text is not focused:
 *    -> focus by keyboard -> select all text
 *    -> focus by mouse click -> select all text unless user manually selects text
 * 
 * @param text
 */
public static void addSelectOnFocusToText(Text text) {
  Listener listener = new Listener() {

    private boolean hasFocus = false;
    private boolean hadFocusOnMousedown = false;

    @Override
    public void handleEvent(Event e) {
      switch(e.type) {
        case SWT.FocusIn: {
          Text t = (Text) e.widget;

          // Covers the case where the user focuses by keyboard.
          t.selectAll();

          // The case where the user focuses by mouse click is special because Eclipse,
          // for some reason, fires SWT.FocusIn before SWT.MouseDown, and on mouse down
          // it cancels the selection. So we set a variable to keep track of whether the
          // control is focused (can't rely on isFocusControl() because sometimes it's wrong),
          // and we make it asynchronous so it will get set AFTER SWT.MouseDown is fired.
          t.getDisplay().asyncExec(new Runnable() {
            @Override
            public void run() {
              hasFocus = true;
            }
          });

          break;
        }
        case SWT.FocusOut: {
          hasFocus = false;
          ((Text) e.widget).clearSelection();

          break;
        }
        case SWT.MouseDown: {
          // Set the variable which is used in SWT.MouseUp.
          hadFocusOnMousedown = hasFocus;

          break;
        }
        case SWT.MouseUp: {
          Text t = (Text) e.widget;
          if(t.getSelectionCount() == 0 && !hadFocusOnMousedown) {
            ((Text) e.widget).selectAll();
          }

          break;
        }
      }
    }

  };

  text.addListener(SWT.FocusIn, listener);
  text.addListener(SWT.FocusOut, listener);
  text.addListener(SWT.MouseDown, listener);
  text.addListener(SWT.MouseUp, listener);
}
于 2012-04-06T20:28:07.440 回答