开发Eclipse自定义控件(一)

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

概述:

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


现在基于 Eclipse 的应用越来越多,很多桌面应用都是用Eclipse开发的。Eclipse提供了一套 SWT/JFACE 的控件库,使得人们开发界面应用极大的方便。但是,SWT/JFACE的控件库毕竟有限,在应用开发是我们不可避免地要自己开发一些自定义的控件。本文通过开发一个颜色列表控件的实例介绍了Eclipse自定义控件开发中所要用到的技术。

在Eclipse网站上有一篇相关的文章"Creating Your Own Widgets using SWT",该文介绍了开发自己控件的很多基本概念、方法,并且通过实例进行了介绍,非常好。但是其所用的实例比较简单,还有很多控件开发中所要涉及到的内容,例如键盘、鼠标事件的处理,滚动条、焦点的处理等等没有提及。本文通过开发一个自定义的颜色列表控件的实例,全面地介绍了自定义控件所涉及的技术。同时,读者也可以对该实例进行扩展,实现自己的列表控件。

SWT中提供的标准列表控件非常简单,只能提供字符串的选择。我们经常需要提供一些图形列表供用户选择,这就需要自己开发自定义的列表控件。颜色选择列表是我们常用的一种图形列表,我们就以此为例进行介绍。以下是我们将要开发的颜色列表。

我们在开发自定义控件时主要考虑以下问题:

1、 自定义控件的绘制:通常我们需要自己对控件的形状或图案进行绘制;
2、 控件对键盘事件的响应:当焦点进入控件,用户进行键盘操作,通过键盘对控件进行控制时,我们需要让控件对用户的操作进行响应。例如在列表中,用户会通过上下箭头改变列表的选择项;
3、 控件对鼠标事件的响应:当用户用鼠标选中控件,进行操作时,控件必须作出相应的反应;
4、 控件对焦点事件的响应:当界面焦点进入或移出控件,通常我们需要将控件绘制成得到或失去焦点的形状。例如,当焦点进入列表时,一般被选中的列表项会有虚框表示选中。
5、 响应TAB键:对于一个可操纵的控件,用户可以用TAB键将焦点移入或移出。
6、 响应滚动条事件:当控件有滚动条时,我们需要响应用户对滚动条的操作,完成对控件的绘制工作。
7、 提供事件监听机制:程序员使用你的控件时通常需要监听控件中发生的一些事件,这样当事件发生时,他们能够进行相应处理。
8、 提供辅助功能(Accessibility):辅助功能是方便残障人士使用时必须的,标准控件都会提供相应的支持,我们自定义的控件也不例外。
9、 提供功能接口方便程序员访问:通常为方便程序员使用时获取控件中的信息或进行设置,我们需要提供一些接口。

首先我们要开发的列表控件是一个基本控件,所以我们选择Canvas作为我们开发的基类。

public class ColorList extends Canvas {
       Vector colors = new Vector(); // 用于保存我们颜色控件中的颜色值
       Vector colorNames = new Vector(); // 用于保存颜色控件中的颜色名字

       int rowSel = -1; // 用于保存当前选中的行号
       int oldRowSel = -1; // 用于保存上一次选中的行号

       int maxX, maxY; // 用于保存列表的宽度和高度
       int lineHeight; // 用于设置行高

       int cx = 0; // 滚动条滚动后,控件的图形相对于控件可见区域左上角的x坐标
       int cy = 0; // 滚动条滚动后,控件的图形相对于控件可见区域左上角的y坐标
}

控件开发最重要的就是控件的绘制了。控件的绘制可以通过添加PaintListener,在它的paintControl方法中进行。

这里要注意的是从PaintEvent中获取的x,y,height,width是需要重绘的区域,x,y是以控件的左上角为原点的坐标。在我们的程序中,为了性能起见,我们先根据需要重绘的区域计算出需要重绘的行数,只重绘相应的行,而不是将整个控件重绘。我们程序中用到的onPaint用于绘制一行。

接下来,我们要让我们的控件响应键盘上下键对列表项进行选择。我们已对向上键的处理为例,首先当用户按了向上键时,我们需要改变选择,并且重绘旧的和新的选择项。如果选择项已经到了列表的顶部,我们还需要同时滚动滚动条。

addListener(SWT.KeyDown, new Listener() {
public void handleEvent(Event event) {
       switch (event.keyCode) {
       case SWT.ARROW_UP: // 处理向上键
            if (rowSel != 0) {
            oldRowSel = rowSel;
            rowSel--;
                 if (oldRowSel != rowSel) { //发送消息让控件重绘
                 ((Canvas) event.widget).redraw(cx, (rowSel + cy/ lineHeight)
                 * lineHeight, maxX, lineHeight*2, false);
               }
          if (rowSel < -cy / lineHeight) { //如果需要,滚动滚动条
       ScrollBar bar = ((Canvas) event.widget)
     .getVerticalBar();
     bar.setSelection(bar.getSelection() - lineHeight);
  scrollVertical(bar);
  }
selectionChanged(); // 发送selectionChanged事件
}
break;
case SWT.ARROW_DOWN: // down arror key

break;
}
}
});

接下来,我们要让我们的控件响应鼠标对列表项进行选择。首先我们要计算出鼠标选中的行号,注意MouseEvent中的y值只是相对于控件左上角的坐标,我们需要加上滚动出了控件的部分。

addMouseListener(new MouseListener() {
public void mouseDoubleClick(MouseEvent e) {
}
     public void mouseDown(MouseEvent e) {
     int row = (e.y - cy) / lineHeight; //计算选中的行
          if (row >= 0) {
          oldRowSel = rowSel;
          rowSel = row;
       }
     if (oldRowSel != rowSel) { // 重画旧的和新的选择项
     ((Canvas) e.getSource()).redraw(cx, (e.y / lineHeight)
     * lineHeight, maxX, lineHeight, false);
     ((Canvas) e.getSource()).redraw(cx, (oldRowSel + cy/ lineHeight)
     * lineHeight, maxX, lineHeight, false);
     }
    selectionChanged();
   }
 public void mouseUp(MouseEvent e) {
 }
});


addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
     GC gc = e.gc;
     Point size = getSize();
     int beginx = e.x;
     int beginy = (e.y / lineHeight) * lineHeight;
     int beginLine = (e.y - cy) / lineHeight;
     int endLine = beginLine + e.height / lineHeight + 1;
     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);
        }
     }
});

 


标签:

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


为你推荐

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


添加微信 立即咨询

电话咨询

客服热线
023-68661681

TOP