熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> Java編程 >> Java開源技術 >> 正文

技術分享——開發Eclipse自定義控件

2013-11-23 20:08:47  來源: Java開源技術 

  現在基於 Eclipse 的應用越來越多很多桌面應用都是用Eclipse開發的Eclipse提供了一套 SWT/JFACE 的控件庫使得人們開發界面應用極大的方便但是SWT/JFACE的控件庫畢竟有限在應用開發是我們不可避免地要自己開發一些自定義的控件本文通過開發一個顏色列表控件的實例介紹了Eclipse自定義控件開發中所要用到的技術
  
  目標讀者必須熟悉Java開發並且有一定的Eclipse開發經驗
  
  在Eclipse網站上有一篇相關的文章Creating Your Own Widgets using SWT該文介紹了開發自己控件的很多基本概念方法並且通過實例進行了介紹非常好但是其所用的實例比較簡單還有很多控件開發中所要涉及到的內容例如鍵盤鼠標事件的處理滾動條焦點的處理等等沒有提及本文通過開發一個自定義的顏色列表控件的實例全面地介紹了自定義控件所涉及的技術同時讀者也可以對該實例進行擴展實現自己的列表控件
  
  SWT中提供的標准列表控件非常簡單只能提供字符串的選擇我們經常需要提供一些圖形列表供用戶選擇這就需要自己開發自定義的列表控件顏色選擇列表是我們常用的一種圖形列表我們就以此為例進行介紹以下是我們將要開發的顏色列表
  
  我們在開發自定義控件時主要考慮以下問題
  
   自定義控件的繪制通常我們需要自己對控件的形狀或圖案進行繪制
  
   控件對鍵盤事件的響應當焦點進入控件用戶進行鍵盤操作通過鍵盤對控件進行控制時我們需要讓控件對用戶的操作進行響應例如在列表中用戶會通過上下箭頭改變列表的選擇項
  
   控件對鼠標事件的響應當用戶用鼠標選中控件進行操作時控件必須作出相應的反應
  
   控件對焦點事件的響應當界面焦點進入或移出控件通常我們需要將控件繪制成得到或失去焦點的形狀例如當焦點進入列表時一般被選中的列表項會有虛框表示選中
  
   響應TAB鍵對於一個可操縱的控件用戶可以用TAB鍵將焦點移入或移出
  
   響應滾動條事件當控件有滾動條時我們需要響應用戶對滾動條的操作完成對控件的繪制工作
  
   提供事件監聽機制程序員使用你的控件時通常需要監聽控件中發生的一些事件這樣當事件發生時他們能夠進行相應處理
  
   提供輔助功能(Accessibility)輔助功能是方便殘障人士使用時必須的標准控件都會提供相應的支持我們自定義的控件也不例外
  
   提供功能接口方便程序員訪問通常為方便程序員使用時獲取控件中的信息或進行設置我們需要提供一些接口
  
  首先我們要開發的列表控件是一個基本控件所以我們選擇Canvas作為我們開發的基類
  
  public class ColorList extends Canvas {
  Vector colors = new Vector(); // 用於保存我們顏色控件中的顏色值
  Vector colorNames = new Vector(); // 用於保存顏色控件中的顏色名字
  
  int rowSel = ; // 用於保存當前選中的行號
  int oldRowSel = ; // 用於保存上一次選中的行號
  
  int maxX maxY; // 用於保存列表的寬度和高度
  int lineHeight; // 用於設置行高
  
  int cx = ; // 滾動條滾動後控件的圖形相對於控件可見區域左上角的x坐標
  int cy = ; // 滾動條滾動後控件的圖形相對於控件可見區域左上角的y坐標
  }
  
  控件開發最重要的就是控件的繪制了控件的繪制可以通過添加PaintListener在它的paintControl方法中進行
  
  addPaintListener(new PaintListener() {
  public void paintControl(PaintEvent e) {
  GC gc = egc;
  Point size = getSize();
  int beginx = ex;
  int beginy = (ey / lineHeight) * lineHeight;
  int beginLine = (ey cy) / lineHeight;
  int endLine = beginLine + eheight / lineHeight + ;
  if (endLine > getItemCount())
  endLine = getItemCount();
  for (int i = beginLine; i < endLine; i++) {
  boolean selected = false;
  if (i == rowSel)
  selected = true;
  onPaint(gc i cx beginy + (i beginLine) * lineHeight
  selected);
  }
  }
  });
  
  這裡要注意的是從PaintEvent中獲取的xyheightwidth是需要重繪的區域xy是以控件的左上角為原點的坐標在我們的程序中為了性能起見我們先根據需要重繪的區域計算出需要重繪的行數只重繪相應的行而不是將整個控件重繪我們程序中用到的onPaint用於繪制一行
  
  接下來我們要讓我們的控件響應鍵盤上下鍵對列表項進行選擇我們已對向上鍵的處理為例首先當用戶按了向上鍵時我們需要改變選擇並且重繪舊的和新的選擇項如果選擇項已經到了列表的頂部我們還需要同時滾動滾動條
  
  addListener(SWTKeyDown new Listener() {
  public void handleEvent(Event event) {
  switch (eventkeyCode) {
  case SWTARROW_UP: // 處理向上鍵
  if (rowSel != ) {
  oldRowSel = rowSel;
  rowSel;
  if (oldRowSel != rowSel) { //發送消息讓控件重繪
  ((Canvas) eventwidget)redraw(cx (rowSel + cy
  / lineHeight)
  * lineHeight maxX lineHeight* false);
  }
  if (rowSel < cy / lineHeight) { //如果需要滾動滾動條
  ScrollBar bar = ((Canvas) eventwidget)
  getVerticalBar();
  barsetSelection(bargetSelection() lineHeight);
  scrollVertical(bar);
  }
  selectionChanged(); // 發送selectionChanged事件
  }
  break;
  case SWTARROW_DOWN: // down arror key
  …
  break;
  }
  }
  });
  
  接下來我們要讓我們的控件響應鼠標對列表項進行選擇首先我們要計算出鼠標選中的行號注意MouseEvent中的y值只是相對於控件左上角的坐標我們需要加上滾動出了控件的部分
  
  addMouseListener(new MouseListener() {
  public void mouseDoubleClick(MouseEvent e) {
  }
  public void mouseDown(MouseEvent e) {
  int row = (ey cy) / lineHeight; //計算選中的行
  if (row >= ) {
  oldRowSel = rowSel;
  rowSel = row;
  }
  if (oldRowSel != rowSel) { // 重畫舊的和新的選擇項
  ((Canvas) egetSource())redraw(cx (ey / lineHeight)
  * lineHeight maxX lineHeight false);
  ((Canvas) egetSource())redraw(cx (oldRowSel + cy
  / lineHeight)
  * lineHeight maxX lineHeight false);
  }
  selectionChanged();
  }
  public void mouseUp(MouseEvent e) {
  }
  });
  
  當我們的控件獲得焦點時選中的列表項需要有虛框表示控件得到焦點當獲得或失去焦點是我們這裡只需要簡單的通知選中的項重畫
  
  addFocusListener(new FocusListener() {
  public void focusGained(FocusEvent e) {
  ((Canvas) egetSource())redraw(cx rowSel * lineHeight maxX
  lineHeight true);
  }
  public void focusLost(FocusEvent e) {
  ((Canvas) egetSource())redraw(cx rowSel * lineHeight maxX
  lineHeight true);
  }
  });
  
  我們在繪制每一個列表項時可以加入判斷當前控件是否得到焦點如果控件得到了焦點我們就在選中的項目上畫一個虛框下面是我們繪制一個列表項的代碼注意在代碼的最後繪制焦點的虛框
  
  void onPaint(GC gc int row int beginx int beginy boolean isSelected) {
  Color initColor = gcgetBackground();
  Color initForeColor = gcgetForeground();
  if (isSelected) {
  gcsetBackground(DisplaygetCurrent()getSystemColor(
  SWTCOLOR_LIST_SELECTION));
  gcfillRectangle(beginx beginy maxX lineHeight);
  gcsetForeground(DisplaygetCurrent()getSystemColor(
  SWTCOLOR_LIST_SELECTION_TEXT));
  } else {
  gcsetBackground(initColor);
  }
  gcdrawString((String) colorNamesget(row) beginx + beginy);
  Color color = DisplaygetCurrent()getSystemColor(
  ((Integer) colorsget(row))intValue());
  gcsetBackground(color);
  gcfillRectangle(beginx + beginy + lineHeight );
  gcsetBackground(initColor);
  gcsetForeground(initForeColor);
  if (isFocusControl() && isSelected)
  gcdrawFocus(cx beginy maxX lineHeight);
  }
  
  作為一個可操作的控件TAB鍵的支持也是很重要的由於我們的控件是從Canvas繼承過來的不支持TAB鍵下面的代碼使我們的控件有TAB鍵的支持
  
  addTraverseListener(new TraverseListener() {
  public void keyTraversed(TraverseEvent e) {
  if (edetail == SWTTRAVERSE_TAB_NEXT
  || edetail == SWTTRAVERSE_TAB_PREVIOUS) {
  edoit = true;
  }
  };
  });
  

From:http://tw.wingwit.com/Article/program/Java/ky/201311/28014.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.