开发Eclipse自定义控件(二)

翻译|其它|编辑:郝浩|2005-12-27 13:39:00.000|阅读 1335 次

概述:

# 界面/图表报表/文档/IDE等千款热门软控件火热销售中 >>


当我们的控件获得焦点时,选中的列表项需要有虚框表示控件得到焦点。当获得或失去焦点是,我们这里只需要简单的通知选中的项重画。

addFocusListener(new FocusListener() {
public void focusGained(FocusEvent e) {
     ((Canvas) e.getSource()).redraw(cx, rowSel * lineHeight, maxX,lineHeight, true);
  }
     public void focusLost(FocusEvent e) {
        ((Canvas) e.getSource()).redraw(cx, rowSel * lineHeight, maxX,lineHeight, true);
  }
});

我们在绘制每一个列表项时可以加入判断当前控件是否得到焦点,如果控件得到了焦点,我们就在选中的项目上画一个虚框。下面是我们绘制一个列表项的代码,注意在代码的最后绘制焦点的虚框。

void onPaint(GC gc, int row, int beginx, int beginy, boolean isSelected) {
Color initColor = gc.getBackground();
Color initForeColor = gc.getForeground();
if (isSelected) {
     gc.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_LIST_SELECTION));
     gc.fillRectangle(beginx, beginy, maxX, lineHeight);
     gc.setForeground(Display.getCurrent().getSystemColor(
     SWT.COLOR_LIST_SELECTION_TEXT));
     } else {
 gc.setBackground(initColor);
}
gc.drawString((String) colorNames.get(row), beginx + 24, beginy);
Color color = Display.getCurrent().getSystemColor(((Integer) colors.get(row)).intValue());
gc.setBackground(color);
gc.fillRectangle(beginx + 2, beginy + 2, 20, lineHeight - 4);
gc.setBackground(initColor);
gc.setForeground(initForeColor);
if (isFocusControl() && isSelected)
gc.drawFocus(cx, beginy, maxX, lineHeight);
}

作为一个可操作的控件,TAB键的支持也是很重要的。由于我们的控件是从Canvas继承过来的,不支持TAB键。下面的代码使我们的控件有TAB键的支持:

addTraverseListener(new TraverseListener() {
public void keyTraversed(TraverseEvent e) {
     if (e.detail == SWT.TRAVERSE_TAB_NEXT
     || e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
     e.doit = true;
       }
   };
});


很多时候,我们需要有滚动条的支持。对于滚动条,我们只要在上面加上selectionListener,处理它的widgetSelected事件就可以。

bar = getVerticalBar();
if (bar != null) {
bar.addSelectionListener(new SelectionAdapter() {
     public void widgetSelected(SelectionEvent event) {
     scrollVertical((ScrollBar) event.widget);
   }
});
}

下面是函数scrollVertical的代码。一旦用户对滚动条操作,我们就可以计算出要滚动的区域,然后调用scroll函数。对函数scroll函数的调用会导致相应区域的重绘。

void scrollVertical(ScrollBar scrollBar) {
Rectangle bounds = getClientArea();
int y = -scrollBar.getSelection();
if (y + maxY < bounds.height) {
     y = bounds.height - maxY;
}
if( y%lineHeight !=0 )
     y = y - y % lineHeight - lineHeight;
     scroll(cx, y, cx, cy, maxX, maxY, false);
     cy = y;
}

现在我们的程序已经基本成形了,我们来进一步完善它。由于我们开发的控件是提供给程序员的,我们需要提供接口,让外部知道控件中发生的事件。其中最重要的是列表项的选中事件。我们需要提供接口让程序员能够添加事件监控器(listener)来监控发生的事件,并且一旦发生事件,我们需要通知监控器。

首先,我们添加一个成员来保存添加的事件监控器:

Vector selectionListeners = new Vector();

我们再增加一个函数addSelectionListener,让程序员可以添加监控器

public void addSelectionListener(SelectionListener listener) {
     selectionListeners.addElement(listener);
}

在我们前面的代码中,我们注意到每次选择项改变,我们都会调用selectionChanged函数。下面是selectionChanged函数代码。这里,我们会生成一个SelectionEvent事件,并且逐个调用事件监控器的widgetSelected方法。这样别人就可以监听到我们的事件了。

public void selectionChanged() {
     Event event = new Event();
     event.widget = this;
     SelectionEvent e = new SelectionEvent(event);
     for (int i = 0; i < selectionListeners.size(); i++) {
          SelectionListener listener = (SelectionListener) selectionListeners.elementAt(i);
          listener.widgetSelected(e);
     }
}

     现在辅助功能(Accessibility)也日益成为软件重要的部分,它是的残疾人也能够方便的使用我们的软件。美国已经立法,不符合Accessibility规范的软件不能够在政府部门销售。我们开发的控件也需要支持Accessibility.下面的代码使我们的控件有Accessibility支持。其中最重要的是getRole和getValue函数。我们的控件是从Canvas继承,我们在getRole函数中返回ACC.ROLE_LIST,这样我们的控件才能让屏幕阅读软件将我们的控件作为列表控件对待。

Accessible accessible = getAccessible(); accessible.addAccessibleControlListener(new AccessibleControlAdapter() { public void getRole(AccessibleControlEvent e)
 { int role = 0; int childID = e.childID; if (childID == ACC.CHILDID_SELF)
  { role = ACC.ROLE_LIST; }
    else if (childID >= 0 && childID < colors.size()) {
         role = ACC.ROLE_LISTITEM;
          }
         e.detail = role; }
   public void getValue(AccessibleControlEvent e){
          int childID = e.childID; if (childID == ACC.CHILDID_SELF) {
              e.result = getText();
              }
        else if (childID >= 0 && childID < colors.size()) {
        e.result = (String)colorNames.get(childID);
       }
    }
   public void getChildAtPoint(AccessibleControlEvent e) {
          Point testPoint = toControl(new Point(e.x, e.y));
          int childID = ACC.CHILDID_NONE; childID = (testPoint.y - cy)/lineHeight;
              if (childID == ACC.CHILDID_NONE) { Rectangle location = getBounds();                   location.height = location.height - getClientArea().height;
               if (location.contains(testPoint)) { childID = ACC.CHILDID_SELF;
           }
         }
     e.childID = childID;
}
public void getLocation(AccessibleControlEvent e) {
       Rectangle location = null; int childID = e.childID;
       if (childID == ACC.CHILDID_SELF) {
          location = getBounds();
        }
      if (childID >= 0 && childID < colors.size()) {
         location = new Rectangle(cx,childID*lineHeight+cy,maxX,lineHeight);
      }
     if (location != null) {
    Point pt = toDisplay(new Point(location.x, location.y));
          e.x = pt.x; e.y = pt.y;
          e.width = location.width;
          e.height = location.height;
      }
    }
   public void getChildCount(AccessibleControlEvent e) {
          e.detail = colors.size();
       }
   public void getState(AccessibleControlEvent e) {
         int state = 0; int childID = e.childID;
             if (childID == ACC.CHILDID_SELF) {
                 state = ACC.STATE_NORMAL;
                }
             else if (childID >= 0 && childID < colors.size()) {
        state = ACC.STATE_SELECTABLE;
      if (isFocusControl()) {
          state |= ACC.STATE_FOCUSABLE;
        }
     if (rowSel == childID) {
          state |= ACC.STATE_SELECTED;
     if (isFocusControl()) {
        state |= ACC.STATE_FOCUSED;
      }
   }
 }
e.detail = state;
}
});

最后,我们需要提供一些方法方便程序员使用我们的控件。

public void setSelection(int index) {
      if (index >= getItemCount() || index < 0)
      return;
      oldRowSel = rowSel;
      rowSel = index;
      selectionChanged();
    }
public int getSelectionIndex() {
      return rowSel;
   }
public int getItemHeight() {
      return lineHeight;
   }
public void setItemHeight(int height) {
      lineHeight = height;
   }
public int getItemCount() {
      return colors.size();
   }
public void add(int colorIndex, String colorName) {
      colorNames.add(colorName);
      colors.add(new Integer(colorIndex));
}

我们开发的控件的使用也是非常简单的。

CustomList customlist = new CustomList( parent, SWT.V_SCROLL | SWT.H_SCROLL );
customlist.add(SWT.COLOR_BLACK,"BLACK");
customlist.add(SWT.COLOR_BLUE,"BLUE");
customlist.setSelection(1);
customlist.setSize(400,400);
customlist.setBackground(Display.getDefault().getSystemColor(SWT.COLOR_LIST_BACKGROUND));

以上我们介绍了如何开发一个简单的自定义控件所需要涉及的技术。这里我们只以一个简单的颜色控件为例,但是一旦我们掌握了方法,我们很容易就可以开发出各种不同的漂亮控件。

 


标签:

本站文章除注明转载外,均为本站原创或翻译。欢迎任何形式的转载,但请务必注明出处、不得修改原文相关链接,如果存在内容上的异议请邮件反馈至chenjj@evget.com


为你推荐

  • 推荐视频
  • 推荐活动
  • 推荐产品
  • 推荐文章
  • 慧都慧问
扫码咨询


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP