Java - Implement SWT Text Input selection by "mouseDoubleClick event"

在這邊將探討如何在SWT Text輸入元件下,自行定義selection的行為在mouse double click的情況之下,因為Text在double click內容時,預設的行為會是整段資料做全選的動作!

相關程式碼如下:
  1. import org.eclipse.swt.SWT;
  2. import org.eclipse.swt.events.MouseAdapter;
  3. import org.eclipse.swt.events.MouseEvent;
  4. import org.eclipse.swt.graphics.Font;
  5. import org.eclipse.swt.graphics.FontData;
  6. import org.eclipse.swt.layout.GridData;
  7. import org.eclipse.swt.layout.GridLayout;
  8. import org.eclipse.swt.widgets.Display;
  9. import org.eclipse.swt.widgets.Shell;
  10. import org.eclipse.swt.widgets.Text;
  11. public class TextInputSelection {
  12. public static void main(String[] args) {
  13. // TODO Auto-generated method stub
  14. Display display = new Display();
  15. Shell shell = new Shell(display);
  16. shell.setText("Text Selection");
  17. shell.setLayout(new GridLayout(1, false));
  18. shell.setSize(400, 300);
  19. Text input = new Text(shell, SWT.BORDER);
  20. input.setText("00:00:00");
  21. input.setDoubleClickEnabled(false);
  22. GridData grid = new GridData(SWT.LEFT, SWT.TOP, false, false, 1, 1);
  23. grid.widthHint = 100;
  24. grid.heightHint = 30;
  25. input.setLayoutData(grid);
  26. FontData fontData = input.getFont().getFontData()[0];
  27. fontData.setHeight(16);
  28. Font font = new Font(display, new FontData(fontData.getName(), fontData.getHeight(), SWT.NONE));
  29. input.setFont(font);
  30. input.setForeground(display.getSystemColor(SWT.COLOR_GRAY));
  31. input.addMouseListener(new MouseAdapter() {
  32. public void mouseDoubleClick(MouseEvent e) {
  33. Text input = (Text) e.widget;
  34. String text = input.getText();
  35. int curPos = input.getCaretPosition();
  36. if(curPos == text.length()) {
  37. return;
  38. }
  39. int start = text.lastIndexOf(":", curPos);
  40. int end = text.indexOf(":", curPos);
  41. start = (start == -1) ? 0 : start + 1;
  42. end = (end == -1) ? text.length() : end;
  43. System.out.println("mouseDoubleClick..."+start+", "+end);
  44. input.setSelection(start, end);
  45. }
  46. });
  47. shell.open();
  48. while (!shell.isDisposed()) {
  49. if (!display.readAndDispatch())
  50. display.sleep();
  51. }
  52. font.dispose();
  53. display.dispose();
  54. }
  55. }

在此將說明的是,為何需要呼叫setDoubleClickEnabled且指定為false
查了一下Text的source code,若設定該method為false,在Text內doubleClick全域變數set為false,如此一來method WM_LBUTTONDBLCLK內原本預設的double click行為將被disable,看這樣子Text double click會全選的行為似乎是windows本身定義好的!
相關註解如下,詳見org.eclipse.swt.widgets.Text:
/*
* Prevent Windows from processing WM_LBUTTONDBLCLK
* when double clicking behavior is disabled by not
* calling the window proc.
*/

因此若我們沒有setDoubleClickEnabled為flase,如此一來我們定義的event mouseDoubleClick在呼叫getCaretPosition時,不管是在哪個cursor position做click的動作,最後它都會跳到尾端且進行全選的動作,如此一來在計算start and end就會得到錯誤的值!

相反地,若setDoubleClickEnabled為false,則getCaretPosition就會回傳當下我click的cursor position位置!

最後DEMO如下:
當我選起00:00:00,只要我的cursor在00的左側及中間點擊都會選擇起來,而若是右側的話則會選起其右側的冒號!

補充一下:
1. 如何將Text輸入框設大一點
可以調整其LayoutData的widthHint and heightHint,在此是Grid Layout
2. 如何將Text text size設大一點
需要new Font來進行重畫的動作

留言