>Goal
我正在尝试为 Eclipse Text
控件实现"在焦点上选择"行为:
-
当控件已聚焦时:
- 单击和拖动行为正常
-
当控件未聚焦时:
-
单击并拖动以选择文本的行为正常
-
单击而不选择文本将选择所有文本
-
使用键盘给予焦点将选择所有文本
-
问题
-
仅选择
SWT.FocusIn
的所有文本不会在通过鼠标单击聚焦时选择文本。 -
SWT.FocusIn
在SWT.MouseDown
之前触发,因此无法判断当用户按下鼠标时控件是否已具有焦点。
问题
-
为什么 Eclipse 会按这个顺序触发事件?这对我来说没有任何意义。这是对某些受支持的操作系统的限制吗?
-
是否有一些解决方法可用于实现此功能?
#eclipse 中的某个人将我链接到很久以前提出的 Eclipse 错误:无法使用焦点侦听器选择所有文本
使用那里的建议之一,我想出了以下解决方案(适用于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);
}