JCombobox display text according to value - java

I have combobox which is filled with some items. Each item have display member and value member:
Vector model = new Vector();
model.addElement(new FilterValue("10000 Hz", 0));
model.addElement(new FilterValue("5000 Hz", 1));
model.addElement(new FilterValue("1000 Hz", 5));
model.addElement(new FilterValue("100 Hz", 50));
model.addElement(new FilterValue("10 Hz", 500));
model.addElement(new FilterValue("1 Hz", 5000));
public class FilterValue {
private final String label;
private final int value;
public FilterValue(String label, int value) {
this.label = label;
this.value = value;
}
public String getLabel() {
return label;
}
public int getValue() {
return value;
}
public String toString()
{
return label;
}
}
Initialization of JComboBox
cbFilter1 = new JComboBox(model);
cbFilter1.setBounds(176, 70, 90, 20);
cbFilter1.setSelectedIndex(-1);
pnlOUT1.add(cbFilter1);
cbFilter1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox comboBox = (JComboBox)e.getSource();
FilterValue item = (FilterValue)comboBox.getSelectedItem();
System.out.println( item.getValue() + " : " + item.getLabel() );
}
});
When I select for example 5000 Hz, display text is 5000 Hz, and value is 1.
The question is how to set value for example 5 and display 1000 Hz?
I have tried with
cbFilter1.setSelectedItem(5);
But there is no effect.

So you basically want to select the items either by their value or by their label.
The first (and simplest) thing I could think of to achieve this, is to create a Map object with the FilterValue as value. With this mapping you can simply use setSelectedItem on the ComboBox.
First copy the elements from your Vector:
Map<Integer, FilterValue> valueMap = new HashMap<>();
Map<String, FilterValue> labelMap = new HashMap<>();
model.forEach(filter -> {
valueMap.put(filter.getValue(), filter);
labelMap.put(filter.getLabel(), filter);
});
Then you could do something like this
String label = "5000 Hz";
cbFilter1.setSelectedItem(labelMap.get(label));
or this
int value = 5;
cbFilter1.setSelectedItem(valueMap.get(value));
It is then your choice how to collect the value (or label) of the FilterValue (maybe a JTextField or whatever)

Change your selected item:
cbFilter1 = new JComboBox(model);
cbFilter1.setBounds(176, 70, 90, 20);
cbFilter1.setSelectedIndex(5); // EDITED
pnlOUT1.add(cbFilter1);
cbFilter1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JComboBox comboBox = (JComboBox)e.getSource();
FilterValue item = (FilterValue)comboBox.getSelectedItem();
System.out.println( item.getValue() + " : " + item.getLabel() );
}
});

So you want the select a row by passing an existing value or label ?
The method setSeletedIndex(int index) expects an int corresponding of the number of the row (here, from 0 to 5).
You could use the method setSelectedItem(Object obj) to select the wanted FilterValue object.
Here is a simple method to help you select the correct FilterValue object from a given value :
/* Could do the same for label, using val.getLabel()
* and passing a String in parameter
*/
public void selectByValue(int value){
FilterValue row = null;
for(FilterValue val : model){ //Searching for the corresponding FilterValue
if(val.getValue() == value){
row = val;
}
}
cbFilter1.setSelectedItem(row); //Select the corresponding row
}
When calling this method like this
this.selectByValue(5);
It will search for the FilterValue in your Vector that have the value "5" and select the row of this object. This expects you don't have any values twice or it would select the first that appears.
Tested, and worked ;)
Hope it helped !

Thanks to all, I've found one solution that works fine in my case:
public static void setSelectedValue(JComboBox comboBox, int value)
{
FilterValue item;
for (int i = 0; i < comboBox.getItemCount(); i++)
{
item = (FilterValue)comboBox.getItemAt(i);
if (item.getValue() == value)
{
comboBox.setSelectedIndex(i);
break;
}
}
}

Related

Upon loading JTable dynamically, before selected JComboBox appears visible

I use:
Java 10 SE
Java Swing
Eclipse IDE
I have JTable, the contents gets loaded at runtime dynamically. It has some JComboBoxes. If I select the JComboBox, and then attempt to reload the table, the JComboBox appears visible at the time when the table loading is in progress.
Besides that, if the JComboBox's contents gets updated (elsewhere in different table, when the combo supposed to reflect that new contents), that new contents does not get visible staright away after loading the JTable dynamically.
The snap-shot sample of the app:
That's, the table being loaded at runtime up, and in the middle you have vsisble JComboBox persistent from the previous selection.
How to:
Get rid off that persistent JComboBox
Make the data visible instantly, upon update under the combo, once you load the table dynamically
I have the public final class TableColumnEditor extends DefaultCellEditor{
which returns the JComboBox on a specific column:
else if(row == ROW_2_DEVS_WORK_WEEKEND) {
ProjectMetrics metrics = new ProjectMetrics();
JComboBox<String> combo = new JComboBox<>();
combo.setBackground(Color.WHITE);
for(String devs : metrics.identifyDevsThatWorkAtWeekend()) {
combo.addItem(devs);
}
return combo;
}
I have the public final class TableColumnRenderer extends DefaultTableCellRenderer{
which makes sure that the view displays the JComboBox under that specific column:
else if(row == ROW_2_DEVS_WORK_WEEKEND) {
ProjectMetrics metrics = new ProjectMetrics();
JComboBox<String> combo = new JComboBox<>();
combo.setBackground(Color.WHITE);
for(String devs : metrics.identifyDevsThatWorkAtWeekend()) {
combo.addItem(devs);
break;
}
return combo;
}
The table gets loaded dynamically right here (non-essential things removed):
public static void reloadTableDynamically(JTable metricsTable){
DefaultTableModel model = (DefaultTableModel)metricsTable.getModel();
if(projectData.isEmpty()) {
metricsTable.clearSelection();
int rowCount = model.getRowCount();
for(int item = (rowCount - 1); item >= 0; item--) {
model.removeRow(item);//clears previous rows
}
metricsTable.repaint();
return;
}
model.getDataVector().clear();
int rowCount = constantRows + ((devsTask.size() == 0) ? 1 : devsTask.size());
try {
new Thread(()-> {
int lastRowID = 0;
int devsTaskID = 0;
for(int item = 0; item < rowCount; item++) {
Object[] input = null;
if(item == 0) {
input = new Object[] {"", metrics.getProjectDateRange(), "" };
}//similar branches removed
else {
devsTaskID++;
input = new Object[] {"", devsTask.get(devsTaskID).getDeveloper(), ""};
}
model.addRow(input);
metricsTable.scrollRectToVisible(new java.awt.Rectangle(metricsTable.getCellRect(lastRowID++, 0, true)));
metricsTable.repaint();
try {
Thread.sleep(Config.getInstance().getReloadInOutTable());
}
catch(InterruptedException e) {
e.printStackTrace();
}
}
metricsTable.scrollRectToVisible(new java.awt.Rectangle(metricsTable.getCellRect(projectData.size() - 1, 0, true)));
metricsTable.repaint();//so that to reach the last row
}).start();
}
catch(Exception e) {
}
}
What do you think?
Well, I figured out how to overcome this problem.
Firstly, the JComboBox gets updated on EDT(Event Despatch Thread).
/**
* #param combo The JComboBox ref.
* #param toDisplay The value to add to it
*/
public static void updateComboBoxOnEventDespatchThread(JComboBox<String> combo, String toDisplay) {
Runnable doComboUpdate = new Runnable() {
public void run() {
combo.addItem(toDisplay);
}
};
SwingUtilities.invokeLater(doComboUpdate);
}
Under the JTable column editor:
else if(row == ROW_2_DEVS_WORK_WEEKEND) {
ProjectMetrics metrics = new ProjectMetrics();
JComboBox<String> combo = new JComboBox<>();
combo.setBackground(Color.WHITE);
Runnable doComboInsert = new Runnable() {
public void run() {
int id = 0;
for(String devs : metrics.identifyDevsThatWorkAtWeekend()) {
UIutils.updateComboBoxOnEventDespatchThread(combo, "("+ ++id +") " + devs);
}
}
};
SwingUtilities.invokeLater(doComboInsert);
return combo;
}
But the main fix, without which both issues do not go away, is following.
That is, I noticed that in order for data to appear under the table instantly, firstly, you need to select any other unrelated table's cell.
That is, the Java thread, which loads the JTable at runtime, does need to have this:
if(model.getRowCount() > 0) {
metricsTable.selectAll();
}
That's probably a hack, but it works for me!

How to sort JTable alphabetically separated by first letter? [see picture for clarification]

How to sort JTable alphabetically with separated lines showing the occurrence of the next letter? For example, consider how Windows Media Player 12 sorts it tracks,
Another example of this problem is for instance how Macintosh 'Finder' sorts recent opening applications by date. I can't figure out how they added additional row showing the date and lines enclosing the matching.
Any ideas of how to approach this problem?
Macintosh, Finder, example
To have the table rows appear in a place other than where JTable normally expects them to be, the methods in JTable you’ll need to override are rowAtPoint, getCellRect, and of course, paintComponent. To support those methods, I would keep track of the rows where section headings occur in a sorted Map, and I would keep track of the row positions in a second sorted Map.
I would then recompute those Maps whenever the table model or sort column changes, or whenever the table validates itself for any reason, which means override the tableChanged, sortedChanged, and validate methods, respectively.
The result isn’t as lengthy as you might expect:
public class SectionedTable
extends JTable {
private static final long serialVersionUID = 1;
private final NavigableMap<Integer, String> sectionHeadings =
new TreeMap<>();
private final NavigableMap<Integer, Integer> rowTopEdges =
new TreeMap<>();
// Used when calling SwingUtilities.layoutCompoundLabel.
private final Rectangle iconBounds = new Rectangle();
private final Rectangle textBounds = new Rectangle();
public SectionedTable() {
init();
}
public SectionedTable(TableModel model) {
super(model);
init();
}
private void init()
{
setShowGrid(false);
setAutoCreateRowSorter(true);
recomputeSections();
recomputeRowPositions();
}
private void recomputeSections() {
if (sectionHeadings == null) {
return;
}
sectionHeadings.clear();
RowSorter<? extends TableModel> sorter = getRowSorter();
if (sorter == null) {
return;
}
for (RowSorter.SortKey key : sorter.getSortKeys()) {
SortOrder order = key.getSortOrder();
if (order != SortOrder.UNSORTED) {
int sortColumn = key.getColumn();
String lastSectionStart = "";
int rowCount = getRowCount();
for (int row = 0; row < rowCount; row++) {
Object value = getValueAt(row, sortColumn);
if (value == null) {
value = "?";
}
String s = value.toString();
if (s.isEmpty()) {
s = "?";
}
String sectionStart = s.substring(0,
s.offsetByCodePoints(0, 1));
sectionStart = sectionStart.toUpperCase();
if (!sectionStart.equals(lastSectionStart)) {
sectionHeadings.put(row, sectionStart);
lastSectionStart = sectionStart;
}
}
break;
}
}
}
private void recomputeRowPositions() {
if (rowTopEdges == null) {
return;
}
rowTopEdges.clear();
int y = getInsets().top;
int rowCount = getRowCount();
int rowHeight = getRowHeight();
for (int row = 0; row < rowCount; row++) {
rowTopEdges.put(y, row);
y += getRowHeight(row);
if (sectionHeadings.containsKey(row)) {
y += rowHeight;
}
}
}
#Override
public void tableChanged(TableModelEvent event) {
recomputeSections();
recomputeRowPositions();
super.tableChanged(event);
}
#Override
public void sorterChanged(RowSorterEvent event) {
recomputeSections();
recomputeRowPositions();
super.sorterChanged(event);
}
#Override
public void validate() {
super.validate();
recomputeRowPositions();
}
#Override
public int rowAtPoint(Point location) {
Map.Entry<Integer, Integer> entry = rowTopEdges.floorEntry(location.y);
if (entry != null) {
int row = entry.getValue();
return row;
}
return -1;
}
#Override
public Rectangle getCellRect(int row,
int column,
boolean includeSpacing) {
Rectangle rect = super.getCellRect(row, column, includeSpacing);
int sectionHeadingsAbove = sectionHeadings.headMap(row, true).size();
rect.y += sectionHeadingsAbove * getRowHeight();
return rect;
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
boolean ltr = getComponentOrientation().isLeftToRight();
int rowHeight = getRowHeight();
FontMetrics metrics = g.getFontMetrics();
int ascent = metrics.getAscent();
for (Map.Entry<Integer, String> entry : sectionHeadings.entrySet()) {
int row = entry.getKey();
String heading = entry.getValue();
Rectangle bounds = getCellRect(row, 0, true);
bounds.y -= rowHeight;
bounds.width = getWidth();
bounds.grow(-6, 0);
iconBounds.setBounds(0, 0, 0, 0);
textBounds.setBounds(0, 0, 0, 0);
String text = SwingUtilities.layoutCompoundLabel(this,
metrics, heading, null,
SwingConstants.CENTER, SwingConstants.LEADING,
SwingConstants.CENTER, SwingConstants.CENTER,
bounds, iconBounds, textBounds, 0);
g.drawString(text, textBounds.x, textBounds.y + ascent);
int lineY = textBounds.y + ascent / 2;
if (ltr) {
g.drawLine(textBounds.x + textBounds.width + 12, lineY,
getWidth() - getInsets().right - 12, lineY);
} else {
g.drawLine(textBounds.x - 12, lineY,
getInsets().left + 12, lineY);
}
}
}
}
You can adapt this class to make a Finder table, by changing how the headings are derived from the data. Merely examining one cell with getValueAt won’t be sufficient; instead, you’ll need to translate the sorted row to the corresponding model row, and obtain the data object for that row directly from the TableModel. Then you can compare the rows by age rather than by string data.
I would group my data alphabetically and then create a separate table for each letter included in my data.
You can customize the display of the header using a TableCellRenderer to get the desired look, if you are looking to add more columns as shown in your examples you can replace the header with a different component altogether.
public class MyTableFrame extends JFrame {
MyTableFrame() {
List<String> data = Arrays.asList(
"Alpha1",
"Beta1",
"Alpha2",
"Charlie2",
"Alpha3",
"Beta2",
"Charlie1"
);
// Sort alphabetically
data.sort(String::compareTo);
// Group by first letter
Map<Character, List<String>> collect = data.stream()
.collect(Collectors.groupingBy(string -> string.charAt(0)));
JPanel tablesContainer = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
c.fill = GridBagConstraints.BOTH;
c.weightx = 1;
c.weighty = 0;
c.gridy = 0;
// Create a table for each Letter
collect.entrySet().forEach(mapEntry -> {
Character letter = mapEntry.getKey();
List<String> startingWithLetter = mapEntry.getValue();
TableModel tableModel = new TableModel(startingWithLetter, letter);
JTable table = new JTable(tableModel);
// Table header must be added separately since there is no scroll pane
JTableHeader tableHeader = table.getTableHeader();
tablesContainer.add(tableHeader, c);
c.gridy++;
tablesContainer.add(table, c);
c.gridy++;
});
add(tablesContainer);
setVisible(true);
pack();
}
static class TableModel extends AbstractTableModel {
private List<String> data;
private Character columnName;
TableModel(List<String> data, Character columnName) {
this.data = data;
this.columnName = columnName;
}
#Override
public String getColumnName(int column) {
return columnName.toString();
}
#Override
public int getRowCount() {
return data.size();
}
#Override
public int getColumnCount() {
return 1;
}
#Override
public Object getValueAt(int rowIndex, int columnIndex) {
return data.get(rowIndex);
}
}
public static void main(String args[]) {
new MyTableFrame();
}
}

Upgrade the Items of JCombobox

I want to upgrade the list items of myComboBox when I click a row in myJtabel. I did what I must do to have a good result. But when a unpgrade myComboBox I have a true as a last item and every time I have done an upgrade adds a true as item
What it does not go in my class
myUpgradeCombo :
class myUpgradeCombo {
public static <E> void upgrade_(JComboBox<E> combo, int index)
{
E item = combo.getItemAt(index);
combo.removeItemAt(index);
combo.insertItemAt(item, 0);
combo.setSelectedIndex(0);
}
public static <E> boolean upgrade(JComboBox<E> combo, E item)
{
for (int index=0; index<combo.getItemCount(); index++)
{
if (combo.getItemAt(index).toString().equals(item.toString()))
{
upgrade_(combo,index);
return true;
}
}
return false ;
}
}
when myJtable Mouse pressed :
int rec = myJtableF.getSelectedRow();
String idf = myJtableF.getValueAt(rec, 1).toString();
String format = myJtableF.getValueAt(rec, 2).toString();
String platef = myJtableF.getValueAt(rec, 3).toString();
this.myCombo.addItem(myUpgradeCombo.upgrade(myCombo, new FC(format,platef,idf)));
As result in myCombo :
...... MySelectedItem
.......Firstitem
.......SecondItem
.......ThirdItem
.......fourthItem
.......true
.......true
Thanks,
Well because the return value of your myUpgradeCombo.upgrade(myCombo, new FC(format,platef,idf)) is passed to this.myCombo.addItem().
So the true returned from upgrade() is added as an item to your combo box, in this line:
this.myCombo.addItem(myUpgradeCombo.upgrade(myCombo, new FC(format,platef,idf)));

ItemListener itemStateChanged does not change when choosing an index with the same content

For example i have a JComboBox with values :
{"weapon","armor","weapon"}
If currently selected index is 0 (weapon) and I select index 2 (weapon), it does not trigger an ItemStateChanged in my ItemListener. Although if currently selected index is 0 and I select index 1, it triggers an ItemStateChanged.
Here is my code as of now:
class CBListener implements ItemListener{
#Override
public void itemStateChanged(ItemEvent e){
JComboBox temp = (JComboBox) e.getSource();
int wordIndex = temp.getSelectedIndex(); // index of selected string in the list
int row = sTable.getSelectedRow(); // row of the cell
int col = sTable.getSelectedColumn(); // column of the cell
sTable.setValueAt(listE.get(row)[wordIndex], row, 0);
//System.out.println(listE.get(row)[wordIndex]);
sTable.setValueAt(listI.get(row)[wordIndex], row, 1);
sTable.setValueAt(listD.get(row)[wordIndex], row, 3);
}
}
How can I modify my code so that I can get an index similar to index 2 in my example?
I would still recommend some differentiation between the two items, but if you really want them to be the same, I think you'll have to create an object that has a toString value of "weapon", but for which an equals returns false. Something like:
public BuyableItem( String description, int index ) {
:
:
}
public String toString() {
return this.description;
}
public boolean equals( BuyableItem item ) {
boolean retVal = this.description.equals( item.description );
if( retVal ) {
retVal = this.index == item.index;
}
return retVal;
}
Then your JComboBox values could be
{ new BuyableItem( "weapon", 0 ), new BuyableItem( "armor", 1 ), new BuyableItem( "weapon", 2 ) };

JComboBox setSelectedItem does not work

I am trying to set the setSelectedItem of the JComboBox in the constructor of my JPanel class just after populating the combobox.
I am set the value for textbox, but I can't figure out why setSelectedItem does not seem to work. Any ideas?
public StudentProfilePanel(StudentInfo si) {
yesButton.setBounds(50, 346, 69, 40);
noButton.setBounds(121, 346, 56, 40);
this.add(yesButton);
this.add(noButton);
setLayout(null);
comboBoxYear.setModel(new DefaultComboBoxModel(years()));
comboBoxYear.setBounds(202, 365, 62, 23);
if(si.birthdate!=null){
//System.out.println("year value : ["+dateofbirth(si.birthdate)[2]+"]");
comboBoxYear.setSelectedItem(dateofbirth(si.birthdate)[2]);
}
add(comboBoxYear);
comboBoxMonth.setModel(new DefaultComboBoxModel(new String[]{"01","02","03","04","05","06","07","08","09","10","11","12"}));
comboBoxMonth.setBounds(285, 365, 56, 23);
//set month value
if(si.birthdate!=null){
//comboBoxMonth.setSelectedItem(dateofbirth(si.birthdate)[1]);
comboBoxMonth.setSelectedItem("04");
System.out.println("month value : ["+dateofbirth(si.birthdate)[1]+"]");
}
add(comboBoxMonth);
comboBoxDay.setModel(new DefaultComboBoxModel(days()));
comboBoxDay.setBounds(351, 365, 54, 23);
if(si.birthdate!=null){
//comboBoxDay.setSelectedItem(dateofbirth(si.birthdate)[0]);
comboBoxDay.setSelectedItem(dateofbirth(si.birthdate)[0]);
}
add(comboBoxDay);
textFieldFirstName = new JTextField();
textFieldFirstName.setBounds(21, 321, 171, 21);
add(textFieldFirstName);
textFieldFirstName.setColumns(10);
// set the value of first name
textFieldFirstName.setText(si.firstName);
textFieldLastName = new JTextField();
textFieldLastName.setBounds(242, 321, 163, 21);
add(textFieldLastName);
textFieldLastName.setColumns(10);
//set the value of the last name
textFieldLastName.setText(si.lastName);
JPanel panelPersonPhoto = new ImagePanel(
"C:\\Users\\MDJef\\Pictures\\Wallpaper\\General\\11.jpg");
panelPersonPhoto.setBorder(new TitledBorder(null, "",
TitledBorder.LEADING, TitledBorder.TOP, null, null));
panelPersonPhoto.setBounds(21, 20, 384, 291);
add(panelPersonPhoto);
}
Thanks very much.
helper methods that I used
// jf : helper method
public String[] years() {
String[] results = new String[90];
for (int i = 0; i < 90; i++) {
results[i] = Integer.toString(1900 + i);
}
return results;
}
// jf : helper method
public String[] months() {
String[] results = new String[12];
for (int i = 0; i < 12; i++) {
results[i] = Integer.toString(i + 1);
}
return results;
}
// jf : helper method
public String[] days() {
String[] results = new String[31];
for (int i = 0; i < 31; i++) {
results[i] = Integer.toString(i + 1);
}
return results;
}
// jf : helper method
public String[] dateofbirth(String dob) {
String[] tokens = dob.split("-");
return tokens;
}
The values assigned to the combo box are not the same values you are trying set.
For example, the years are Strings from 1900 - 1990, but if I supply a value 72, there is no matching value in the combo box to match to.
Equally, your days and months methods are only returning values that are not padded (ie 01), where as, in your code, you're trying to set the value using a padded value (ie 04), meaning there is no matching value...
You have a number of options...
You could...
Convert all the values to an int, meaning that the values in the combo box are simply ints. You would then need to convert the date values to ints as well.
This would make your helper code look more like...
public int[] years() {
int[] results = new String[90];
for (int i = 0; i < 90; i++) {
results[i] = 1900 + i;
}
return results;
}
public int[] months() {
int[] results = new String[12];
for (int i = 0; i < 12; i++) {
results[i] = i + 1;
}
return results;
}
public int[] days() {
int[] results = new String[31];
for (int i = 0; i < 31; i++) {
results[i] = i + 1;
}
return results;
}
public int[] dateofbirth(String dob) {
int[] tokens = dob.split("-");
int[] values = new int[tokens.length];
for (int index = 0; index < tokens.length; index++) {
values[index] = Integer.parse(tokens[index]);
}
return index;
}
A better solution
Would be to use a JSpinner, which would take care of date rolling issues and validation automatically.
Check out Using Standard Spinner Models and Editors
Not related to your problem, but:
yesButton.setBounds(50, 346, 69, 40);
noButton.setBounds(121, 346, 56, 40);
setLayout(null);
Don't use a null layout and setBounds(...). Swing was designed to be used with Layout Manager. In the long run you will save time.
if(si.birthdate!=null){
Don't access variables in your class directly. Create a getter method to access the properties of your class.
//System.out.println("year value : ["+dateofbirth(si.birthdate)[2]+"]");
comboBoxYear.setSelectedItem(dateofbirth(si.birthdate)[2]);
Don't always try to force you code into a single statement. Instead do something like:
String birthdate = dateofbirth(si.birthdate[2]);
System.out.println("year value : [" + birthdate +"]");
comboBoxYear.setSelectedItem(birthdate);
This helps with your debugging because now you know that the variable you display is the same variable that you are trying to use in the setSelectedItem() method. It saves typing the statement twice and avoids typing mistakes.
When you call comboBoxMonth.setSelectedItem("04"); you try to select a newly created String which is not equal to the one which is in your JComboBox. Ergo it does not get selected.
You can try something like this instead:
String[] months = new String[] {"01","02","03","04","05","06","07","08","09","10","11","12"};
comboBoxMonth.setModel(new DefaultComboBoxModel(months));
comboBoxMonth.setSelectedItem(months[3]);
Edit: Try this. It uses the index of the item instead. Just make sure you add the months in order to the array.
String[] months = new String[] {"01","02","03","04","05","06","07","08","09","10","11","12"};
comboBoxMonth.setModel(new DefaultComboBoxModel(months));
if(si.birthdate!=null)
{
comboBoxMonth.setSelectedIndex(Integer.parseInteger(dateofbirth(si.birthdate)[1]) - 1);
}
For other developer with the same issue:
A closer look into the implementation of setSelectedItem(Object anObject) from JComboBox might help:
public void setSelectedItem(Object anObject) {
Object oldSelection = selectedItemReminder;
Object objectToSelect = anObject;
if (oldSelection == null || !oldSelection.equals(anObject)) {
if (anObject != null && !isEditable()) {
// For non editable combo boxes, an invalid selection
// will be rejected.
boolean found = false;
for (int i = 0; i < dataModel.getSize(); i++) {
E element = dataModel.getElementAt(i);
if (anObject.equals(element)) {
found = true;
objectToSelect = element;
break;
}
}
if (!found) {
return;
}
}
...
In the loop your object is compared with an object of the dataModel with the specific type E. In the implementation of equals() from String you can see a verification of class/interface, length and each character one after another. That means, our object must have same type and all characters must be the same!
public boolean equals(Object anObject) {
if (this == anObject) {
return true;
}
if (anObject instanceof String) {
String anotherString = (String)anObject;
int n = value.length;
if (n == anotherString.value.length) {
char v1[] = value;
char v2[] = anotherString.value;
int i = 0;
while (n-- != 0) {
if (v1[i] != v2[i])
return false;
i++;
}
return true;
}
}
return false;
}
And this is the most annoying part if (anObject.equals(element)) in setSelectedItem! You cant override equals method from your element. For example StudentInfo and compare other types like strings or integers to it. Simple example. You implement combobox like this JComboBox<StudentInfo> and you want to select the student with int id = 2;. So it compares now Integer with StudentInfo. Here you have to override equals from Integer...
My proposal is to swap it. Create own class, add boolean selectingItem and override setSelectedItem(Object anObject) and contentsChanged(ListDataEvent e)(this method one-to-one). Nevertheless, I had side effects in one project...
Use the following:
comboBoxMonth.setSelectedItem(index of the array);
The item you wish to set as selected must share the class of the objects stored in the JComboBox.
public static void main(String[] args) {
String[] items = {"1", "2", "3"};
JComboBox jcb = new JComboBox(items);
jcb.setSelectedItem(3);
System.out.println(jcb.getSelectedItem());
jcb.setSelectedItem(3+"");
System.out.println(jcb.getSelectedItem());
}
Output of the above code:
1
3

Categories