java 将列添加到退出的 TableModel

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6793257/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 17:17:29  来源:igfitidea点击:

Add column to exiting TableModel

javaswingjtableabstracttablemodeldefaulttablemodel

提问by Bitmap

I have a class;

我有一堂课;

public class A extends AbstractTableModel
{
 ...
}

Using ResultSetMetaData I build the TableModel to match my result set from the database.

使用 ResultSetMetaData 我构建了 TableModel 以匹配我的数据库结果集。

public class B extends JPanel
{
 ...
}

In class Bwhere I extends JPanel and added class Ato show my table. I want to be able to add new columns base on a condition to the table model. I have tried googling around but most example shown are based on the DefaultTableModelnot AbstractTableModel.

B 类中,我扩展了 JPanel 并添加了A 类来显示我的表格。我希望能够根据条件向表模型添加新列。我试过谷歌搜索,但显示的大多数示例都基于DefaultTableModelnot AbstractTableModel

Do anyone know how to achieve this?

有谁知道如何实现这一目标?

采纳答案by Eric Hydrick

Just extend DefaultTableModel and then you have access to all of its methods. DefaultTableModel also extends AbstractTableModel, so references to AbstractTableModel in other parts of your code aren't going to break.

只需扩展 DefaultTableModel,然后您就可以访问它的所有方法。DefaultTableModel 还扩展了 AbstractTableModel,因此在代码的其他部分中对 AbstractTableModel 的引用不会中断。

回答by mKorbel

for example

例如

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableColumnHider {

    private JTable table;
    private TableColumnModel tcm;
    private Map hiddenColumns;

    public TableColumnHider(JTable table) {
        this.table = table;
        tcm = table.getColumnModel();
        hiddenColumns = new HashMap();
    }

    public void hide(String columnName) {
        int index = tcm.getColumnIndex(columnName);
        TableColumn column = tcm.getColumn(index);
        hiddenColumns.put(columnName, column);
        hiddenColumns.put(":" + columnName, new Integer(index));
        tcm.removeColumn(column);
    }

    public void show(String columnName) {
        Object o = hiddenColumns.remove(columnName);
        if (o == null) {
            return;
        }
        tcm.addColumn((TableColumn) o);
        o = hiddenColumns.remove(":" + columnName);
        if (o == null) {
            return;
        }
        int column = ((Integer) o).intValue();
        int lastColumn = tcm.getColumnCount() - 1;
        if (column < lastColumn) {
            tcm.moveColumn(lastColumn, column);
        }
    }

    public static void main(String[] args) {
        String[] columnNames = {"Name", "Size", "Type", "Date Modified", "Permissions"};
        String[][] data = {
            {"bin", "2", "dir", "Jun 9", "drwxr-xr-x"},
            {"boot", "3", "dir", "Jun 9", "drwxr-xr-x"},
            {"dev", "6", "dir", "Jul 12", "drwxr-xr-x"},
            {"etc", "34", "dir", "Jul 12", "drwxr-xr-x"},};
        JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        final TableColumnHider hider = new TableColumnHider(table);
        JPanel checkBoxes = new JPanel();
        for (int i = 0; i < columnNames.length; i++) {
            JCheckBox checkBox = new JCheckBox(columnNames[i]);
            checkBox.setSelected(true);
            checkBox.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent evt) {
                    JCheckBox cb = (JCheckBox) evt.getSource();
                    String columnName = cb.getText();

                    if (cb.isSelected()) {
                        hider.show(columnName);
                    } else {
                        hider.hide(columnName);
                    }
                }
            });
            checkBoxes.add(checkBox);
        }
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(scrollPane);
        frame.getContentPane().add(checkBoxes, BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

回答by trashgod

Just for fun, here's a generic version of @mKorbel's TableColumnHider.

只是为了好玩,这是@mKorbel's 的通用版本TableColumnHider

import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import javax.swing.table.*;

/** @see https://stackoverflow.com/questions/6796673 */
public class TableColumnHider {

    private JTable table;
    private TableColumnModel tcm;
    private Map<String, IndexedColumn> hidden =
        new HashMap<String, IndexedColumn>();

    public TableColumnHider(JTable table) {
        this.table = table;
        this.tcm = table.getColumnModel();
    }

    public void hide(String columnName) {
        int index = tcm.getColumnIndex(columnName);
        TableColumn column = tcm.getColumn(index);
        IndexedColumn ic = new IndexedColumn(index, column);
        if (hidden.put(columnName, ic) != null) {
            throw new IllegalArgumentException("Duplicate column name.");
        }
        tcm.removeColumn(column);
    }

    public void show(String columnName) {
        IndexedColumn ic = hidden.remove(columnName);
        if (ic != null) {
            tcm.addColumn(ic.column);
            int lastColumn = tcm.getColumnCount() - 1;
            if (ic.index < lastColumn) {
                tcm.moveColumn(lastColumn, ic.index);
            }
        }
    }

    private static class IndexedColumn {

        private Integer index;
        private TableColumn column;

        public IndexedColumn(Integer index, TableColumn column) {
            this.index = index;
            this.column = column;
        }
    }

    public static void main(String[] args) {
        String[] columnNames = {
            "Name", "Size", "Type", "Date Modified", "Permissions"
        };
        String[][] data = {
            {"bin", "2", "dir", "Jun 9", "drwxr-xr-x"},
            {"boot", "3", "dir", "Jun 9", "drwxr-xr-x"},
            {"dev", "6", "dir", "Jul 12", "drwxr-xr-x"},
            {"etc", "34", "dir", "Jul 12", "drwxr-xr-x"}
        };
        JTable table = new JTable(data, columnNames);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());
        JScrollPane scrollPane = new JScrollPane(table);
        final TableColumnHider hider = new TableColumnHider(table);
        JPanel checkBoxes = new JPanel();
        for (int i = 0; i < columnNames.length; i++) {
            JCheckBox checkBox = new JCheckBox(columnNames[i]);
            checkBox.setSelected(true);
            checkBox.addActionListener(new ActionListener() {

                @Override
                public void actionPerformed(ActionEvent evt) {
                    JCheckBox cb = (JCheckBox) evt.getSource();
                    String columnName = cb.getText();

                    if (cb.isSelected()) {
                        hider.show(columnName);
                    } else {
                        hider.hide(columnName);
                    }
                }
            });
            checkBoxes.add(checkBox);
        }
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().add(scrollPane);
        frame.getContentPane().add(checkBoxes, BorderLayout.SOUTH);
        frame.pack();
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);
    }
}

回答by trashgod

Surely DefaultTableModelis more convenient, but AbstractTableModeloffers more flexibility and less overhead. There's an example herethat shows a model containing a List<Value>, where Valueis a POJO. More examples may be found here.

当然DefaultTableModel更方便,但AbstractTableModel提供了更多的灵活性和更少的开销。这里有一个例子在这里,包含显示模型的List<Value>,在那里Value是一个POJO。可以在此处找到更多示例。

回答by msugar

Beware that the code examples from mKorbeland trashgoddoesn't preserve the original order of the columns. Just try hiding all the columns in sequence and then showing them in the same sequence again (Name->Size->Type->Date Modified->Permissions), and you'll see that the original order is lost.

请注意,来自mKorbel垃圾神的代码示例不会保留列的原始顺序。只需尝试按顺序隐藏所有列,然后再次以相同的顺序显示它们(名称->大小->类型->修改日期->权限),您会看到原来的顺序丢失了。

If you need to preserve the original order of the columns when showing them again, look at Stephen Kelvin's solution.

如果再次显示时需要保留列的原始顺序,请查看Stephen Kelvin 的解决方案

Unfortunately, the confusion between "view" and "model" is prevalent in JTableAPI. Even the method names are misleading. For some enlightenment, see a related discussion here.

不幸的是,“视图”和“模型”之间的混淆在JTableAPI 中很普遍。甚至方法名称也具有误导性。有关一些启示,请参阅此处的相关讨论。

回答by Arvanem

I have adapted DefaultTableModel's addColumn method to a custom AbstractTableModel as follows. Assume that both the column identifiers (headers) and model data (localCache) are ArrayLists - the model data being an ArrayList of an ArrayList.

我已将 DefaultTableModel 的 addColumn 方法调整为自定义 AbstractTableModel,如下所示。假设列标识符(标题)和模型数据(localCache)都是 ArrayLists——模型数据是一个 ArrayList 的 ArrayList。

public void addColumn(String columnName, List columnData) {
    headers.add(columnName);
    colCount = headers.size();
    if (columnData != null) {
        for (int r = 0; r < localCache.size(); r++) {
            ((List)localCache.get(r)).add(columnData.get(r));
        }
    } else {
        System.out.println("Null columnData passed");
    }
    fireTableStructureChanged();
}