如何从一个用于查看标签随光标移动到某个位置的方法中优雅地返回?
我正在使用下面的代码来遍历一个游标。这个方法是在一个名为Practice Session窗体中运行,该窗体有3 个练习视图实例。第一个按钮会激活第一个视图实例并正确演示练习,但在第二个视图实例中,练习的最后一条记录被处理并显示,调用窗体重新绘制,然后placePlayers方法再执行一行,导致在Practice Session窗体上方弹出一个Index Out of Bounds(越界)错误框。
在从第二次查看中关闭错误框后,Practice Session窗体上的第三个按钮将调用第三个视图。问题1:第二个视图的名称未从View窗体中移除;问题2:第三个视图完成后,调用窗体重新绘制,方法尝试再运行一行,此时显示IOOB错误框。关闭错误框后,调用窗体功能正常。
public boolean placePlayers() throws IOException {
dbp = Display.getInstance().openOrCreate("pandr.db");
String rd = "SELECT * FROM PandR WHERE name ='" + namevt + "'";
cur = dbp.executeQuery(rd);
Row currentRow = cur.getRow();
int txt = currentRow.getInteger(2);
cc = currentRow.getInteger(3);
x = cc + 1;//+1
for (r = 1; r < x; r++) {
// Place labels on View Form
tbloc = currentRow.getString(5);// location for ball label returned from pandr.db
tbloci = Integer.parseInt(tbloc);
((Container) gls.getComponentAt(tbloci)).add(blbl);
//
//
tgloc = currentRow.getString(28); // location for G label returned from pandr.db
tgloci = Integer.parseInt(tgloc);
((Container) field.getComponentAt(tgloci)).add(glbl);
//Wait between player movement
monitor.animateLayoutAndWait(400);
//Remove Labels from field and glass pane for next move
((Container) gls.getComponentAt(tbloci)).removeComponent(blbl);
//
//
((Container) field.getComponentAt(tgloci)).removeComponent(glbl);
//Move to next location record in database
cur.next();
//Check to determine last record
pl = currentRow.getInteger(2);
//Process the last record
if (pl == cc) {
// Place last record labels
tbloc = currentRow.getString(5);// location for ball label returned from pandr.db
tbloci = Integer.parseInt(tbloc);
((Container) gls.getComponentAt(tbloci)).add(blbl);
//
//
tgloc = currentRow.getString(28); // location for G label returned from pandr.db
tgloci = Integer.parseInt(tgloc);
((Container) field.getComponentAt(tgloci)).add(glbl);
//Hold last position before clearing field
monitor.animateLayoutAndWait(400);
//Clearing all labels from the field and glass pane
((Container) gls.getComponentAt(tbloci)).removeComponent(blbl);
//
//
((Container) field.getComponentAt(tgloci)).removeComponent(glbl);
//Removing View components so the View form can be redrawn
controlarea.removeComponent(add1);
controlarea.removeComponent(caLabel);
monitor.removeComponent(controlarea);
field.removeAll();
gls.removeAll();
monitor.removeComponent(field);
monitor.removeComponent(gls);
//Close Database and cursor
dbp.close();
cur.close();
//Return to Practice Plan Form
contactEditor.showBack();
}
}
return true;
}
有什么建议吗?
解决方案
The IndexOutOfBoundsException is triggered because the for loop never stops after the cleanup block runs.
Inside if (pl == cc) you do all the
field.removeAll();
gls.removeAll(); ...
dbp.close();
cur.close();
contactEditor.showBack();
…but there is no break or return. Control falls out of the if, hits r++, the loop condition r < x is still true, and the body runs one more iteration. That next iteration calls: ((Container) gls.getComponentAt(tbloci)).add(blbl);
gls was just emptied by gls.removeAll(), so getComponentAt(tbloci) throws IndexOutOfBoundsException.
The "second view's name not removed" symptom is the same cause: when the exception fires mid-iteration, whatever cleanup you do later in your view-teardown path (or any component you re-add on the way out) is left in an inconsistent state.
The fix is to stop the loop as soon as you've handled the last record:
if (pl == cc) {
// ...all your last-record placement and cleanup...
contactEditor.showBack();
return true; // <-- add this (or `break;`) }
A couple of other things worth fixing while you're in there
cur.next()is called unconditionally, including on the final row. After the last row,next()moves the cursor past the end. With the return/break above this becomes harmless, but the loop shape is fragile. A cleaner pattern:
Row currentRow = cur.getRow();
cc = currentRow.getInteger(3);
do {
currentRow = cur.getRow();
int pl = currentRow.getInteger(2);
// place labels, animate, remove labels...
if (pl == cc) {
// teardown + showBack
return true;
}
} while (cur.next());
- Resource leak on early exit: if any of the add/removeComponent calls throws before you reach the
if (pl == cc)cleanup, dbp and cur are left open. Wrap the body intry { ... } finally { cur.close(); dbp.close(); }.