8

ツリーやテーブルと同様に、任意のオブジェクトのリストを使用してエントリを設定できる、SWTのコンボボックスの実装を探しています。

理想的には、ドロップダウンしたときの文字列を、選択した最終的な文字列とは異なるものにできるようにする必要があります。IEのドロップダウンで、リスト内の名前の横に年齢が表示されている人を選択しますが、選択してボックスに配置した場合は名前のみを選択します。

存在するのは文字列ベースのコンボボックスだけで、さまざまな表示オプションを説明する方法がないので、機能させたい場合は新しいコンポーネントを作成する必要があると思いますが、誰かがすでにそのようなものを実装していることを望んでいました物事(私はいくつかのアプリケーションでこの種の機能を見たので)そして私はそれを見つけることができませんか?

このようなものを作りたいと思っています。

ここに画像の説明を入力してください

4

2 に答える 2

10

JFaceComboViewerはあなたが望むもののようです。ModelProviderそれはあなたのオブジェクトを保持するによって支えられています。ALabelProviderは、コンボ内のテキストを表示するために使用されます。

これはVogellaによる優れたチュートリアルです。

これがあなたが望むことをする例です。表示されたオブジェクトのブール値の場合、基本的に現在のコンボ選択が保存されます。

public static void main(String[] args) {
    final Display display = new Display();
    final Shell shell = new Shell(display);
    shell.setLayout(new FillLayout());

    final ComboViewer viewer = new ComboViewer(shell, SWT.READ_ONLY);

    viewer.setContentProvider(ArrayContentProvider.getInstance());

    /* if the current person is selected, show text */
    viewer.setLabelProvider(new LabelProvider() {
        @Override
        public String getText(Object element) {
            if (element instanceof Person) {
                Person current = (Person) element;

                if(current.isSelected())
                    return current.getName();
                else
                    return "";
            }
            return super.getText(element);
        }
    });

    final Person[] persons = new Person[] { new Person("Baz"),
            new Person("BazBaz"), new Person("BazBazBaz") };

    viewer.setInput(persons);

    /* within the selection event, tell the object it was selected */
    viewer.addSelectionChangedListener(new ISelectionChangedListener() {
        @Override
        public void selectionChanged(SelectionChangedEvent event) {
            IStructuredSelection selection = (IStructuredSelection) event.getSelection();
            Person person = (Person)selection.getFirstElement();

            for(Person p : persons)
                p.setSelected(false);

            person.setSelected(true);

            viewer.refresh();
        }
    });

    viewer.setSelection(new StructuredSelection(viewer.getElementAt(0)), true);

    shell.pack();
    shell.setSize(200, shell.getSize().y);
    shell.open();
    while (!shell.isDisposed()) {
        if (!display.readAndDispatch()) {
            display.sleep();
        }
    }
    display.dispose();
}

public static class Person {
    private String name;

    /* this will be true for the selected person */
    boolean isSelected;

    public Person(String name) {
        this.name = name;
        this.setSelected(false);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public boolean isSelected() {
        return isSelected;
    }

    public void setSelected(boolean isSelected) {
        this.isSelected = isSelected;
    }

}
于 2012-09-20T11:50:16.307 に答える
5

私を正しい軌道に乗せ、初期コードを提供してくれたBazに感謝します。しかし、これらすべてを取り入れたので、RCPビュー自体で使用するクリーナーが必要でした。また、コンボボックスの一般的なインスタンスが将来的には便利になるので、すべての定型的なものを新しいクラスにラップしました。次のように使用できます。

    List<Person> persons = new ArrayList<Person>();
    persons.add(new Person("Baz",26));
    persons.add(new Person("Glen",27));
    persons.add(new Person("Jimmy",18));

    TypedComboBox<Person> box = new TypedComboBox<Person>(parent);

    box.addSelectionListener(new TypedComboBoxSelectionListener<Person>() {

        @Override
        public void selectionChanged(TypedComboBox<Person> typedComboBox,
                Person newSelection) {
            System.out.println(newSelection);
        }
    });

    box.setLabelProvider(new TypedComboBoxLabelProvider<Person>() {

        @Override
        public String getSelectedLabel(Person element) {
            return element.getName();
        }

        @Override
        public String getListLabel(Person element) {
            return element.getName() + " | " + element.getAge();
        }
    });


    box.setContent(persons);

    box.selectFirstItem();

さまざまなオブジェクトを含む複数の選択ボックスが必要になるビューの場合、ビューのコードの本体にボイラープレートコードをキャストしたり再現したりすることはないので、型付きボックスを使用する方がはるかに満足です。

toSting()メソッドを使用するだけの場合は、ラベルプロバイダーを設定する必要はありません。それ以外の場合は、選択したアイテム用と他のすべてのアイテム用の2つのラベルを提供します。

誰かが私と同じ問題でこの質問に出くわした場合に備えて、ここに私のコードがあります、フィードバックをいただければ幸いです。

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

public class TypedComboBox<T> {

    private ComboViewer viewer;
    private TypedComboBoxLabelProvider<T> labelProvider;
    private List<T> content;
    private List<TypedComboBoxSelectionListener<T>> selectionListeners;
    private T currentSelection;

    public TypedComboBox(Composite parent) {
        this.viewer = new ComboViewer(parent, SWT.READ_ONLY);
        this.viewer.setContentProvider(ArrayContentProvider.getInstance());

        viewer.setLabelProvider(new LabelProvider() {
            @Override
            public String getText(Object element) {
                T typedElement = getTypedObject(element);
                if (labelProvider != null && typedElement != null) {
                    if (typedElement == currentSelection) {
                        return labelProvider.getSelectedLabel(typedElement);
                    } else {
                        return labelProvider.getListLabel(typedElement);
                    }

                } else {
                    return element.toString();
                }
            }
        });

        viewer.addSelectionChangedListener(new ISelectionChangedListener() {
            @Override
            public void selectionChanged(SelectionChangedEvent event) {
                IStructuredSelection selection = (IStructuredSelection) event
                        .getSelection();
                T typedSelection = getTypedObject(selection.getFirstElement());
                if (typedSelection != null) {
                    currentSelection = typedSelection;
                    viewer.refresh();
                    notifySelectionListeners(typedSelection);
                }

            }
        });

        this.content = new ArrayList<T>();
        this.selectionListeners = new ArrayList<TypedComboBoxSelectionListener<T>>();
    }

    public void setLabelProvider(TypedComboBoxLabelProvider<T> labelProvider) {
        this.labelProvider = labelProvider;
    }

    public void setContent(List<T> content) {
        this.content = content;
        this.viewer.setInput(content.toArray());
    }

    public T getSelection() {
        return currentSelection;
    }

    public void setSelection(T selection) {
        if (content.contains(selection)) {
            viewer.setSelection(new StructuredSelection(selection), true);
        }
    }

    public void selectFirstItem() {
        if (content.size()>0) {
            setSelection(content.get(0));
        }
    }
    public void addSelectionListener(TypedComboBoxSelectionListener<T> listener) {
        this.selectionListeners.add(listener);
    }

    public void removeSelectionListener(
            TypedComboBoxSelectionListener<T> listener) {
        this.selectionListeners.remove(listener);
    }

    private T getTypedObject(Object o) {
        if (content.contains(o)) {
            return content.get(content.indexOf(o));
        } else {
            return null;
        }
    }

    private void notifySelectionListeners(T newSelection) {
        for (TypedComboBoxSelectionListener<T> listener : selectionListeners) {
            listener.selectionChanged(this, newSelection);
        }
    }

そして、ラベルプロバイダーインターフェイス。

public interface TypedComboBoxLabelProvider<T> {

    public String getSelectedLabel(T element);

    public String getListLabel(T element);

}

そして選択リスナー:

public interface TypedComboBoxSelectionListener<T> {

    public void selectionChanged(TypedComboBox<T> typedComboBox, T newSelection);
}
于 2012-09-20T16:08:05.673 に答える