如何完全擦除 Java Swing JTable 列及其数据?
Posted
技术标签:
【中文标题】如何完全擦除 Java Swing JTable 列及其数据?【英文标题】:How to completely erase a Java Swing JTable column and its data? 【发布时间】:2022-01-24 00:51:45 【问题描述】:我正在尝试在 Java Swing 中创建一个动态 JTable,用户可以在其中根据需要添加/删除行和列。一切都很好,除了删除列。我已经做了好几个小时了,我不知道如何完全擦除一列及其值。
类中有removeColumn(int)
方法,但它们只是隐藏列。我也搜索并找到了this 答案,但是当我尝试创建 CustomTableModel 类并扩展 DefaultTableModel 时,我只得到了一个 ClassCastException。
【问题讨论】:
我刚刚得到一个 ClassCastException。 - 那么你的代码是错误的。我们无法猜测您为什么会收到 ClassCastException。发布您的minimal reproducible example 来证明问题。您的自定义模型应仅出于 MRE 的目的实现“removeCoumn(...)”方法。 1.从模型中删除数据; 2.更新TableModel
,从相关方法中删除该列; 3. 如果需要,将表格模型重新应用于表格。你也许可以逃脱; 1 & 2 如果您确保您还触发了tableStructureChanged
事件
@camickr 我的错,应该让它更具体。我已经创建了我的 CustomTableModel 类并将其正确扩展为 DefaultTableModel,但是当我尝试使用 (CustomTableModel) table.getModel();
分配表模型并将其转换为它时,我得到了错误。虽然我不确定这是否是检索对象的正确方法。
如果您将表格的模型设置为 CustomTableModel 那么您应该能够使用 getModel() 方法并对其进行转换。如果您遇到异常,则表示您没有将 CustomTableModel 设置为表。仍然没有看到minimal reproducible example。在代码中添加System.out.println( table.getModel() )
语句以查看模型是什么类。
@WayneG 很高兴它有帮助。注意,我们不使用 IDE 来生成代码。您花时间学习 IDE 而不是 Java/Swing。尝试手动创建表单。您将完全控制所使用的代码和布局管理器。 IDE 仍可用于调试和测试。
【参考方案1】:
添加列
确定列的新索引(如何操作取决于您) 确定每行/列的新值 - 您也可以轻松地将值设置为null
以开始
更新模型中的行数据
更新模型中的列数据(即columnCount
和columnName
)
触发TableModelEvent.HEADER_ROW
事件,以便JTable
使用新数据更新自身
删除列
确定要删除的列索引 删除每一行的列数据 更新模型中的列数据(即columnCount
和columnName
)
触发TableModelEvent.HEADER_ROW
事件,以便JTable
使用新数据更新自身
可运行示例
这是该概念的一个基本示例。就我个人而言,我更喜欢通过 POJO 管理我的数据(这里的“隐藏列”的想法会更实用,但这可能并不总是可能的
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
public class Test
public static void main(String[] args)
new Test();
public Test()
EventQueue.invokeLater(new Runnable()
@Override
public void run()
JFrame frame = new JFrame();
frame.add(new TestPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
);
public class TestPane extends JPanel
private MutableTableModel model;
private JTable table;
public TestPane()
setLayout(new BorderLayout());
JButton addColumnButton = new JButton("Add column");
JButton removeColumnButton = new JButton("Remove column");
addColumnButton.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
List<Object> rows = new ArrayList<>(100);
for (int row = 0; row < 100; row++)
rows.add(randomString());
String columnName = JOptionPane.showInputDialog(TestPane.this, "Column name");
if (columnName == null || columnName.isBlank())
columnName = randomString();
int columnIndex = table.getSelectedColumn();
if (columnIndex < 0)
model.addColumn(columnName, rows);
else
model.addColumn(columnName, rows, columnIndex + 1);
);
removeColumnButton.addActionListener(new ActionListener()
@Override
public void actionPerformed(ActionEvent e)
int columnIndex = table.getSelectedColumn();
if (columnIndex < 0)
JOptionPane.showMessageDialog(TestPane.this, "Now column selected");
else
model.removeColumn(columnIndex);
);
JPanel actionPanels = new JPanel(new GridBagLayout());
actionPanels.add(addColumnButton);
actionPanels.add(removeColumnButton);
add(actionPanels, BorderLayout.SOUTH);
String[] columnNames = new String[]"One", "Two", "Three", "Four", "Five";
List<List<Object>> rows = new ArrayList<>(100);
for (int row = 0; row < 100; row++)
List<Object> rowData = new ArrayList<>(columnNames.length);
for (int col = 0; col < columnNames.length; col++)
rowData.add(randomString());
rows.add(rowData);
model = new MutableTableModel(Arrays.asList(columnNames), rows);
table = new JTable(model);
add(new JScrollPane(table));
private Random random = new Random();
protected String randomString()
int leftLimit = 48; // numeral '0'
int rightLimit = 122; // letter 'z'
int targetStringLength = 10;
String generatedString = random.ints(leftLimit, rightLimit + 1)
.filter(i -> (i <= 57 || i >= 65) && (i <= 90 || i >= 97))
.limit(targetStringLength)
.collect(StringBuilder::new, StringBuilder::appendCodePoint, StringBuilder::append)
.toString();
return generatedString;
public class MutableTableModel extends AbstractTableModel
private ArrayList<List<Object>> rows = new ArrayList<>(32);
private ArrayList<String> columnNames = new ArrayList<>(8);
public MutableTableModel()
public MutableTableModel(List<String> columnNames, List<List<Object>> rows)
this.columnNames = new ArrayList<>(columnNames);
this.rows = new ArrayList<>(rows);
public void addColumn(String name)
addColumn(name, columnNames.size() - 1);
public void addColumn(String name, int columnIndex)
columnIndex = Math.max(0, Math.min(columnIndex, columnNames.size()));
int rowCount = getRowCount();
List<Object> rows = new ArrayList<>(rowCount);
for (int row = 0; row < rowCount; row++)
rows.add(null);
addColumn(name, rows, columnIndex);
public void addColumn(String name, List<Object> rows)
addColumn(name, rows, columnNames.size());
public void addColumn(String name, List<Object> newRows, int columnIndex)
columnIndex = Math.max(0, Math.min(columnIndex, columnNames.size()));
columnNames.add(columnIndex, name);
int rowCount = getRowCount();
for (int row = 0; row < rowCount; row++)
List<Object> rowData = rows.get(row);
Object value = null;
if (row < newRows.size())
value = newRows.get(row);
rowData.add(columnIndex, value);
fireTableStructureChanged();
public void removeColumn(int columnIndex)
if (columnIndex < 0 || columnIndex >= columnNames.size())
return;
int rowCount = getRowCount();
for (int row = 0; row < rowCount; row++)
List<Object> rowData = rows.get(row);
rowData.remove(columnIndex);
columnNames.remove(columnIndex);
fireTableStructureChanged();
@Override
public int getRowCount()
return rows.size();
@Override
public int getColumnCount()
return columnNames.size();
@Override
public String getColumnName(int column)
if (column >= columnNames.size())
return super.getColumnName(column);
return columnNames.get(column);
@Override
public Object getValueAt(int rowIndex, int columnIndex)
return rows.get(rowIndex).get(columnIndex);
【讨论】:
【参考方案2】:感谢 camickr 将我的头敲回原位,我真的只需将模型设置为 CustomTableModel 以便我也可以使用 getModel()
将其转换回来。它现在使用here 中的答案工作。如果您使用的是 NetBeans,请务必自己编辑自动生成的代码并更改...
contentTable.setModel(new TableModel(
new Object [][]
,
new String []
));
到
contentTable.setModel(new CustomTableModel(
new Object [][]
,
new String []
));
【讨论】:
您的答案可以通过额外的支持信息得到改进。请edit 添加更多详细信息,例如引用或文档,以便其他人可以确认您的答案是正确的。你可以找到更多关于如何写好答案的信息in the help center。以上是关于如何完全擦除 Java Swing JTable 列及其数据?的主要内容,如果未能解决你的问题,请参考以下文章
如何在JTable Invisible for Swing Java中创建一个列