Discussion:
Long delay when using JComboBox.setSelectedIndex() ??
(too old to reply)
k***@gmail.com
2012-12-05 17:27:59 UTC
Permalink
Hello,

I am attempting to load 5000 employee items into a jcombobox, and then setSelectedIndex, but I am getting a odd delay in the gui after setting the selectedIndex

1) If I load the 5000 employee names using a simple vector, it works fine. When I call setSelectedIndex(5), it sets the combobox to the 5th element, very quickly. This works fine:

while ((line = input.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
comboBoxItems.add(lastName);}

mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);


2)HOWEVER, if I load an employee object into a mapped vector, and then setSelectedIndex(5), I DO see it instantly set the GUI combobox to the 5th item, BUT then there is a LOOOONG delay in the gui (1 minute or more) before it allows me to do anything further in the gui

while ((line = input.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
empBuffer= new Employee(id, lastName );
map.put(empBuffer.getId()+"",empBuffer );
count++; }

model.addAll(map.values());
Collections.sort(model);
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);


public class Employee implements Comparable {
private int id;
private String name;

public Employee(int id, String name) {
this.id = id;
this.name = name;
}

public String getName() {
return name;
}

public int getId() {
return id;
}

public int compareTo(Object emp) {
return getName().compareTo(((Employee)emp).getName());
}

public String toString() {
return getName()+","+getId();
}
}
k***@gmail.com
2012-12-05 18:08:13 UTC
Permalink
CORRECTION, both examples have the same problem. I thought the first example was working, but in each case AFTER I call setSelectedIndex, the GUI DOES quickly go to the item in the combobox , but then the whole gui hangs for about a minute ???? Why? If I replace the combobox with a jtextfield, it works without delay...
Lew
2012-12-05 18:35:50 UTC
Permalink
Post by k***@gmail.com
I am attempting to load 5000 employee items into a jcombobox, and then setSelectedIndex, but I am getting a odd delay in the gui after setting the selectedIndex
1) If I load the 5000 employee names using a simple vector, it works fine. When I call
'vector' or "vector" or 'Vector'?
Post by k***@gmail.com
while ((line = input.readLine()) != null) {
This is a slow action on the EDT. Bad.
Post by k***@gmail.com
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
'lastName, 'firstName', and 'id' should be declared locally to the loop.
Post by k***@gmail.com
comboBoxItems.add(lastName);}
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);
2)HOWEVER, if I load an employee object into a mapped vector, and then setSelectedIndex(5), I DO
What is a "mapped vector"?
Post by k***@gmail.com
see it instantly set the GUI combobox to the 5th item, BUT then there is a LOOOONG delay in the gui (1 minute or more) before it allows me to do anything further in the gui
while ((line = input.readLine()) != null) {
This is a slow action on the EDT. Bad.
Post by k***@gmail.com
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
empBuffer= new Employee(id, lastName );
'lastName, 'firstName', 'id' and 'empBuffer' should be declared locally to the loop.
Post by k***@gmail.com
map.put(empBuffer.getId()+"",empBuffer );
count++; }
model.addAll(map.values());
Collections.sort(model);
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);
public class Employee implements Comparable {
private int id;
private String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public int compareTo(Object emp) {
return getName().compareTo(((Employee)emp).getName());
}
public String toString() {
return getName()+","+getId();
}
}
You should override 'equals()' to match 'compareTo()' so the model will work right.
Post by k***@gmail.com
CORRECTION, both examples have the same problem. I thought the first example was working, but in each case AFTER I call setSelectedIndex, the GUI DOES quickly go to the item in the combobox , but then the whole gui hangs for about a minute ???? Why? If I replace the combobox with a jtextfield, it works without delay...
How long does 'input.readLine()' take, and why are you doing it on the EDT?

I/O is much slower than CPU activity. You are causing the GUI to wait for 5000 lines of read. Bad.

Don't do it on the EDT.
--
Lew
k***@gmail.com
2012-12-05 18:46:14 UTC
Permalink
Thank you for your input!

I know doing io on the EDT is not optimal, but I was just trying to provide a short code snippet to illustrate the problem. The issue is happening well AFTER I load the employee names from disk. The delay is happening right after I setSelectedIndex(3) on the jcombobox..

Can you show me how to override equals ??

Thank you again!
Ken
Post by Lew
Post by k***@gmail.com
I am attempting to load 5000 employee items into a jcombobox, and then setSelectedIndex, but I am getting a odd delay in the gui after setting the selectedIndex
1) If I load the 5000 employee names using a simple vector, it works fine. When I call
'vector' or "vector" or 'Vector'?
Post by k***@gmail.com
while ((line = input.readLine()) != null) {
This is a slow action on the EDT. Bad.
Post by k***@gmail.com
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
'lastName, 'firstName', and 'id' should be declared locally to the loop.
Post by k***@gmail.com
comboBoxItems.add(lastName);}
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);
2)HOWEVER, if I load an employee object into a mapped vector, and then setSelectedIndex(5), I DO
What is a "mapped vector"?
Post by k***@gmail.com
see it instantly set the GUI combobox to the 5th item, BUT then there is a LOOOONG delay in the gui (1 minute or more) before it allows me to do anything further in the gui
while ((line = input.readLine()) != null) {
This is a slow action on the EDT. Bad.
Post by k***@gmail.com
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
empBuffer= new Employee(id, lastName );
'lastName, 'firstName', 'id' and 'empBuffer' should be declared locally to the loop.
Post by k***@gmail.com
map.put(empBuffer.getId()+"",empBuffer );
count++; }
model.addAll(map.values());
Collections.sort(model);
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);
public class Employee implements Comparable {
private int id;
private String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public int compareTo(Object emp) {
return getName().compareTo(((Employee)emp).getName());
}
public String toString() {
return getName()+","+getId();
}
}
You should override 'equals()' to match 'compareTo()' so the model will work right.
Post by k***@gmail.com
CORRECTION, both examples have the same problem. I thought the first example was working, but in each case AFTER I call setSelectedIndex, the GUI DOES quickly go to the item in the combobox , but then the whole gui hangs for about a minute ???? Why? If I replace the combobox with a jtextfield, it works without delay...
How long does 'input.readLine()' take, and why are you doing it on the EDT?
I/O is much slower than CPU activity. You are causing the GUI to wait for 5000 lines of read. Bad.
Don't do it on the EDT.
--
Lew
Lew
2012-12-05 19:31:16 UTC
Permalink
Post by k***@gmail.com
Thank you for your input!
Thank me by not top-posting.
Post by k***@gmail.com
I know doing io on the EDT is not optimal, but I was just trying to provide a short code snippet to illustrate the problem. The issue is happening well AFTER I load the employee names from disk. The delay is happening right after I setSelectedIndex(3) on the jcombobox..
You don't show that code. Why not?
Post by k***@gmail.com
Can you show me how to override equals ??
Really?

Really?

Okay.

Same as any other method.

You should learn the very basic basics of Java before programming with it.
Overriding methods is far more basic than Swing programming.

/**
* Javadoc comments go here!
*/
public class Employee implements Comparable

// Dude! 'Comparable' is a generic type! DO NOT USE RAW TYPES!

<Employee>
{
private int id; // should be final

// Far too much indentation for Usenet. 2 to 4 spaces per level.

private String name; // should be final

/**
* Javadoc comments go here!
*/
public Employee(int id, String name) {
this.id = id;
this.name = name;
}

/**
* Javadoc comments go here!
*/
public String getName() {
return name;
}

/**
* Javadoc comments go here!
*/
public int getId() {
return id;
}

/**
* Javadoc comments go here!
*/
public int compareTo(Employee emp) {
return getName().compareTo(emp.getName());

// this will throw NullPointerException when getName() returns null
// or when emp == null
// Careless.
}

/**
* Value equality - do equality comparison on the field(s) that represent the
* distinguishing value, usually the same fields used to sort.
* You also need to override {@code hashCode} for consistency.
*
* @param obj Object to compare.
* @return boolean {@code true} iff values are "equal".
*/
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (! (obj instanceof getClass()))
{
return false;
}
Employee other = (Employee) obj;
return name == null? other.name == null : name.equals(other.name);
}

@Override
public int hashCode()
{
return name == null? 0 : name.hashCode();
}

/**
* Javadoc comments go here!
*/
public String toString() {
return getName()+","+getId();
}
}
Roedy Green
2012-12-06 00:16:30 UTC
Permalink
Post by k***@gmail.com
Can you show me how to override equals ??
Thank you again!
just write a method that has the same parms as Object.equals
--
Roedy Green Canadian Mind Products http://mindprod.com
Students who hire or con others to do their homework are as foolish
as couch potatoes who hire others to go to the gym for them.
Lew
2012-12-06 00:34:28 UTC
Permalink
Post by k***@gmail.com
Can you show me how to override equals ??
just write a method that has the same parms [sic] as Object.equals
That is necessary but very far from sufficient.

It has to have the same or compatible signature, not just the same parms.

It should be annotated with '@Override'.

It has to have logic appropriate to the type, so that the semantics of
'equals()' makes sense.

You also left out the part about having 'hashCode()' match.

Your answer is like telling a newbie, "To write a Java program to do what you're
asking, just write a class that has the same form as 'Hello, World'." Except for
being more incorrect.

It also came four hours after an extremely detailed answer with code specific to
the OP's situation that didn't have these lacunae.

But thank you for participating anyway.
--
Lew
Knute Johnson
2012-12-06 00:40:42 UTC
Permalink
Post by Lew
It also came four hours after an extremely detailed answer with code specific to
the OP's situation that didn't have these lacunae.
Lacunae, you must have gone to a good college :-).
--
Knute Johnson
Lew
2012-12-06 00:58:03 UTC
Permalink
Post by Knute Johnson
Post by Lew
It also came four hours after an extremely detailed answer with code specific to
the OP's situation that didn't have these lacunae.
Lacunae, you must have gone to a good college :-).
SUNY at Stony Brook, an excellent institution of higher learning.

But the real culprit is my penchant for sesquipedalianism.
--
Lew
Roedy Green
2012-12-06 23:32:56 UTC
Permalink
Post by Lew
just write a method that has the same parms [sic] as Object.equals
That is necessary but very far from sufficient.
That would take a perverse nature to change the types and still expect
it to work.
--
Roedy Green Canadian Mind Products http://mindprod.com
Students who hire or con others to do their homework are as foolish
as couch potatoes who hire others to go to the gym for them.
Lew
2012-12-07 02:04:10 UTC
Permalink
Post by Roedy Green
Post by Lew
just write a method that has the same parms [sic] as Object.equals
That is necessary but very far from sufficient.
That would take a perverse nature to change the types and still expect
it to work.
If you mean the types of the method parameters, you're right but irrelevant.
No one disputed that the parameter types had to match - hence my comment
that it is necessary to do that. The problem with your advice is that it left out
every other significant factor that makes a method an override of 'equals()'.

Case in point - 'Object#equals()' requires one parameter of type 'Object'. A common
tyro mistake is to use the type of the defining child class, much as one is supposed
to do with 'compareTo()'. Thus:

public class Foo
{
...
public boolean equals(Foo other) { ... }
}

If you remember to use the '@Override' annotation this mistake will be caught at
compile time, rather than at run time as happens when you don't use that annotation.
That's one of the items you left out, and ignored from my post.

It has to have a compatible return type.

public void equals(Object other) { ... }

fits your advice but is wrong.

It has to make sense.

@Override public boolean equals(Object other) { return true; }

is a valid override but almost always very stupid.

Your advice didn't cover that, and you ignored it from my post.

'hashCode()' has to match. It is possible to have code work correctly without
following this advice, but it's not smart. It'll break with one unanticipated
refactor or extension. It won't work right in hash structures.

'compareTo()' has to be consistent nearly always. Again, you can violate this
in particular circumstances, but why violate the rule? Just always keep the four
identifying methods in synch with each other (three if you don't implement 'Comparable<T>').

equals()
hashCode()
toString()
compareTo()

They should all agree with respect to equality.

That way you don't have to puzzle out every time if your code will always be safe
when you violate the rule of thumb.

Your comment about "changing the types" makes no sense to me, actually. I don't
know what triggered it or how it furthers the pedagogy.
--
Lew
Knute Johnson
2012-12-06 00:15:46 UTC
Permalink
Post by k***@gmail.com
Hello,
I am attempting to load 5000 employee items into a jcombobox, and then setSelectedIndex, but I am getting a odd delay in the gui after setting the selectedIndex
while ((line = input.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
comboBoxItems.add(lastName);}
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);
2)HOWEVER, if I load an employee object into a mapped vector, and then setSelectedIndex(5), I DO see it instantly set the GUI combobox to the 5th item, BUT then there is a LOOOONG delay in the gui (1 minute or more) before it allows me to do anything further in the gui
while ((line = input.readLine()) != null) {
StringTokenizer st = new StringTokenizer(line, "|");
lastName = st.nextToken().trim();
firstName = st.nextToken().trim();
id = Integer.parseInt(st.nextToken().trim());
empBuffer= new Employee(id, lastName );
map.put(empBuffer.getId()+"",empBuffer );
count++; }
model.addAll(map.values());
Collections.sort(model);
mybox1.setModel(new javax.swing.DefaultComboBoxModel(model));
mybox1.setSelectedIndex(5);
public class Employee implements Comparable {
private int id;
private String name;
public Employee(int id, String name) {
this.id = id;
this.name = name;
}
public String getName() {
return name;
}
public int getId() {
return id;
}
public int compareTo(Object emp) {
return getName().compareTo(((Employee)emp).getName());
}
public String toString() {
return getName()+","+getId();
}
}
Having created some rather large GUIs that perform poorly, I wouldn't
create a JComboBox with 5000 elements. It is just too many especially
if your computer is not really fast.

Suggestion: Keep your Employee objects in a List of some sort and use
an editable JComboBox that will load names or IDs that match what you
enter. I might wait for two or three letters before stuffing the
JComboBox to keep the list a more reasonable size. If a person entered
a number you could just bring up that Employee.
--
Knute Johnson
Gene Wirchenko
2012-12-13 02:15:34 UTC
Permalink
Post by k***@gmail.com
I am attempting to load 5000 employee items into a jcombobox, and
then setSelectedIndex, but I am getting a odd delay in the gui after
setting the selectedIndex

5000? Are you really expecting someone to scroll through
something that big?

[snip]

Sincerely,

Gene Wirchenko

Loading...