2011-05-24 42 views
0

我有一個JTable,可以使用互聯網上的數據插入行。當我運行直接從主函數填充列表的代碼時,我可以看到每行被插入同時'fireTableRowsInserted'被調用 - 這是我想要的行爲。然而,當我從JButton的ActionListener運行相同的代碼時(在'ActionPreformed()'期間,表不會更新,直到線程/事件結束。 我認爲問題與線程有關,但我不是很。熟悉如何線程的工作,我不知道從哪裏開始 這是問題的一個例子:當從Action Listener調用fireTableRowsInserted()時,JTable不會立即更新

public class Main { 
    static TestModel myTestModel = new TestModel(); 

    public static void main(String[] args) { 
     JFrame testFrame = new JFrame(); 
     JTable table  = new JTable(myTestModel); 
     JButton button  = new JButton("Load"); 

     testFrame.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER); 
     testFrame.getContentPane().add(button, BorderLayout.PAGE_END); 
     testFrame.pack(); 
     testFrame.setVisible(true); 
     testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     button.addActionListener(new ActionListener(){ 
      @Override public void actionPerformed(ActionEvent e) { 
       //When openURLStr is called here, the table in the JFrame doesn't add rows until 
       // the function has exited. 
       openURLStr("http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Component.html", true);    
      }   
     }); 

     //When openURLStr is called here, the table in the JFrame adds rows at the same time the 
     // list in the table-model adds a row. (the desired behavoir) 
     openURLStr("http://download.oracle.com/javase/1.4.2/docs/api/java/awt/Component.html", true); 
     myTestModel.myArrayList.clear(); 
     myTestModel.fireTableDataChanged(); 
    } 

    static class TestModel extends AbstractTableModel { 
     ArrayList<String> myArrayList = new ArrayList<String>(); 

     @Override public int getColumnCount() { return(3);     } 
     @Override public int getRowCount()  { return(myArrayList.size()); } 
     @Override public Object getValueAt(int row, int col) { 
      char c = '*'; 
      String rowStr = myArrayList.get(row); 
      if (rowStr.length() > col) c = rowStr.charAt(col); 
      return(c); 
     } 

     public boolean add(String line) { 
      int row = myArrayList.size(); 
      if (row < 100) { 
       myArrayList.add(line); 
       this.fireTableRowsInserted(row, row);    
       return(true); 
      } 
      else { 
       return(false); 
      } 
     }  
    } 

    private static void openURLStr(String urlStr, boolean lookForLinks) { 
     try { 
      URL     url   = new URL(urlStr); 
      InputStreamReader isr   = new InputStreamReader(url.openConnection().getInputStream()); 
      BufferedReader  br   = new BufferedReader(isr); 
      ArrayList<String> linksFound = new ArrayList<String>(); 

      if (br != null) { 
       String strLine = br.readLine(); 
       //row added to table-model here: 
       boolean continueParse = myTestModel.add(strLine); 

       //this code is mainly to induce more time between each addition of a line. 
       while (strLine != null && continueParse) { 
        if (lookForLinks && strLine != null) { 
         String ahrefStr = "a href=\""; 
         int start_i = strLine.indexOf(ahrefStr) + ahrefStr.length(); 
         if (start_i > -1) { 
          int end_i = strLine.indexOf("\"", start_i+1); 
          if (end_i > -1 && end_i > start_i) { 
           linksFound.add(strLine.substring(start_i, end_i)); 
          } 
         } 
        } 
        strLine = br.readLine(); 
       } 
       br.close(); 
      } 

      for (String link : linksFound) { 
       openURLStr(link, false); 
      } 

     } catch (IOException e) { 
     } 
    } 
} 

回答

5

的的ActionListener的actionPerformedevent dispatch thread執行,這將通過您的代碼被封鎖內這樣的GUI此時會凍結,並且根本不顯示任何更新。

嘗試將「長時間運行」URL調用分開,例如在SwingWorker

+0

是的,這是問題及其解決方案。 +1 – 2011-05-24 19:10:32