目标功能:
随便焦点的跳转(键盘的上下左右操作;键盘的PgUp、PgDown操作;鼠标的点击操作),得到焦点所在位置的Style信息。
StyledText可以添加TraverseListener, 表示对界面上的焦点移动的监听.
getStyledText().addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
}
});
一般的处理代码都是对event.detail进行判断,再进行对应的操作, 代码如下:
switch (event.detail) {
case SWT.TRAVERSE_NONE:
case SWT.TRAVERSE_ESCAPE:
case SWT.TRAVERSE_RETURN:
case SWT.TRAVERSE_TAB_PREVIOUS:
case SWT.TRAVERSE_TAB_NEXT:
case SWT.TRAVERSE_ARROW_PREVIOUS: // 上 或 左
case SWT.TRAVERSE_ARROW_NEXT: // 下 或 右
case SWT.TRAVERSE_MNEMONIC:
case SWT.TRAVERSE_PAGE_PREVIOUS:
case SWT.TRAVERSE_PAGE_NEXT:
}
但通过调试分析后发现:
event.keyCode
只监听 SWT.ARROW_LEFT, SWT.ARROW_RIGHT, SWT.ARROW_UP, SWT.ARROW_DOWN有效(也就是键盘上的上、下、左、右), 对于SWT.PAGE_UP, SWT.PAGE_DOWN都无效(也就是PgUp、PgDown按键)。
TraverseListener是不能用了, 因为PgUp、PgDown也会让界面的焦点移动,但却无法得到监听。于是,考虑换用
VerifyKeyListener 和
MouseListener的组合来完成该需求。
VerifyKeyListener
对StyledText界面上的按键进行监听。能监听所有的按键操作。
MouseListener
对界面上的鼠标按下、鼠标弹起等进行监听。
具体实现就比较简单了:
getStyledText().addMouseListener(new MouseAdapter() {
public void mouseUp(MouseEvent e) {
showCaretStyle();
}
});
getStyledText().addVerifyKeyListener(new VerifyKeyListener() {
public void verifyKey(VerifyEvent event) {
if (isTraverseKey(event.keyCode) {
showCaretStyle();
}
}
private boolean isTraverseKey(int keyCode) {
if (event.stateMask == 0) {
if (SWT.ARROW_LEFT == event.keyCode || SWT.ARROW_RIGHT == event.keyCode || SWT.ARROW_UP == event.keyCode || SWT.ARROW_DOWN == event.keyCode
|| SWT.PAGE_UP == event.keyCode || SWT.PAGE_DOWN == event.keyCode) {
return true;
}
}
return false;
}
});
protected void showCaretStyle() {
int caretOffset = dialog.getStyledText().getCaretOffset();
StyleRange beforeStyle = getCaretBeforeStyle(caretOffset);
System.out.println(beforeStyle);
}
private StyleRange getCaretBeforeStyle(int caretOffset) {
if (caretOffset > 0) {
caretOffset--;
}
StyleRange[] styleRanges = this.dialog.getStyledText().getStyleRanges(caretOffset, 1);
if (styleRanges.length > 0) {
return styleRanges[0];
} else {
return null;
}
}
但问题来了,因为:int caretOffset = dialog.getStyledText().getCaretOffset();得到的还是在焦点移动前的caretOffset,而不是焦点移动后的caretOffset,这也比较好理解,因为在MouseListener、VerifyKeyListener里面,焦点还没有移动呢,你当然只可以拿到移动前的caretOffset了。
解决方法:让得到Style的线程sleep(100)再去获得caretOffset,这样就可以得到焦点移动后的caretOffset了。关键代码如下:
Display.getCurrent().asyncExec(new Runnable() {
public void run() {
// 先等待100ms,让按键事件、鼠标点击事件先执行完成,焦点移动到新的位置上
try {
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
// 再得到新的焦点所在位置的Style信息
showCaretStyle();
}
});