Checking if an item already exists in a JComboBox? - java

Is there an easy way to check if an item already exists in a JComboBox besides iterating through the latter? Here's what I want to do:
Item item = ...;
boolean exists = false;
for (int index = 0; index < myComboBox.getItemCount() && !exists; index++) {
if (item.equals(myComboBox.getItemAt(index)) {
exists = true;
}
}
if (!exists) {
myComboBox.addItem(item);
}
Thanks!

Use a DefaultComboBoxModel and call getIndexOf(item) to check if an item already exists. This method will return -1 if the item does not exist. Here is some sample code:
DefaultComboBoxModel model = new DefaultComboBoxModel(new String[] {"foo", "bar"});
JComboBox box = new JComboBox(model);
String toAdd = "baz";
//does it exist?
if(model.getIndexOf(toAdd) == -1 ) {
model.addElement(toAdd);
}
(Note that under-the-hood, indexOf does loop over the list of items to find the item you are looking for.)

Check with this:
if(((DefaultComboBoxModel)box.getModel()).getIndexOf(toAdd) == -1) {
box.addItem(toAdd );
}
or
if(((DefaultComboBoxModel)box.getModel()).getIndexOf(toAdd) < 0) {
box.addItem(toAdd );
}

Update:
myComboBox.setSelectedIndex(-1);
String strItem="exists";
myComboBox.setSelectedItem(strItem);
if(myComboBox.getSelectedIndex()>-1){
//exists
}

Related

Find anywhere in jList items?

I can find item in jlist with this code. But I want to find anywhere in item. How can I do this. Thanks a lot. (Sorry my English)
For example: I can find "New or San" but I want to find "York or Diago".
New York
San Diago
jTextField1.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
String text = "" + e.getKeyChar();
StringBuffer buffer = new StringBuffer(jTextField1.getText().substring(0, jTextField1.getText().length() - 1));
buffer.append(text);
int index = jList1.getNextMatch(buffer.toString(), 0, Position.Bias.Forward);
jList1.setSelectedIndex(index);
}
});
getNextMatch checks if the given string exists at the start position passed as the second param. You can just traverse the jlist to find the index.
jTextField1.addKeyListener(new KeyAdapter() {
public void keyReleased(KeyEvent e) {
String text = "" + e.getKeyChar();
StringBuffer buffer = new StringBuffer(jTextField1.getText().substring(0, jTextField1.getText().length() - 1));
buffer.append(text);
ListModel<String> model = jList1.getModel();
int index;
for(int i = 0; i < model.getSize(); i++) {
if(model.getElementAt(i).contains(buffer.toString())){
index = i;
break;
}
}
jList1.setSelectedIndex(index);
}
});
I believe the method available in JList only searches if the items start with a specific prefix.
public List<Integer> getMatches(ListModel listModel, String text){
List<Integer> indices = new List<Integer>();
for(int i = 0; i < listModel.getSize(); i++){
if(listModel.getElementAt(i).contains(text)){
indices.add(i);
}
}
return indices;
}
The method above iterates the listmodel and checks if each element contains the text provided and returns the indices of matched items.

Linked list looping and addfirst

Why this is not working? I am looping on a trxFifoArray List and passing its object items to result List. I need to split some amounts in 2 so I need to addFirst this 2 amount to result list. The amounts are in an arrayList [-9.0000, -6.0000]. So I loop the amount list to do the addFirst on result and the items are added but with same amount even the list has 2 different amount.
LinkedList<InvtQaTracer> trxFifoArray = new LinkedList<InvtQaTracer>();
LinkedList<InvtQaTracer> result = new LinkedList<InvtQaTracer>();
InvtQaTracer trx = new InvtQaTracer();
int trxDocoRef = 0;
for (int j = list.size() - 1; j >= 0; j--) {
trx = list.get(j);
System.out.printf("%12.4f %4s%10d %12s%n", trx.getTrxQty(), trx.getDocType(), trx.getOrdNo(), trx.getLocNo());
List<BigDecimal> auxAmounts = new ArrayList<BigDecimal>();
if (trx.getDocType().compareTo("OV") == 0
|| trx.getDocType().compareTo("XV") == 0) {
//Do something ...
} else {
BigDecimal auxAmount = BigDecimal.ZERO;
Boolean needRemove = false;
for (InvtQaTracer tFifo : trxFifoArray) {
if (trx.getDocType().compareTo("IT") == 0) {
auxAmounts.add(tFifo.getTrxQty().negate());
}
}
if (needRemove) {
Iterator<InvtQaTracer> iterator = trxFifoArray.iterator();
int count = 0;
while (iterator.hasNext()) {
InvtQaTracer iqt = iterator.next();
if (iqt.getTrxQty().compareTo(BigDecimal.ZERO) == 0) {
count++;
iterator.remove();
}
}
}
}
if (!auxAmounts.isEmpty()) {
for (BigDecimal asss : auxAmounts) {
System.out.println(asss);
trx.setTrxQty(asss);
result.addFirst(trx);
}
} else {
result.addFirst(trx);
}
for (InvtQaTracer invtQT : trxFifoArray) {
System.out.printf("%20s%2s%12.4f %10d %12s%10d%n", " ----------------> ", invtQT.getDocType(), invtQT.getTrxQty(), invtQT.getOrdNo(), invtQT.getLocNo(), invtQT.getDocNo());
}
}
This code add two records with -6.000000 value even it is printing out both of them. I hope you understand the code. Please Help!!!
Thanks.
Thanks for any help!
Am finding a problem in the code.
Code needs to be updated like this
if (!auxAmounts.isEmpty()) {
LinkedList<InvtQaTracer> result = new LinkedList<InvtQaTracer>();
//Updated Here
InvtQaTracer trx = null;
List<BigDecimal> auxAmounts = new ArrayList<BigDecimal>(); //[-9.000000, -6.000000]
for (BigDecimal asss : auxAmounts) {
System.out.println(asss);
//Updated Here
trx = new InvtQaTracer();
trx.setTrxQty(asss);
result.addFirst(trx);
}
} else {
result.addFirst(trx);
}
One more change identified is
inside the else loop needRemove value is set to false by default and below checking whether it is true in if loop. think this one can be removed.

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

Add Multiple Elements to ListModel using Combo box

I want to add multiple elements to JList using JComboBox. When user select an item from the JComboBox, it should add to JList. If the item already exists in the List message should pop up to notify that. How do I do this?
private void cmbBagSizeItemStateChanged(java.awt.event.ItemEvent evt) {
DefaultListModel listModel = new DefaultListModel();
lstBagSize.setModel(listModel);
if ((evt.getStateChange() == ItemEvent.SELECTED)) {
if (listModel.getSize() != 0) {
for (int i = 0; i < listModel.getSize(); i++) {
listModel.addElement(cmbBagSize.getModel().getSelectedItem());
break;
}
} else {
listModel.addElement(cmbBagSize.getModel().getSelectedItem());
}
}
}
I managed to find the solution to above issue. I used method called contains to check where any duplicates exists.
DefaultListModel listModel = new DefaultListModel();
if (listModel.contains(this.cmbBagSize.getSelectedItem())) {
JOptionPane.showMessageDialog(null, "Duplicate");
} else {
listModel.addElement(this.cmbBagSize.getSelectedItem());
this.lstBagSize.setModel(listModel);
}

In Java/Swing, is there a way to legally "attempt to mutate in notification"?

I was wondering if there is some sort of magic I can use to get around an IllegalStateException and allow a JTextField to "attempt to mutate in notification", or in other words to set its own text if its listener is triggered.
For your information, I am trying to program an auto-complete function which returns the most likely match in a range of 12 enums in response to a user's input in the JTextField.
Here is the code sample. You'll have to pardon my clumsy algorithm which creaks out enum results. I've highlighted the code which produces the exception with a comment:
jtfElement1.addCaretListener(new CaretListener() {
#Override
public void caretUpdate(CaretEvent e) {
String s = jtfElement1.getText();
int[] attributes = new int[13];
// iterate through each enum
for (BaseEnumAttributes b: BaseEnumAttributes.values()) {
// iterate through the length of the current text in jtfElement1
for (int i = 0; i < s.length(); i++) {
if (s.length() <= b.toString().length()) {
if (b.toString().charAt(i) == s.charAt(i)) {
// increase the number of "hits" noted for that enum
attributes[b.ordinal()] = attributes[b.ordinal()] + 1;
}
}
}
}
int priorC = 0;
int rightC = 0;
// iterate through the "array" of enums to find the highest score
for (int j = 0; j < attributes.length; j++) {
if (attributes[j] > priorC) {
priorC = attributes[j];
rightC = j;
}
}
if (!s.equals("")) {
// assign to b the Enum corresponding to the "array" with highest score
BaseEnumAttributes b = BaseEnumAttributes.values()[rightC];
iController.updateInputElement1String(b.toString());
// THIS TRIGGERS EXCEPTION
jtfElement1.setText(b.toString());
}
}
});
You are probably better off using a document filter or a custom document.
What are other listeners expected to see if the document doesn't stay the same during event dispatch?
Use SwingUtilities.invokeLater() placing all the modifications there
Maybe you can delay the setText() with a Thread to run after caretUpdate() has terminated.
i'm found on the same problem but i found an easy solution:
lock the caretUpdate() by a boolean if(false) while u'r setting the text to the jTextField than unlock it after . . something like this:
boolean caret = true;
private void listValueChanged(javax.swing.event.ListSelectionEvent evt) {
caret = false;
name.setText((String)list.getSelectedValue());
caret = true;
}
private void nameCaretUpdate(javax.swing.event.CaretEvent evt) {
if(caret){
model = new DefaultListModel();
this.fillList(name.getText());
list.setModel(model);
}
}
Create a custom Document and override insertString( )
filenameText = new JTextField(new FilenameDocument(), "", 0);
...
/**
* document which adds .xml extension if not specified
*
*/
private class FilenameDocument extends PlainDocument {
#Override
public void insertString(int offset, String insertedText, AttributeSet set)
throws BadLocationException {
if (offset == 0) {
insertedText = insertedText.trim( );
}
super.insertString(offset, insertedText, set);
if (filenameText != null) {
final int caretPos = filenameText.getCaretPosition();
String text = filenameText.getText().trim();
if (text.indexOf('.') == -1) {
filenameText.setText(text + ".xml");
filenameText.setCaretPosition(caretPos);
}
}
}
}
Note that calling setText will result in a recursive call to insertString( ), so make sure you have a stopping condition.
I'm surprised no one has answered this, but would'nt you have been better off implementing an editable JSpinner with a SpinnerListModel?

Categories