我正在寻找 SWT 中组合框的实现,它允许我使用任何对象的列表设置其中的条目,其方式类似于树和表。
理想情况下,我希望下拉时的字符串能够与选择后的最终字符串不同。IE 下拉选择一个人,该人在列表中的姓名旁边显示他们的年龄,但在选择并放置在框中时只有他们的姓名。
我能找到的只是基于字符串的组合框,无法描述不同的显示选项,所以我想如果我想让它工作,我将不得不构建一个新组件,但我希望有人已经实现了这样一个东西(因为我在某些应用程序中看到过这种功能)但我找不到它?
我希望创造出这样的东西。
我正在寻找 SWT 中组合框的实现,它允许我使用任何对象的列表设置其中的条目,其方式类似于树和表。
理想情况下,我希望下拉时的字符串能够与选择后的最终字符串不同。IE 下拉选择一个人,该人在列表中的姓名旁边显示他们的年龄,但在选择并放置在框中时只有他们的姓名。
我能找到的只是基于字符串的组合框,无法描述不同的显示选项,所以我想如果我想让它工作,我将不得不构建一个新组件,但我希望有人已经实现了这样一个东西(因为我在某些应用程序中看到过这种功能)但我找不到它?
我希望创造出这样的东西。
JFaceComboViewer
似乎正是您想要的。它由ModelProvider
保存您的对象的 a 支持。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;
}
}
非常感谢 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() 方法,则不必设置标签提供程序,否则需要提供两个标签,一个用于选定项,一个用于所有其他项。
以防万一有人偶然发现这个问题与我的代码相同,我们将不胜感激反馈。
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);
}