5

クラスがあります。

public class A extends AbstractTableModel
{
 ...
}

ResultSetMetaData を使用して、データベースからの結果セットと一致するように TableModel を構築します。

public class B extends JPanel
{
 ...
}

クラス Bでは、JPanel を拡張し、クラス Aを追加してテーブルを表示しました。条件に基づいて新しい列をテーブル モデルに追加できるようにしたいと考えています。DefaultTableModel私はグーグルで試してみましたが、示されているほとんどの例はnotに基づいていAbstractTableModelます。

これを達成する方法を知っている人はいますか?

4

6 に答える 6

16

例えば

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);
    }
}
于 2011-07-22T22:16:34.877 に答える
11

楽しみのために、これは @mKorbel の一般的なバージョンです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);
    }
}
于 2011-07-23T03:17:11.127 に答える
3

DefaultTableModel を拡張するだけで、そのすべてのメソッドにアクセスできます。DefaultTableModel は AbstractTableModel も拡張するため、コードの他の部分での AbstractTableModel への参照が壊れることはありません。

于 2011-07-22T17:31:50.790 に答える
2

確かにDefaultTableModelの方が便利ですが、AbstractTableModelの方が柔軟性が高く、オーバーヘッドが少なくなります。を含むモデルを示す例がここList<Value>にあります。ここValueで、はPOJOです。その他の例については、こちらを参照してください。

于 2011-07-22T18:05:25.070 に答える
1

mKorbelTrashgodのコード例では、列の元の順序が保持されていないことに注意してください。すべての列を順番に非表示にしてから、同じ順序で再度表示してみてください ([名前] -> [サイズ] -> [タイプ] -> [更新日] -> [権限])。元の順序が失われていることがわかります。

列を再度表示するときに列の元の順序を保持する必要がある場合は、Stephen Kelvin のソリューションを参照してください。

JTable残念ながら、 APIでは「ビュー」と「モデル」の混同が蔓延しています。メソッド名でさえ誤解を招きます。いくつかの啓発については、ここで関連する議論を参照してください。

于 2012-01-17T14:03:48.933 に答える
0

次のように、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();
} 
于 2012-04-12T17:56:31.153 に答える