2011-06-17 33 views
2

這是給我問題的代碼。在while(resultSet.next())循環中調用JComboBox#addItem()最後只有1個項目

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);} 

這裏dbase是一個執行Statement.executeQuery的對象,而cmb是JComboBox。

問題是,即使表中有10行,我只得到單行在cmb。 如果我不註釋掉第一個rs.next(),我得到cmb中的第二行。

我試圖跟蹤rs.next()的價值,發現後而(rs.next())它給了假,始終。

我的目標是獲得cmb中的所有10個值。 作爲我已經研究過的fas,這個代碼應該把所有的值加到cmb中,但是隻有一個值被添加。 如果在進入循環之前我呼叫rs.next(),那麼下一個值將添加到cmb。

+1

'while'循環有多少次循環?把一個調試斷點或一個窮人的'System.out.println()'弄清楚。 – BalusC 2011-06-17 00:36:09

+0

如果註釋掉cmb.addItem行會發生什麼 - 它仍然只運行while循環一次嗎? – Ord 2011-06-17 00:36:26

+0

你能告訴我們創建組合框的代碼嗎? – jfpoilpret 2011-06-17 06:53:35

回答

2

您沒有提及您的catch區塊是否發現任何異常。

我看到的可能會阻止循環比第一行更進一步,將是下一行有一個NULL第一列。

事實上,如果在任何由"select * from myTable"返回的行的第一列NULL,然後rs.getString(1).trim()將拋出一個NullPointerException將中斷循環。

您可以避免通過寫

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); 
} 

此外,我會提高整個片段,以便:

  • 確保rs即使發生異常
  • 確保關閉我們看到任何異常的完整堆棧跟蹤
  • 確保cmb專門從EDT(Swing EDT規則)
  • 通過聚集所有 addItems

那麼這裏

  • 避免過多的調用到EDT是你擁有的一切:

    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(); 
         } 
        } 
    } 
    

    當然,一些地區仍可以進一步改進,比如我如果它不是null,可能會編寫一個幫助程序方法來關閉ResultSet,因爲此代碼可能會在許多地方重複使用。

  • +0

    嘿,那有效! 謝謝隊友! 也謝謝! – 2011-06-17 17:45:16

    0

    這是你正在做什麼的正確結構,所以這個問題可能在別處。 SELECT *在這樣的情況下並不是一個好主意,SELECT *加上rs.getString(1)使我們不可能再次猜測要添加到組合框中的內容。我會猜測第一列不是你想象的那樣。至少,請使用rs.getString("column_name_I_want")

    順便說一下,你確定要search而不是某種execute

    +0

    嗯,我可以做到這一點,但它會有什麼不同? 我的表只有一列;)。 將我的評論轉介給othman作爲搜索方法。 – 2011-06-17 07:36:14

    1

    如果您的ResultSet實際上是正確填充的,那麼您的問題與Swing有關。也就是說,Swing不是線程安全的。將項目添加到JComboBox時,在事件派遣線程或EDT中這樣做至關重要。爲此,請使用SwingUtilities實用程序類別在EventQueue上發佈Runnable任務,以便在EDT中執行該任務。例如,

    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()); 
          } 
         }); 
        } 
    } 
    

    無論實際最終是什麼問題,請留意此建議。

    +0

    很可能他的ResultSet沒有正確填充。他說rs.next()總是返回false。如果是這種情況,那麼檢查你的main.db.search()方法。這個方法可能不會返回字符串?這意味着第一個結果是一個字符串,但其餘的結果不是*字符串*。或者您的查詢方法執行得不好。將代碼發佈到你的db.search()中,這樣我們可以幫助你更多。 – othman 2011-06-17 03:49:48

    +0

    我試過你的代碼,但仍然只添加一個項目。而在你的代碼中,else部分沒有被執行。我想你是正確的,問題在於addItem行。 – 2011-06-17 07:32:12

    +0

    @othman:繼承人的代碼 '公共的ResultSet搜索(串Q){ 嘗試{回報(st.executeQuery(Q));} 趕上(例外五){返回NULL;}' 我想的ResultSet越來越正確填充。 – 2011-06-17 07:33:39

    相關問題