2016-09-08 44 views
0

我正在尋找一種方法來在jtable獲得新行後觸發代碼。我一直在閱讀相當多的線程,並對它們進行測試,其中一個像model.fireTableDataChanged(),我不知道如何放置。在JTable中添加一個新行後的消防代碼

我想要發生的是每次用戶添加一個新行,添加行後,方法refreshTable()將執行。

這裏是我的代碼:

import java.awt.BorderLayout; 
import java.awt.Color; 
import java.awt.Component; 
import java.awt.event.ActionEvent; 

import javax.swing.AbstractCellEditor; 
import javax.swing.JButton; 
import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JTable; 
import javax.swing.JTextArea; 
import javax.swing.event.TableModelEvent; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellEditor; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableModel; 
import javax.swing.table.TableRowSorter; 

/** 
* 
* @author Innocentus 
*/ 
public class JayMultiLineTable extends JTable{ 

    public JayMultiLineTable(){ 
     super(); 
    } 

    public JayMultiLineTable(Object[][] row, String[] col){ 
     DefaultTableModel dtm = new DefaultTableModel(row,col); 
     this.setModel(dtm); 
     addFireEvent(); 
     this.setDefaultRenderer(Object.class, new MultiLineCellRendererx()); 
     this.setDefaultEditor(Object.class, new MultiLineCellEditor()); 
    } 

    @Override 
    public void setModel(TableModel dataModel) { 
     if (dataModel == null) { 
      throw new IllegalArgumentException("Cannot set a null TableModel"); 
     } 
     if (this.dataModel != dataModel) { 
      TableModel old = this.dataModel; 
      if (old != null) { 
       old.removeTableModelListener(this); 
      } 
      this.dataModel = dataModel; 
      dataModel.addTableModelListener(this); 

      tableChanged(new TableModelEvent(dataModel, TableModelEvent.HEADER_ROW)); 

      firePropertyChange("model", old, dataModel); 

      if (getAutoCreateRowSorter()) { 
       setRowSorter(new TableRowSorter<TableModel>(dataModel)); 
      } 
      addFireEvent(); 
     } 
     try { 
      this.setDefaultRenderer(Object.class, new MultiLineCellRendererx()); 
      this.setDefaultEditor(Object.class, new MultiLineCellEditor()); 
     } catch (Exception e) { 

     } 

    } 

    public void refreshTable(){ 
     JTable tbl = this; 
     for (int row = 0; row < tbl.getRowCount(); row++){ 
      int rowHeight = tbl.getRowHeight(); 

      for (int column = 0; column < tbl.getColumnCount(); column++){ 
       Component comp = tbl.prepareRenderer(tbl.getCellRenderer(row, column), row, column); 
       rowHeight = Math.max(rowHeight, comp.getPreferredSize().height); 
      } 

      tbl.setRowHeight(row, rowHeight); 
     } 
    } 

    private void addFireEvent(){ 
     this.getModel().addTableModelListener((TableModelEvent e) -> { 
      switch (e.getType()) { 
       case TableModelEvent.DELETE: 
        refreshTable(); 
        break; 
       case TableModelEvent.INSERT: 
        refreshTable(); 
        break; 
       case TableModelEvent.UPDATE: 
        refreshTable(); 
        break; 
      } 
     }); 

    } 

    public static void main(String args[]){ 
     JFrame jf = new JFrame(); 
     jf.getContentPane().setLayout(new BorderLayout()); 
     JayMultiLineTable table = new JayMultiLineTable(); 
     table.setModel(new DefaultTableModel(
      new Object [][] { 
       {"this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample. this is a sample.", " this is a sample."," this is a sample."," this is a sample."} 
      }, 
      new String [] { 
       "Title 1", "Title 2", "Title 3", "Title 4" 
      } 
     )); 
     jf.getContentPane().add(table, BorderLayout.CENTER); 
     JButton btn = new JButton("add another row"); 
     btn.addActionListener((ActionEvent e)->{ 
      Object row[] = {"This is an added sample","This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample. This is an added sample","This is an added sample","This is an added sample"}; 
      ((DefaultTableModel)table.getModel()).addRow(row); 
      //table.refreshTable(); <--- unless I call this method, the row height will not adjust unless the addrow is fired again for the second time. 
     }); 
     jf.getContentPane().add(btn, BorderLayout.NORTH); 
     jf.setExtendedState(JFrame.MAXIMIZED_BOTH); 
     jf.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     jf.show(); 

    } 
} 
class MultiLineCellRendererx extends JTextArea implements TableCellRenderer { 

    public MultiLineCellRendererx() { 
     setLineWrap(true); 
     setWrapStyleWord(true); 
     setSelectionColor(Color.GREEN); 
    } 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 

     setText((String)value); 
     setSize(table.getColumnModel().getColumn(column).getWidth(),this.getPreferredSize().height); 
     setSelectionColor(Color.GREEN); 

     if (isSelected){ 
      setBackground(table.getSelectionBackground()); 
      setForeground(table.getSelectionForeground()); 
     }else{ 
      setBackground(table.getBackground()); 
      setForeground(table.getForeground()); 
     } 
     return this; 
    } 
} 

class MultiLineCellEditor extends AbstractCellEditor implements TableCellEditor { 
    // This is the component that will handle the editing of the cell value 
    JComponent component = new JTextArea(); 

    public MultiLineCellEditor(){ 
     ((JTextArea)component).setLineWrap(true); 
     ((JTextArea)component).setWrapStyleWord(true); 
    } 
    // This method is called when a cell value is edited by the user. 
    public Component getTableCellEditorComponent(JTable table, Object value, 
      boolean isSelected, int rowIndex, int vColIndex) { 
     // 'value' is value contained in the cell located at (rowIndex, vColIndex) 

     if (isSelected) { 
      // cell (and perhaps other cells) are selected 
     } 

     // Configure the component with the specified value 
     ((JTextArea)component).setText((String)value); 

     // Return the configured component 
     return component; 
    } 

    // This method is called when editing is completed. 
    // It must return the new value to be stored in the cell. 
    public Object getCellEditorValue() { 
     return ((JTextArea)component).getText(); 
    } 

} 

編輯

我的道歉沒有解釋。

這是一個定製的JTable,它允許多行數據,而無需用戶添加渲染器。我的問題是當我添加一行時,該行不會調整其rowheight,而是獲取默認大小,但是當我添加另一行時,上一行將更新並調整其大小以適應多行文本。

現在我想實現的是允許jtable在插入行之後觸發refreshTable()方法,這將解決問題。

現在我該怎麼做才能實現呢?

添加一個tableModelListener,其中包含refreshTable()火災BEFORE該行被插入,這不是我所爲。我想在「更新表格」行後添加。

+1

請解釋你應該做什麼程序並提供[SSCCE](http://sscce.org) –

+0

使用doLayout()而不是refreshTable(),大多數代碼負責XxxTableCellRenderer而不是尋找從TableModelListener觸發的事件 – mKorbel

回答

1

如果DefaultTableModel檢測到更改,它將觸發相應的事件,比如說您是否使用較大數字調用setRowCount:fireTableRowsInserted(old, rowCount-1);

注意接口TableModelDefaultTableModel的要求較低,甚至DefaultTableModelAbstractTableModel已經不是所有的發射能力實現的衍生:在不改變方法燒製。將需要Javadoc和至少一個檢查:

if (!(model instanceof DefaultTableModel)) { 
    throw bad luck; 
} 

移動addFireEventsetModel,所以使用它對於以後的型號了。 在設置模型時添加表模型偵聽器可能是調用第一個refreshTable的關鍵。

由於refreshTable涉及繁重的計算,請致電invokeLater以保持GUI的響應。

在java中8個

 this.getModel().addTableModelListener(e -> { // TableModelListener 
      SwingUtilities.invokeLater(() -> { // Runnable 
       switch (e.getType()) { 
        case TableModelEvent.DELETE: 
         refreshTable(); 
         break; 
        case TableModelEvent.INSERT: 
         refreshTable(); 
         break; 
        case TableModelEvent.UPDATE: 
         refreshTable(); 
         break; 
       } 
      }); 
     }); 

使用記錄器可能找到問題。

+0

太棒了!正是我需要的!謝謝! –