2013-07-16 53 views
0

任何人都可以告訴我刷新JTable的最佳方式嗎?我試圖從另一個線程使用table.repaint(),但我不知道這是否是最好的方法。刷新JTable的最佳方法是什麼?

我的代碼:

類:型號

public class CLS_ValueUpdater extends Thread { 

    private String sRowName; 
    private String sValue; 

    public CLS_ValueUpdater(String sRowName) { 
     this.sRowName = sRowName; 
     this.start(); 
    } 

    public String getValue() { 
     return this.sValue; 
    } 

    public String getRowName() { 
     return sRowName; 
    } 

    public void setRowName(String sRowName) { 
     this.sRowName = sRowName; 
    } 

    public void run() { 
     try { 
      for (int i = 0; i <= 100; i++) { 
       this.sValue = String.valueOf(i); 

       try { 
        Thread.sleep(1000); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
      } 
     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

類:控制器

public class CLS_Controller extends AbstractTableModel { 

    private static final long serialVersionUID = -5603593230985106202L; 
    private String[] sArrColumns = { "Nombre", "Valor" }; 

    private ArrayList<CLS_ValueUpdater> tListUpdater = new ArrayList<CLS_ValueUpdater>(); 

    public CLS_Controller() { 
     super(); 
    } 

    public void addRow(String sName) { 
     this.tListUpdater.add(new CLS_ValueUpdater(sName)); 
     this.fireTableDataChanged(); 
    } 

    public void deleteRow(int iIndex) { 
     this.tListUpdater.remove(iIndex); 
     this.fireTableDataChanged(); 
    } 

    @Override 
    public String getColumnName(int iColumn) { 
     return this.sArrColumns[iColumn]; 
    } 

    @Override 
    public int getColumnCount() { 
     return this.sArrColumns.length; 
    } 

    @Override 
    public int getRowCount() { 
     return this.tListUpdater.size(); 
    } 

    @Override 
    public Object getValueAt(int iRow, int iColumn) { 
     CLS_ValueUpdater tValueUpdater = this.tListUpdater.get(iRow); 

     switch (iColumn) { 
     case 0: 
      return tValueUpdater.getRowName(); 
     case 1: 
      return tValueUpdater.getValue(); 
     default: 
      return null; 
     } 
    } 

    @Override 
    public void setValueAt(Object oValue, int iRow, int iColumn) { 
     CLS_ValueUpdater tValueUpdater = this.tListUpdater.get(iRow); 

     switch (iColumn) { 
     case 0: 
      tValueUpdater.setRowName(oValue.toString()); 
      break; 
     } 

     this.fireTableCellUpdated(iRow, iColumn); 
    } 

    @Override 
    public Class<String> getColumnClass(int iColumn) { 
     return String.class; 
    } 

    @Override 
    public boolean isCellEditable(int rowIndex, int columnIndex) { 
     return false; 
    } 
} 

類:查看

public class FRM_Main { 

    private JFrame frame; 
    private JTable table; 
    private CLS_Controller tModel = new CLS_Controller(); 
    private JTextField textField; 
    /** 
    * Launch the application. 
    */ 
    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      public void run() { 
       try { 
        FRM_Main window = new FRM_Main(); 
        window.frame.setVisible(true); 
       } catch (Exception e) { 
        e.printStackTrace(); 
       } 
      } 
     }); 
    } 

    /** 
    * Create the application. 
    */ 
    public FRM_Main() { 
     try { 
      for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) { 
       if ("Windows".equals(info.getName())) { 
        UIManager.setLookAndFeel(info.getClassName()); 
        break; 
       } 
      } 
     } catch (Exception e) { 
      System.out.println(e.getMessage()); 
     } 

     initialize(); 
    } 

    /** 
    * Initialize the contents of the frame. 
    */ 
    private void initialize() { 
     frame = new JFrame(); 
     frame.setBounds(100, 100, 476, 283); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 

     JPanel panel = new JPanel(); 
     frame.getContentPane().add(panel, BorderLayout.CENTER); 

     JScrollPane scrollPane = new JScrollPane(); 

     JButton btnNewButton = new JButton("Add"); 
     btnNewButton.addActionListener(new ActionListener() { 
      public void actionPerformed(ActionEvent arg0) { 
       tModel.addRow(textField.getText()); 
      } 
     }); 

     JButton btnNewButton_1 = new JButton("Delete"); 

     textField = new JTextField(); 
     textField.setColumns(10); 
     GroupLayout gl_panel = new GroupLayout(panel); 
     gl_panel.setHorizontalGroup(gl_panel 
       .createParallelGroup(Alignment.LEADING) 
       .addGroup(
         gl_panel.createSequentialGroup() 
           .addContainerGap() 
           .addGroup(
             gl_panel.createParallelGroup(
               Alignment.LEADING) 
               .addComponent(
                 scrollPane, 
                 GroupLayout.DEFAULT_SIZE, 
                 440, Short.MAX_VALUE) 
               .addGroup(
                 Alignment.TRAILING, 
                 gl_panel.createSequentialGroup() 
                   .addComponent(
                     textField, 
                     GroupLayout.PREFERRED_SIZE, 
                     GroupLayout.DEFAULT_SIZE, 
                     GroupLayout.PREFERRED_SIZE) 
                   .addPreferredGap(
                     ComponentPlacement.RELATED) 
                   .addComponent(
                     btnNewButton) 
                   .addPreferredGap(
                     ComponentPlacement.RELATED, 
                     216, 
                     Short.MAX_VALUE) 
                   .addComponent(
                     btnNewButton_1))) 
           .addContainerGap())); 
     gl_panel.setVerticalGroup(gl_panel 
       .createParallelGroup(Alignment.LEADING) 
       .addGroup(
         gl_panel.createSequentialGroup() 
           .addContainerGap() 
           .addComponent(scrollPane, 
             GroupLayout.PREFERRED_SIZE, 194, 
             GroupLayout.PREFERRED_SIZE) 
           .addPreferredGap(ComponentPlacement.RELATED) 
           .addGroup(
             gl_panel.createParallelGroup(
               Alignment.BASELINE) 
               .addComponent(btnNewButton_1) 
               .addComponent(
                 textField, 
                 GroupLayout.PREFERRED_SIZE, 
                 GroupLayout.DEFAULT_SIZE, 
                 GroupLayout.PREFERRED_SIZE) 
               .addComponent(btnNewButton)) 
           .addContainerGap(80, Short.MAX_VALUE))); 

     table = new JTable(); 
     table.setShowVerticalLines(false); 
     table.setShowHorizontalLines(false); 
     table.setFillsViewportHeight(true); 
     table.setModel(tModel); 

     new tableUpdater(table); 

     scrollPane.setViewportView(table); 
     panel.setLayout(gl_panel); 

    } 
} 

class tableUpdater extends Thread { 

    private JTable tTable; 

    public tableUpdater(JTable tTable) { 
     this.tTable = tTable; 
     this.start(); 
    } 

    public void run() { 
     try { 
      while (true) { 
       tTable.repaint(); 

       Thread.sleep(2000); 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

那麼是否有任何優雅的方式來自動更新JTable?提前致謝!

+0

這個問題的代碼太多了。爲什麼不裁剪它只顯示更新JTable的位? –

+0

要更清楚! –

回答

2

我已經試過如果另一個線程不是EDT你的表是不是要重新繪製使用table.repaint()從另一個線程

你想用進度條更新你的jtable。你可能有興趣使用SwingWorker。這是一個完整的example

class MySwingWorker extends SwingWorker <String,String>{ //what params you want here 

@Override 
protected String doInBackground()throws Exception{ 

    //here you download heavy task 
    //and you call publish() when you want 
} 

@Override 
protected void process(List<String> chunks){ 
    // here you updated your gui 
    //setValueAt(row,col); and fireTableCellUpdated(row,col); 
} 

@Override 
protected void done(){ 
    //here is called when doInBackGround is finished 
} 

}

,那麼你需要調用setValue(int row, int column)fireTableCellUpdated(int row,int col);與SwingWorker的爲您提供了部分結果。

BTW當你插入一行

public void addRow(String sName) { 
     this.tListUpdater.add(new CLS_ValueUpdater(sName)); 
     this.fireTableDataChanged(); 
} 

可能是更好的調用

void fireTableRowsInserted(int firstRow, int lastRow)

+0

你不理解我...我需要隨時更新插入的值,因爲我正在寫一個小型的multidownloader,我需要看到下載進度值,所以Jtable需要更新自動始終爲下載進度。對不起,我的英語不好。感謝您的迴應。 –

+0

我現在明白了..您可能對'SwingWorker'感興趣 – nachokk

+0

@SamuelPedrosa爲什麼不使用'JProgressBar'? –

0

DefaultTableModel#setValueAt()的Javadoc說:

設置在列和行的單元格的對象值。 aValue是 的新值。此方法將生成一個tableChanged通知。

因此,如果您通過調用model.setValueAt()來更改內容,那麼也會觸發重新繪製。

注意:model是您的JTableTableModel

+0

這個。 'setValueAt'是你所需要的。如果你的視圖在你使用'setValueAt'時沒有更新,你的表模型就有一個bug。 – roippi

+0

我的代碼是MVC實現。我需要始終自動更新Jtable的每個項目(如某些進度值)。 –

+0

那麼你問如何更新你的表模型?或者是什麼。 – roippi

-1

如果你想更新你的表,每1秒內,使用一個單獨的線程,做的刷新;不要忘記使用invokeLater方法。

new Thread(new Runnable(){ 
    public void run() 
    { 
    while(true) 
    { 
     Thread.sleep(1000); 
     SwingUtilities.invokeLater(new Runnable(){ 
     public void run() 
     { 
      _tableModel.fireTableDataChanged(); 
     } 
     }); 
    } 
    } 
}).start(); 
+0

我曾嘗試過這種方法,但是如果我選擇了任何一行JTable,它將在刷新時取消選擇,但是Jtable.repaint不會發生。對不起英語不好。感謝您的迴應! –

+1

sceleton是正確的,所有更新都必須在EDT上完成,但不要使用模型調用任何通知器,這是模型的重要組成部分,請參閱@nachokk的答案, – mKorbel

+0

感謝所有人! –

相關問題