首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

SWT/JFace List 與 Combo 列表控件綜合範例:單選、多選、下拉與自訂輸入

     編輯:Java 相關知識

Combo 與 List 核心差異

特性Combo (組合框)List (列表框)
顯示模式單行輸入框 + 下拉清單固定顯示多行清單
輸入方式可選 SWT.DROP_DOWN (唯選) 或 SWT.SIMPLE (可輸入文字)僅支援選擇,不可直接輸入
選擇模式單選SWT.SINGLE / SWT.MULTI (Ctrl/Shift 多選)
捲軸下拉清單內建SWT.V_SCROLL, SWT.H_SCROLL
常用事件SelectionListener (選擇/輸入確認)SelectionListener (選擇變更)

範例一:DROP_DOWN vs SIMPLE 模式對比

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

範例二:Combo 選擇監聽與動態新增/排序

監聽 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(); }
}

範例三:List 單選/多選與選擇索引取得

示範 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(); }
}

範例四:SINGLE vs MULTI 並列展示

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

進階應用技巧

1. 動態資料綁定 (ContentProvider 模式)

實務上建議使用 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);

2. Combo 自動完成

SWT 原生不支援輸入時過濾下拉選單。需自行實作:
- 監聽 ModifyListener 取得輸入文字。
- 過濾資料源。
- 呼叫 combo.setItems(filtered) 並 combo.setListVisible(true) 強制展開。
- 注意游標位置保持與避免遞迴觸發 Modify。

3. List 虛擬化 / 大量資料

List 一次性載入所有字串至記憶體,項目超過數萬筆會卡頓。解決方案:
- 使用 Table + TableViewer (支援虛擬 ILazyContentProvider / Virtual 模式)。
- 或分頁載入。

4. 樣式客製化

  • 字型/顏色:setFont(), setForeground(), setBackground() 影響整體。
  • 行高/項目渲染:原生 List/Combo 不支援逐行不同顏色/圖示。需改用 TableViewer / ComboViewer + OwnerDrawLabelProvider (SWT.OWNER_DRAW) 繪製。

總結

Combo 適合「單選、空間有限、需下拉選擇」場景;List 適合「多選、固定顯示區域、項目較少」場景。掌握 SelectionListener 兩種事件區別 (widgetSelected vs widgetDefaultSelected) 及索引/字串取得 API,即可應付大多數表單輸入需求。複雜互動請升級至 JFace Viewer 框架。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved