在JTable中添加新行后的Fire Code

时间:2016-09-08 05:44:34

标签: java swing jtable

我正在寻找一种在jtable获取新行后触发代码的方法。我一直在阅读很多线程并测试它们,其中一个像model.fireTableDataChanged(),我不知道如何放置。

我想要发生的是每次用户添加新行时,在添加行之后,方法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,这不是我的目的。我希望在添加行后&#34;刷新表格&#34;

1 个答案:

答案 0 :(得分:1)

如果DefaultTableModel检测到更改,则会触发相应的事件,例如,如果您使用更大的数字调用setRowCount:fireTableRowsInserted(old, rowCount-1);

请注意,接口TableModel的要求低于DefaultTableModel,甚至DefaultTableModel也来自AbstractTableModel,但并未实现所有触发功能:在改变方法时开火。 Javadoc至少需要检查一下:

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

addFireEvent移到setModel,以便它也用于以后的模型。 在设置模型时添加表模型侦听器可能是调用第一个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;
                }
            });
        });

使用记录器可能会发现问题。