Calling JComboBox#addItem() in a while(resultSet.next()) loop ends up with only 1 item
this is the code thats giving me problems.
try{
ResultSet rs = Main.dbase.search("select * from myTable");
//rs.next()
while(rs.next())
{
cmb.addItem(rs.getString(1).trim());
}
rs.close();
} catch (Exception ex) {System.out.println(ex);}
here dbase is an object executing Statement.executeQuery, and cmb is JComboBox.
the problem is that even though the table has 10 rows, i get only single row in cmb. if I don't comment out the first rs.next(), i get the 2nd row in cmb.
i tried to track the value of rs.next() and found that after while(rs.next()) it gives out false, always.
My target is to get all the 10 values in cmb. as fas as i have researched, this code should add all values开发者_JAVA百科 to cmb, but only a single value is being added. if before entering the loop i call rs.next(), then the next value adds to the cmb.
You didn't mention if any exception was caught by your catch
block.
What I see could prevent the loop from going further than the first row, would be that the next row has a NULL
first column.
Indeed, if there is a NULL
in the 1st column of any of the rows returned by "select * from myTable"
, then rs.getString(1).trim()
will throw a NullPointerException
that will interrupt the loop.
You can avoid that by writing:
try {
ResultSet rs = Main.dbase.search("select * from myTable");
while(rs.next()) {
String result = rs.getString(1);
if (result != null) {
result = result.trim();
}
cmb.addItem(result);
}
rs.close();
} catch (Exception ex) {
System.out.println(ex);
}
In addition, I would improve the whole snippet in order to:
- ensure
rs
is closed even if an exception occurs - ensure we see the full stack trace of any exception
- ensure that
cmb
is updated exclusively from the EDT (Swing EDT rule) - avoid too many calls to the EDT by aggregating all
addItems
altogether
Then here is what you would have:
ResultSet rs = null;
try {
final List<String> allItems = new ArrayList>String>();
rs = Main.dbase.search("select * from myTable");
while(rs.next()) {
String result = rs.getString(1);
if (result != null) {
result = result.trim();
}
allItems.add(result);
}
SwingUtilities.invokeLater(new Runnable() {
@Overrive public run() {
for (String item: allItems) {
cmb.addItem(item);
}
}
});
} catch (Exception ex) {
ex.printStacktrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Of course, some parts can still be improved further, for instance I would probably write a helper method to close a ResultSet
if it's not null
, because this code is likely to be reused in many places.
If your ResultSet
is actually populating correctly, then your problem is with Swing. That is, Swing is not thread-safe. When adding items to the JComboBox
, it is crucial that you do so in the Event Dispatch Thread, or EDT
. In order to do this, use the SwingUtilities
utility class to post a Runnable
task on the EventQueue
to be executed in the EDT
. For instance,
while(rs.next()){
if(SwingUtilities.isEventDispatchThread()){
cmb.addItem(rs.getString(1).trim());
}
else{
SwingUtilities.invokeLater(new Runnable(){
@Override
public void run(){
cmb.addItem(rs.getString(1).trim());
}
});
}
}
Regardless of what actually ends up being the problem, please heed this advice.
This is the correct structure for what you are doing, so the problem probably lies elsewhere. SELECT *
is not a good idea in a situation like this, and SELECT *
combined with rs.getString(1)
makes it impossible for us to second-guess what is being added to the combo box. I'm going to guess that the first column isn't what you think it is. At the least, use rs.getString("column_name_I_want")
.
By the way, are you sure you want search
and not some sort of execute
?
精彩评论