| 特性 | Combo (組合框) | List (列表框) |
|---|---|---|
| 顯示模式 | 單行輸入框 + 下拉清單 | 固定顯示多行清單 |
| 輸入方式 | 可選 SWT.DROP_DOWN (唯選) 或 SWT.SIMPLE (可輸入文字) | 僅支援選擇,不可直接輸入 |
| 選擇模式 | 單選 | SWT.SINGLE / SWT.MULTI (Ctrl/Shift 多選) |
| 捲軸 | 下拉清單內建 | SWT.V_SCROLL, SWT.H_SCROLL |
| 常用事件 | SelectionListener (選擇/輸入確認) | SelectionListener (選擇變更) |
DROP_DOWN:點擊箭頭展開,不可編輯輸入框文字 (唯選)。
SIMPLE:清單永遠展開,輸入框可編輯,輸入不在清單中的文字不會自動加入 (需自行處理)。
package swt_jface.demo3;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
public class DropDownAndSimple {
Display display = new Display();
Shell shell = new Shell(display);
public DropDownAndSimple() {
RowLayout rl = new RowLayout();
rl.spacing = 15; rl.marginWidth = 15; rl.marginHeight = 15;
shell.setLayout(rl);
Combo comboDropDown = new Combo(shell, SWT.DROP_DOWN | SWT.BORDER);
Combo comboSimple = new Combo(shell, SWT.SIMPLE | SWT.BORDER);
for (int i = 0; i < 3; i++) {
comboDropDown.add("item " + i);
comboSimple.add("item " + i);
}
shell.pack(); shell.open();
while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); }
display.dispose();
}
public static void main(String[] args) { new DropDownAndSimple(); }
}
監聽 SelectionListener:
- widgetSelected:使用者從下拉選單選擇項目。
- widgetDefaultSelected:使用者在輸入框輸入文字並按 Enter (或雙擊)。此範例實作「輸入新值 -> 自動加入清單 -> 重新排序」。
package swt_jface.demo3;
import java.util.Arrays;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
public class SampleCombo {
Display display = new Display();
Shell shell = new Shell(display);
public SampleCombo() {
shell.setLayout(new GridLayout(2, false));
new Label(shell, SWT.NULL).setText("Select your favorite programming language: ");
final Combo combo = new Combo(shell, SWT.DROP_DOWN | SWT.BORDER); // 明確指定 DROP_DOWN
String[] langs = {"Java", "C", "C++", "SmallTalk"};
Arrays.sort(langs);
for (String l : langs) combo.add(l);
combo.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
System.out.println("Selected idx: " + combo.getSelectionIndex()
+ ", item: " + combo.getItem(combo.getSelectionIndex())
+ ", text: " + combo.getText());
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
String text = combo.getText().trim();
if (text.isEmpty()) return;
// 若輸入文字不在清單中,加入並排序
if (combo.indexOf(text) < 0) {
combo.add(text);
String[] items = combo.getItems();
Arrays.sort(items);
combo.setItems(items); // 重設項目觸發排序
}
System.out.println("Default selected (Enter): " + text);
}
});
shell.pack(); shell.open();
while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); }
display.dispose();
}
public static void main(String[] args) { new SampleCombo(); }
}
示範 SWT.SINGLE、SWT.MULTI、SWT.V_SCROLL。取得選擇項目:getSelectionIndices() (索引陣列)、getSelection() (字串陣列)。
package swt_jface.demo3;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.RowLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
public class SampleList {
Display display = new Display();
Shell shell = new Shell(display);
public SampleList() {
shell.setLayout(new RowLayout());
new Label(shell, SWT.NULL).setText("What programming languages are you proficient in? ");
final List list = new List(shell, SWT.SINGLE | SWT.BORDER | SWT.V_SCROLL);
String[] langs = {"Java", "C", "C++", "SmallTalk"};
for (String l : langs) list.add(l);
list.addSelectionListener(new SelectionListener() {
@Override
public void widgetSelected(SelectionEvent e) {
int[] idx = list.getSelectionIndices();
String[] items = list.getSelection();
StringBuilder sb = new StringBuilder("Selected: ");
for (int i = 0; i < idx.length; i++) {
sb.append(idx[i]).append("(").append(items[i]).append(")");
if (i < idx.length - 1) sb.append(", ");
}
System.out.println(sb + ".");
}
@Override
public void widgetDefaultSelected(SelectionEvent e) {
// List 雙擊或 Enter 觸發
System.out.println("Default selected (double click/Enter): " + Arrays.toString(list.getSelection()));
}
});
list.selectAll(); // 程式化全選 (需 MULTI 模式才顯示多選效果)
// list.select(1); // 選擇指定索引
shell.pack(); shell.open();
while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); }
display.dispose();
}
public static void main(String[] args) { new SampleList(); }
}
package swt_jface.demo3;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
public class SingleMultiLists {
Display display = new Display();
Shell shell = new Shell(display);
public SingleMultiLists() {
GridLayout gl = new GridLayout(2, true);
shell.setLayout(gl);
new Label(shell, SWT.NULL).setText("SINGLE");
new Label(shell, SWT.NULL).setText("MULTI");
List single = new List(shell, SWT.BORDER);
List multi = new List(shell, SWT.MULTI | SWT.BORDER);
String[] items = {"Item 1", "Item 2", "Item 3", "Item 4"};
for (String s : items) { single.add(s); multi.add(s); }
shell.pack(); shell.open();
while (!shell.isDisposed()) { if (!display.readAndDispatch()) display.sleep(); }
display.dispose();
}
public static void main(String[] args) { new SingleMultiLists(); }
}
實務上建議使用 JFace ComboViewer / ListViewer 搭配 ArrayContentProvider、LabelProvider,實現 Model-View 分離:
ComboViewer viewer = new ComboViewer(parent, SWT.DROP_DOWN | SWT.READ_ONLY);
viewer.setContentProvider(ArrayContentProvider.getInstance());
viewer.setLabelProvider(new LabelProvider() {
@Override public String getText(Object e) { return ((MyObject)e).getName(); }
});
viewer.setInput(myDataList);
SWT 原生不支援輸入時過濾下拉選單。需自行實作:
- 監聽 ModifyListener 取得輸入文字。
- 過濾資料源。
- 呼叫 combo.setItems(filtered) 並 combo.setListVisible(true) 強制展開。
- 注意游標位置保持與避免遞迴觸發 Modify。
List 一次性載入所有字串至記憶體,項目超過數萬筆會卡頓。解決方案:
- 使用 Table + TableViewer (支援虛擬 ILazyContentProvider / Virtual 模式)。
- 或分頁載入。
setFont(), setForeground(), setBackground() 影響整體。TableViewer / ComboViewer + OwnerDrawLabelProvider (SWT.OWNER_DRAW) 繪製。Combo 適合「單選、空間有限、需下拉選擇」場景;List 適合「多選、固定顯示區域、項目較少」場景。掌握 SelectionListener 兩種事件區別 (widgetSelected vs widgetDefaultSelected) 及索引/字串取得 API,即可應付大多數表單輸入需求。複雜互動請升級至 JFace Viewer 框架。