问题
How do you get a data reference from an SWT Combo drop list? Currently I need to get the text from the Combo box, then run through my data objects until I reach one that has the same text as what the Combo box reports.
Combo combo = new Combo( new Shell(), SWT.READ_ONLY );
for (Person person : People.getPeople())
combo.add( person.getName() );
for (Person person : People.getPeople())
if (combo.getText().equals( person.getName() ))
System.out.println( "Person: " + person.getFullName() );
While this works, it is prone to various errors, and also CPU intensive especially for large lists. I really wish that a Combo would had "setData()" and "getData()" methods for each Combo item.
回答1:
I have created a class which allows an object to be associated with a Combo box "add()". This class will return the object directly without casting it. My first crack at creating a generic class :-)
Basic syntax to use it is (the Combo MUST be set to SWT.READ_ONLY):
Combo peopleBaseCombo = new Combo(shell, SWT.READ_ONLY);
ComboData<Person> peopleCombo = new ComboData<Person>(peopleBaseCombo);
for ( Person person : People.getPeople())
peopleCombo.addItem(person, person.getLastName);
...
Person person = peopleCombo.getCurrentItem();
The class is:
import java.util.ArrayList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Combo;
/**
* A generic wrapper around a standard SWT {@link Combo} control.
* Allows for using arbitrary data objects associated with the displayed text.
* Assumes a {@link SWT#READ_ONLY} combo drop list<br><br>
* <blockquote>Combo peopleBaseCombo = new Combo(shell, SWT.READ_ONLY);<br>
* ComboData<Person> peopleCombo = new ComboData<Person>(peopleBaseCombo);<br><br>
* for ( Person person : People.getPeople())<br>
* peopleCombo.addItem(person, person.getLastName);<br>
* <br>
* ...<br>
* <br>
* Person person = peopleCombo.getCurrentItem();</blockquote>
*/
public class ComboData<T>
{
private ArrayList<ComboItem<T>> ivItemList;
private Combo ivCombo;
/**
* Create a ComboControl for the passed Combo control
* @param combo - SWT {@link Combo} control
*/
public ComboData( Combo combo )
{
super();
ivCombo = combo;
ivItemList = new ArrayList<>();
removeAll();
}
/**
* Adds an item to the controller along with the text you want shown in the Combo
* @param itemData - the data item of the defined type
* @param text - the text which will be shown in the Combo control
*/
public void addItem( T itemData, String text )
{
// these are added at the same time, and therefore have the same index location
ivItemList.add( new ComboItem<T>( itemData, text ) );
ivCombo.add( text );
}
/**
* Removes all the items in the list and Combo
*/
public void removeAll()
{
ivItemList.clear();
ivCombo.removeAll();
}
/**
* Returns the combo held by this control
*/
public Combo getCombo()
{
return ivCombo;
}
/**
* Set the current displayed item in the Combo using the associated data object
* @param setItemData - Sets the Combo display to the text associated with the setItemData
*/
public void setCurrentItem( T setItemData )
{
for (ComboItem<T> item : ivItemList)
if (item.getItemData().equals( setItemData ))
{
ivCombo.setText( item.getText() );
return;
}
if (ivItemList.size() > 0)
ivCombo.setText( ivItemList.get( 0 ).getText() );
}
/**
* Gets the currently chosen ComboItem associated with the Combo control displayed text
* @return the data item associated with the displayed text
*/
public T getCurrentItem()
{
ComboItem<T> currentItem;
try
{
currentItem = ivItemList.get( ivCombo.getSelectionIndex() );
}
catch (IndexOutOfBoundsException e)
{
try
{
currentItem = ivItemList.get( 0 );
}
catch (IndexOutOfBoundsException e1)
{
// will only happen if this method is called before there are any items in the list
return null;
}
}
return currentItem.getItemData();
}
@Override
public String toString()
{
StringBuilder info = new StringBuilder();
String className;
try
{
className = getCurrentItem().getClass().getName();
}
catch (NullPointerException e)
{
className = "";
}
info.append( "ComboControl (" );
info.append( className );
info.append( "):" );
for (ComboItem<T> item : ivItemList)
{
info.append( "\n " );
info.append( item.getInformation() );
}
return info.toString();
}
/**
* The item holding both the Combo control text, and its associated data
*/
private class ComboItem<I>
{
private String ivText;
private I ivItemData;
/**
* Create the Combo item using the arbitrary data and the text to be displayed
*/
private ComboItem( I itemData, String text )
{
super();
ivItemData = itemData;
ivText = text;
}
/**
* Get the text to be displayed in the Combo control
*/
private String getText()
{
return ivText;
}
/**
* Get the object associated with the text shown in the Combo control
*/
private I getItemData()
{
return ivItemData;
}
/**
* Gets information about the item and its data item
*/
private String getInformation()
{
return ivText + ": " + ivItemData.toString();
}
}
}
Create a class called ComboData in your tools package, then copy paste the code into it, just below the package statement.
回答2:
One easy way to associate data with combo box items is to use the JFace model-view wrapper ComboViewer
.
Then, set three things, in this order:
- A content provider, which specifies how to get elements out of the
input you provide next. (Frequently, this is just an
ArrayContentProvider
, for models that are either an array or collection.) - The model to use as input. Each element in your model can have a reference to arbitrary user data.
- A label provider that provides labels for elements.
For example:
myCombo.setContentProvider(new ArrayContentProvider());
myCombo.setInput( myModel );
myCombo.setLabelProvider(new LabelProvider() {
@Override
public String getText(Object element) { ... }
});
Once you've done that, there are mechanisms to get the selected element -- or you can get the wrapped Combo
, ask it for its selected index, and use that index to access an element of your model.
来源:https://stackoverflow.com/questions/62477570/how-to-easily-get-a-data-reference-from-an-swt-combo-drop-list