摘自: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));

  

注意:添加addTraverseListener时也得添加addListener(SWT.KeyDown)监听,不然的话,Tab键的Focus会不支持;

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

/** 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 keyif (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 keyif (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);elsevbar.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;}
}

  

转载于:https://www.cnblogs.com/huadoumi/p/5160300.html

开发Eclipse自定义控件相关推荐

  1. 开发 Eclipse 插件

    如何创建.调试和安装插件 在本文中,David Gallardo 向您展示了如何使用 Plug-in Development Environment 的代码生成向导来创建 Eclipse 插件.您将学 ...

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

    Android开发技巧--自定义控件之自定义属性 掌握自定义控件是很重要的,因为通过自定义控件,能够:解决UI问题,优化布局性能,简化布局代码. 上一篇讲了如何通过xml把几个控件组织起来,并继承某个 ...

  3. Android开发技巧——自定义控件之组合控件

    Android开发技巧--自定义控件之组合控件 我准备在接下来一段时间,写一系列有关Android自定义控件的博客,包括如何进行各种自定义,并分享一下我所知道的其中的技巧,注意点等. 还是那句老话,尽 ...

  4. Android开发之自定义控件——直尺

    Android开发之自定义控件--直尺 本人的第一篇技术博客,希望能够在分享的路上走的更远. 先上效果图: 涉及到的知识点: - Paint类 - Cancas类 - Path类 * 由于功能简单,此 ...

  5. Linux 内核开发 - Eclipse内核开发环境搭建

    翻译这篇文章的时候,我也想过可能会有高手说,内核开发用vi就足够了,还用什么eclipse,当然对于内核中函数特别了解的人确实如此,但是对于新 手,每使用一个函数,就要去查找一下函数的定义,实在是非常 ...

  6. Android安卓开发-eclipse正确添加第三方jar包

    本文转载自http://www.cnblogs.com/developerY/archive/2013/04/18/3027997.html,在此对原作者表示感谢! 在android项目中添加第三方j ...

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

    最近在学习android开发布局这块.第一次学习,很多代码不熟悉.所以自动提示对我来说很重要.但悲催的就是这个自动提示失效.今天在网上搜索了一下解决办法,主要有一下几种方法:转自 1用于没有一点提示的 ...

  8. eclipse插件开发_开发Eclipse插件

    eclipse插件开发 最近,我开始与一个团队合作开发Eclipse插件. 团队开发了一个很棒的插件,可以实现预期的目的. 因此,我检查了源并尝试构建它. 项目源包含所有必需的库,并且只能在Eclip ...

  9. 开发Eclipse插件

    最近,我开始与团队合作开发Eclipse插件. 团队开发了一个很棒的插件,可以实现预期的目的. 因此,我签出了源并尝试构建它. 项目源包含所有必需的库,并且只能在Eclipse中构建. 在当今不断交付 ...

最新文章

  1. 信息熵及其相关概念--数学
  2. 为什么需要系统程序员来构建云和IT自动化基础
  3. dinic (最大流) 算法 讲解
  4. 后台系统可扩展性学习笔记(七)Service Discovery与微服务
  5. php排序地区,怎么在php项目中实现一个地区分类排序算法
  6. 没错,你离分布式搜索只差一个Elasticsearch入门!
  7. java中的生产者消费者模式详解
  8. 实现两(三)列等高布局的方法
  9. 使用BULK COLLECT+FORALL加速批量提交
  10. 自然语言处理——文本的表示
  11. Python xlwt 操作 excel 表格基础(一):单元格写入、合并、插入位图等
  12. Mac电脑如何快速查找文件
  13. 知我者谓我心忧,不知者谓我何求!
  14. 重启计算机指令没用,win10笔记本不能关机重启点什么都没反应怎么办
  15. pythonopencv提取轮廓区域_Python + Opencv 实现轮廓提取,轮廓区域面积计算
  16. Costco市值10年增长5倍的秘诀:水坝式经营
  17. 【机器人基础】阻抗/导纳控制深度解析
  18. nasm 用xmm寄存器做矩阵相加溢出了如何处理?
  19. c语言 json 请求_JSON的简单介绍以及C语言的JSON库使用
  20. 新库上线 | CnOpenDataA股上市公司IPO申报发行文本数据

热门文章

  1. 2022-2028年中国科技馆行业研究及前瞻分析报告
  2. 2022-2028年中国丁晴橡胶行业市场深度分析及投资规划分析报告
  3. Python gRPC 安装
  4. QT5.3 + vs2012 + box2d环境配置
  5. 经常使用的npm命令
  6. Windows 64位下安装Redis详细教程
  7. 最新Maven及Tomcat配置~(IDEA版 试错无数!)
  8. TensorFlow多元线性回归实现
  9. [JS]在ACM模式下获取输入
  10. 微信小程序一键创建js,json,wxml,wxss