如何从一个用于查看标签随光标移动到某个位置的方法中优雅地返回?

编程语言 2026-07-09

我正在使用下面的代码来遍历一个游标。这个方法是在一个名为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

  1. 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());
  1. 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 in try { ... } finally { cur.close(); dbp.close(); }.
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。

相关文章