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

  

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

  1. Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解

    http://hi.baidu.com/ltb6w/item/3a51f11926fda60ce75c361d Eclipse进行C/C++开发——Eclipse+CDT+MinGW的配置与使用详解 ...

  2. jBPM 6 开发 eclipse 插件安装

    jBPM 6 开发 eclipse 插件安装 概述 与之前的jBPM 5相比,jBPM 6 新引入的kjars及mavenized的特性,使流程开发设计与之前有了很大的不同,本文主要说明jBPM 6 ...

  3. Android开发技巧——自定义控件之增加状态

    Android开发技巧--自定义控件之增加状态 题外话 这篇本该是上周四或上周五写的,无奈太久没写博客,前几段把我的兴头都用完了,就一拖再拖,直到今天.不想把这篇拖到下个月,所以还是先硬着头皮写了. ...

  4. Android开发技巧——自定义控件之使用style

    Android开发技巧--自定义控件之使用style 回顾 在上一篇<Android开发技巧--自定义控件之自定义属性>中,我讲到了如何定义属性以及在自定义控件中获取这些属性的值,也提到了 ...

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

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

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

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

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

    eclipse开发Android程序时,忽然莫名其妙报这个错,之前还好好的.忽然就不行了. Failed to install xxx.apk on device~~~: timeout 尝试过手机里 ...

  8. android 开发进阶自定义控件 类似 TextView

    开发自定义控件的步骤: 1. 继承View: 2.重写构造函数并构造方法中获得我们自定义的属性. 3. 重写onDraw, 4.重写onMeasure 等函数 一.自定义View的属性,首先在res/ ...

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

    http://blog.unvs.cn/archives/android-eclipse-alt.html 按照其中的第一条+第二条 处理 注意:abcd要替换为 abcdefghijklmnopqr ...

随机推荐

  1. struts工程建立配置细节

    ActionForm ActionForm是用于存放表单提交的数据. 1.一个action是否必须配置一个actionForm,可以没有2.一个action是否可以配置多个表单?不可以,最多一个 在j ...

  2. java集合-ArrayList

    一.ArrayList 概述 ArrayList 是实现 List 接口的动态数组,所谓动态就是它的大小是可变的.实现了所有可选列表操作,并允许包括 null 在内的所有元素.除了实现 List 接口 ...

  3. ajax的再次封装!

    js的动态加载.缓存.更新以及复用 系列有点卡文,放心会继续的.先来点更基础的,为js的加载做点铺垫. jQuery的ajax本来就很方便了,为啥还要在进一步的封装呢?这个首先要看项目的具体需求了,如 ...

  4. 你可能不需要 jQuery!使用原生 JavaScript 进行开发

    很多的 JavaScript 开发人员,包括我在内,都很喜欢 jQuery.因为它的简单,因为它有很多丰富的插件可供使用,和其它优秀的工具一样,jQuery 让我们开发人员能够更轻松的开发网站和 We ...

  5. vueJS简单的点击显示与隐藏的效果

    目前前端框架太多,接触过angular.ember,现在开始倒腾vue 此处用到v-if.v-else.v-show,v-if或让元素不在DOM上,v-show只是改变display:block属性, ...

  6. mysql win源码比较大 不需要的文件删除 记录下来

    mysql-5.6.25-win32.zip 从官方下载下来的大小为 343MB,太大了可以删除掉的地方记录一下 docs :全部删除. sql-bench:全部删除. mysql-test :全部删 ...

  7. 避开unity的坑(转摘)

    避开unity的坑(转摘) 以下总结一部分来自经验之谈,一部分来自其他人的分享.总的来讲,unity开发原型和效果.验证想法,确实是无比便利.可能一个月就把核心玩法做得差不多.强大的编辑器功能让我们也 ...

  8. Java Web 三层架构详解

    java 三层架构ssh 一个spring2.5+hibernate3.2+struts2.0组合框架,使用spring的 IoC来管理应用的 所有bean,包括struts2的 action,充分发 ...

  9. CSS常用样式(四)之animation

    上篇CSS常用样式(三)这篇博文中已经介绍过了CSS中具有动画效果的transition.transform,今天来大概说说CSS中的animation.animation的加入会使得动画效果更加乐观 ...

  10. Android开发学习——搭建开发环境

    在学校开课学习了android的一些简单的UI组件,布局,四大组件学习了2个,数据存储及网络通信,都是一些简单的概念,入门而已.许多东西需要自己去学习. 学习一下 Android开发环境的搭建,两种方 ...