StyledText 的Traverse,VerifyKey,MouseListener分析

目标功能:
    随便焦点的跳转(键盘的上下左右操作;键盘的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();
			}
		});

你可能感兴趣的:(thread,UP)