如何完全擦除 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 以开始 更新模型中的行数据 更新模型中的列数据(即columnCountcolumnName) 触发TableModelEvent.HEADER_ROW 事件,以便JTable 使用新数据更新自身

删除列

确定要删除的列索引 删除每一行的列数据 更新模型中的列数据(即columnCountcolumnName) 触发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 列及其数据?的主要内容,如果未能解决你的问题,请参考以下文章

java的swing编程,Jtable的单元格如何赋值

java swing JTable显示问题

如何在JTable Invisible for Swing Java中创建一个列

Java Swing 如何使用DefaultTableModel交替刷新JTable?

在java swing Jtable中设置隐藏字段值

Java Swing Jtable 单元格不可编辑