开发Eclipse自定义控件

摘自:http://www.ibm.com/developerworks/cn/opensource/os-eclipcntl/

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

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方法中进行。

 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);
        }
      }
    });

  

这里要注意的是从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) {
      }
    });

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

    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));

  

整个程序完整的代码请参考如下:

/*
 * Created on 2005-8-27
 *
 */
import java.util.Vector;
import org.eclipse.swt.SWT;
import org.eclipse.swt.accessibility.ACC;
import org.eclipse.swt.accessibility.Accessible;
import org.eclipse.swt.accessibility.AccessibleControlAdapter;
import org.eclipse.swt.accessibility.AccessibleControlEvent;
import org.eclipse.swt.events.ControlAdapter;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.events.TraverseEvent;
import org.eclipse.swt.events.TraverseListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;

/**
 * @author lq
 *
 */
public class ColorList extends Canvas {
	static int COLORS[] = { SWT.COLOR_RED, SWT.COLOR_GREEN, SWT.COLOR_BLUE,
			SWT.COLOR_MAGENTA, SWT.COLOR_YELLOW, SWT.COLOR_CYAN,
			SWT.COLOR_DARK_RED, SWT.COLOR_DARK_GREEN, SWT.COLOR_DARK_BLUE,
			SWT.COLOR_DARK_MAGENTA, SWT.COLOR_DARK_YELLOW, SWT.COLOR_DARK_CYAN };

	static String COLORSNAME[] = { "红色", "绿色", "蓝色", "紫色", "黄色",
		"青色", "暗红色", "暗绿色", "暗蓝色", "暗紫色",
		"暗黄色", "暗青色" };

	Vector colors = new Vector();

	Vector colorNames = new Vector();

	int rowSel = -1;

	int oldRowSel = -1;

	int cx, cy;

	int maxX = 200, maxY;

	int lineHeight = 18;

	Vector selectionListeners = new Vector();

	public ColorList(Composite parent, int style) {
		super(parent, style);
		init();
	}

	void init() {
		cx = 0;
		cy = 0;
		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);
				}

			}
		});
		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) {

			}

		});
		addListener(SWT.KeyDown, new Listener() {
			public void handleEvent(Event event) {
				switch (event.keyCode) {
				case SWT.ARROW_UP: // up arrow key
					if (rowSel != 0) {
						oldRowSel = rowSel;
						rowSel--;
						if (oldRowSel != rowSel) {
							((Canvas) event.widget).redraw(cx, rowSel*lineHeight + cy
									, maxX, lineHeight*2, false);
						}
						if (rowSel < -cy / lineHeight) {
							ScrollBar bar = ((Canvas) event.widget)
									.getVerticalBar();
							bar.setSelection(bar.getSelection() - lineHeight);
							scrollVertical(bar);
						}
						selectionChanged();
					}
					break;
				case SWT.ARROW_DOWN: // down arror key
					if (rowSel < colors.size() - 1) {
						oldRowSel = rowSel;
						rowSel++;
						if (oldRowSel != rowSel) {
							((Canvas) event.widget).redraw(cx, (rowSel + cy
									/ lineHeight)
									* lineHeight, maxX, lineHeight, false);
							((Canvas) event.widget).redraw(cx, (oldRowSel + cy
									/ lineHeight)
									* lineHeight, maxX, lineHeight, false);
						}
						if (rowSel >= (((Canvas) event.widget).getClientArea().height - cy)
								/ lineHeight) {
							ScrollBar bar = ((Canvas) event.widget)
									.getVerticalBar();
							if (bar != null) {
								bar.setSelection(bar.getSelection()
										+ lineHeight);
								scrollVertical(bar);
							}
						}
						selectionChanged();
					}
					break;
				}
			}
		});
		addControlListener(new ControlAdapter() {
			public void controlResized(ControlEvent event) {
				Point size = getSize();
				maxX = size.x * 3 / 2;
				maxY = colors.size() * lineHeight;
				resizeScrollBars();
			}
		});
		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);
			}
		});
		addTraverseListener(new TraverseListener() {
			public void keyTraversed(TraverseEvent e) {
				if (e.detail == SWT.TRAVERSE_TAB_NEXT
						|| e.detail == SWT.TRAVERSE_TAB_PREVIOUS) {
					e.doit = true;
				}
			};

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

	private void addAccessibility(){
		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;

	        }

	    });
	}

	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 + 40, beginy);
		Color color = Display.getCurrent().getSystemColor(
				((Integer) colors.get(row)).intValue());
		gc.setBackground(color);
		gc.fillRectangle(beginx + 2, beginy + 2, 30, lineHeight - 4);
		gc.setBackground(initColor);
		gc.setForeground(initForeColor);
		if (isFocusControl() && isSelected)
			gc.drawFocus(cx, beginy, maxX, lineHeight);
	}

	void resizeScrollBars() {
		Rectangle clientArea = getClientArea();
		ScrollBar hbar = getHorizontalBar();
		if (hbar != null) {
			hbar.setMaximum(maxX);
			hbar.setThumb(clientArea.width);
			hbar.setPageIncrement(clientArea.width);
		}

		ScrollBar vbar = getVerticalBar();
		if (vbar != null) {
			vbar.setMaximum(maxY);
			vbar.setThumb(clientArea.height);
			vbar.setPageIncrement(clientArea.height);
			vbar.setIncrement(lineHeight);
			if (clientArea.height >= lineHeight * getItemCount() + 2)
				vbar.setVisible(false);
			else
				vbar.setVisible(true);
		}
	}

	void scrollHorizontal(ScrollBar scrollBar) {
		Rectangle bounds = getClientArea();
		int x = -scrollBar.getSelection();
		if (x + maxX < bounds.width) {
			x = bounds.width - maxX;
		}
		scroll(x, cy, cx, cy, maxX, maxY, false);
		cx = x;
	}

	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;
	}

	public Point computeSize(int wHint, int hHint, boolean changed) {
		int width = 300, height = lineHeight * (getItemCount())+50;
		if (wHint != SWT.DEFAULT)
			width = wHint;
		if (hHint != SWT.DEFAULT)
			height = hHint;
		return new Point(width + 2, height + 2);

	}

	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));
	}

	public void setDefault() {
		for (int i = 0; i < COLORS.length; i++) {
			colors.add(new Integer(COLORS[i]));
			colorNames.add(COLORSNAME[i]);
		}
	}

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

	public void removeImageClickedListener(SelectionListener listener) {
		selectionListeners.removeElement(listener);
	}

	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);
		}

	}

	public String getText(){
		if(rowSel>=0)
			return (String)colorNames.get(rowSel);
		else return null;
	}
}

  

时间: 2024-11-03 17:58:29

开发Eclipse自定义控件的相关文章

android开发——Eclipse环境下代码编辑最常用快捷键集锦(来了就不能空手而归)

Ctrl+D:删除光标所在行 Ctrl+/ :注释选中行 :Ctrl+\:注销选中行 Ctrl+Shift+/:注释选中的java或xml代码块: Ctrl+Shift+\:注销选中的Java或xml代码块.(形式:/*      */ 或 <!--      -->) shift + alt + j或/**+Enter(回车键):添加javadoc头注释,形如/** * * * * * */(个人更习惯用/**+Enter(回车键)) Ctrl+K:向前查找与当前选定内容相同的代码(如查找与

Android开发技巧——自定义控件之自定义属性

Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个ViewGroup子类,把它们封装起来使用.这是我们接触到的最简单的一种自定制控件了.但许多时候,我们还需要在布局文件中使用它们的时候,能通过属性传入一些值,来影响最终的显示结果. 我们在做项目中经常会遇到的一个情况:一张图片加一个文本的组合.比如充值账户成功之后显示的一个界面,上面是一个表示成功的

Java开发 Eclipse使用技巧(转)

1.如何设置默认的代码目录为src,默认的输出目录为bin? window->Preferences->java->Buil Path中,右侧选择Folders就可以 2.如何为快速局部变量设置getX,setX属性?在代码里->右键->source->Generae Getters and Setters,然后在弹出的对话框里,把要加的属性前打勾 3.快速增加try-catch语句块光标放到出错行,然后ctrl+1,在下拉列表里选择 4.eclipse保存时自动编译,

度量快速开发平台自定义控件与自定义事件的使用方法

定义控件: '定义控件,平台支持使用net环境中自带的各种控件,使用各种属性,方法和事件 dim textBox=createObject("System.Windows.Forms.TextBox") ''设置属性及显示到容器中 textBox.Text=".net自带的控件" textBox.Dock = DockStyle.Fill 容器控件1.Controls.Add(textBox) '--------------------自定义控件完成--------

Android Studio大课堂 - 8.不改变现有目录结构开发Eclipse项目

Android Studio大课堂 - 1.简要介绍 Android Studio大课堂 - 2.下载安装及初始化 Android Studio大课堂 - 3.新建或导入APP Android Studio大课堂 - 4.1.Coding - 定位目标 Android Studio大课堂 - 4.2.Coding - 写代码 Android Studio大课堂 - 4.3.Coding - 使用第三方库 Android Studio大课堂 - 4.4.Coding - 快捷键 Android S

android开发 eclipse alt+”/”自动提示失效

最近在学习android开发布局这块.第一次学习,很多代码不熟悉.所以自动提示对我来说很重要.但悲催的就是这个自动提示失效.今天在网上搜索了一下解决办法,主要有一下几种方法:转自 1用于没有一点提示的情况:依次打开eclipse上面的windows ——preferences ——java ——editor —— content assist ,在右上方有一行“select the proposal kinds contained in the ‘default’ content assist

Android开发eclipse运行程序时报timeout的解决方法

eclipse开发Android程序时,忽然莫名其妙报这个错,之前还好好的.忽然就不行了. Failed to install xxx.apk on device~~~: timeout 尝试过手机里删除应用程序.手机重启.重启adb.重启eclipse.重启电脑后,还是不行. 尝试了半天,找到了方案: eclipse-->window-->Preferences-->Android-->DDMS-->ADB connection time out(ms) 里面的值默认为50

java开发eclipse常见问题(一)The superclass &quot;javax.servlet.http.HttpServlet&quot; was not found on the Java Build Path

最近刚开始用Eclipse开发,刚开始都是按教程一步一步的新建web工程也没出现什么问题. 今天选了一个新的workspace,建了个web工程发现最简单的jsp页面都报错:The superclass "javax.servlet.http.HttpServlet" was not found on the Java Build Path 百度了下找到原因了,现在总结下,虽然是个简单的问题,但新手肯定会遇到过的. 报错原因是:web工程缺少编译Tomcat运行时相关类,只要加上就行了

Android 开发 Eclipse 内存调整

在使用Eclipse的过程中,有时会遇到使用Java虚拟机内存不够的情况,这时Eclipse就会提示你重启,我们可以通过设定Eclipse启动参数来调节使用Java虚拟机内存. 右键点击Eclipse的快捷方式,选择属性,在目标的Text里加上 -vmargs -Xmx192M,设定初始化使用Java虚拟机最大内存为192M,也可以设定为其他值. -Xmx 这个参数是设定使用的最大内存 -Xms 这个参数是设定使用的最小内存 两个参数可以同时使用,也可单独使用. 用编译时报内存不够,翻了一下资料