简体   繁体   English

在JTable中添加新行后触发代码

[英]Fire Code after adding a new Row in JTable

Im looking for a way to fire a code after the jtable gets a new row. 我正在寻找一种在jtable获得新行后触发代码的方法。 I have been reading quite alot of threads and tested them out and one of them is something like model.fireTableDataChanged() which I have no idea how to place. 我已经阅读了很多线程并对其进行了测试,其中之一是类似model.fireTableDataChanged()东西,但我不知道该如何放置。

What I would like to happen is everytime the user adds a new row, after the row has been added, the method refreshTable() will execute. 我想发生的是,每当用户添加新行时,在添加该行之后,将执行refreshTable()方法。

here is my code: 这是我的代码:

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

}

EDIT 编辑

my apologies for not explaining. 对于无法解释,我深表歉意。

This is a customized JTable that allows multiline data without having the user to add renderers. 这是一个定制的JTable,它允许多行数据而无需用户添加渲染器。 My problem with this is when I add a row, that row will not adjust its rowheight and instead get the default size, but when I add another row, the previous row will then update and resize itself to fit the multilined text. 我的问题是,当我添加一行时,该行不会调整其行高,而是获得默认大小,但是当我添加另一行时,上一行将更新并调整其大小以适合多行文本。

now what I want to achieve is to allow the jtable to fire the refreshTable() method after the row is inserted which will fix the issue. 现在,我要实现的是允许jtable在插入行之后触发refreshTable()方法,这将解决此问题。

now what can I do to implement this? 现在我该怎么做才能实现呢?

adding a tableModelListener that contains the refreshTable() fires BEFORE the row is inserted which is not what I am for. 添加一个包含refreshTable()refreshTable()BEFORE插入行BEFORE触发,这不是我想要的。 I want it to "refresh the table" after the row is added. 添加行后,我希望它“刷新表”

If the DefaultTableModel detects a change, it fires the corresponding event, say if you would call setRowCount with a larger number: fireTableRowsInserted(old, rowCount-1); 如果DefaultTableModel检测到更改,则将触发相应的事件,例如是否要使用更大的数字调用setRowCount: fireTableRowsInserted(old, rowCount-1); .

Be aware that the interface TableModel is a lower requirement than DefaultTableModel , and even DefaultTableModel is derived from AbstractTableModel that has not that all firing capabilities implemented: does the firing upon changing methods. 请注意,接口TableModel的要求比DefaultTableModel要求低,甚至DefaultTableModel也是从AbstractTableModel派生的, AbstractTableModel并未实现所有触发功能:在更改方法时触发。 Javadoc and at least a check would be needed: Javadoc和至少需要检查:

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

Move the addFireEvent into the setModel , so it is used for later models too. addFireEvent移到setModel ,因此它也用于以后的模型。 The adding of a table model listener on setting a model, might be the point to call a first refreshTable. 在设置模型时添加表模型侦听器可能是调用第一个refreshTable的关键。

As refreshTable involves heavy calculation, call invokeLater to keep the GUI responsive. 由于refreshTable涉及大量计算,请调用invokeLater以保持GUI响应。

In java 8 在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;
                }
            });
        });

Use loggers maybe to find the problem. 使用记录器可能会发现问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM