gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-01 09:31:14 25 4
gpt4 key购买 nike

我正在寻找一种在 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,允许多行数据,而无需用户添加渲染器。我的问题是,当我添加一行时,该行不会调整其行高,而是获得默认大小,但是当我添加另一行时,前一行将更新并调整自身大小以适应多行文本。

现在我想要实现的是允许 jtable 在插入行后触发 refreshTable() 方法,这将解决问题。

现在我可以做什么来实现这个?

添加包含refreshTable()的tableModelListener会在插入行之前触发,这不是我的目的。我希望它在添加行后“刷新表格”

最佳答案

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

请注意,TableModel 接口(interface)的要求低于 DefaultTableModel,甚至 DefaultTableModel 也是从 AbstractTableModel 派生的> 尚未实现所有触发功能:在更改方法时触发。 Javadoc 和至少需要检查:

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

addFireEvent移动到setModel中,这样它也可以用于以后的模型。在设置模型时添加表模型监听器可能是调用第一个刷新表的点。

由于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;
}
});
});

使用记录器也许可以找到问题。

关于java - 在 JTable 中添加新行后触发代码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39383351/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com