【问题标题】:How to completely erase a Java Swing JTable column and its data?如何完全擦除 Java Swing JTable 列及其数据?
【发布时间】: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 仍可用于调试和测试。

标签: java swing


【解决方案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
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-08-31
    • 1970-01-01
    • 2020-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多