Динамический JTable, расширяющий AbstractTableModel

Я хотел бы создать JTable, который может динамически добавлять строки к себе, изначально в таблице не должно быть данных. Я сделал это, создав класс TableModel, расширяющий AbstractTableModel, код прилагается.

class MyTableModel extends AbstractTableModel{

    private static int initialRowCount = 3;
    private ArrayList<ArrayList<Object>> data;
    private static String[] columnName = {"Date Tested","Product","VI Test Result","Lot ID","MCN","SLT TIS","Tester","In","First Pass","FP%","RT1 Pass","RT2 Pass","Final Pass",
        "SLT Final Yield %","SLT Fail Quantity","Remark"};
    int i=0;

    public MyTableModel(){
        data = new ArrayList<ArrayList<Object>>(20);
    }

    public int getColumnCount() {
        System.out.println(i++);
        return columnName.length;
    }

    public int getRowCount() {
        return initialRowCount;
    }

    public Object getValueAt(int r, int c) {

    }

    public String getColumnName(int c) {
        return columnName[c];
    }    

    public boolean isCellEditable(int row, int column) {
        if(column==0)
            return false;
        else
        return true;
    }

    public void setValueAt(Object vaule,int row,int column){
        data.add();
    }

    public void addRow(){
        initialRowCount++;
    }
}

Мой вопрос: должен ли я использовать 2-D ArrayList в качестве контейнера данных? Если да, то как мне реализовать это в этом коде? Я новичок в Java и только начинаю изучать Swing, любая помощь приветствуется.


person user3595179    schedule 07.05.2014    source источник
comment
DefaultTableModel внутри использует Vector внутри Vector. Если вы не знаете фактический тип данных для строки (т. е. это не стандартный POJO), я бы предложил использовать что-то подобное. На самом деле, просто используйте вместо этого DefaultTableModel...   -  person MadProgrammer    schedule 07.05.2014
comment
Спасибо за своевременный ответ, я хотел бы иметь возможность делать что-то еще, поэтому мне нужно написать свою собственную TableModel. Возможен ли в этом случае ArrayList массива объектов, потому что я только расширяю строки.   -  person user3595179    schedule 07.05.2014
comment
Я бы использовал List из List для простоты   -  person MadProgrammer    schedule 07.05.2014
comment
есть два способа: 1. использовать DefaultTableModel, 2. переопределить уведомители для просмотра в setValueAt и addRow, 3. тип базового массива не важен для AbstractTableModel (за исключением HashMap или HashWhatever == не имеет индексации)   -  person mKorbel    schedule 07.05.2014


Ответы (1)


Вы можете попробовать следующий простой пример JTable с пользовательскими TableModel(MyModel), которые позволяют добавлять/удалять строки и столбцы. Данные строки хранятся в обернутом объекте (RowData). Фильтрация и сортировка в модели не поддерживаются, но их можно просто добавить.

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellEditor;


public class TestFrame extends JFrame{

    private MyModel model;
    private JTable table;

    public TestFrame(){
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        init();
        pack();
        setVisible(true);
    }

    private void init() {
        table = new JTable(model = new MyModel());

        JButton add = new JButton("add row");
        add.addActionListener(getAddListener());
        JButton remove = new JButton("remove row");
        remove.addActionListener(getRemoveListener());
        JButton addC = new JButton("add column");
        addC.addActionListener(getAddColListener());
        JButton removeC = new JButton("remove column");
        removeC.addActionListener(getRemoveColListener());

        add(new JScrollPane(table));
        JPanel p = new JPanel();
        p.add(add);
        p.add(remove);
        p.add(addC);
        p.add(removeC);
        add(p,BorderLayout.SOUTH);
    }

    private ActionListener getRemoveColListener() {
        return new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int selectedColumn = table.getSelectedColumn();
                if(selectedColumn != -1){
                    stopEditing();
                    model.removeColumn(selectedColumn);
                }
            }
        };
    }

    private ActionListener getAddColListener() {
        return new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                model.addColumn();
            }
        };
    }

    private ActionListener getRemoveListener() {
        return new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                int selectedRow = table.getSelectedRow();
                if(selectedRow != -1){
                    stopEditing();
                    model.removeRow(selectedRow);
                }
            }

        };
    }

    private ActionListener getAddListener() {
        return new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                model.addRow();
            }
        };
    }

    private void stopEditing() {
        TableCellEditor cellEditor = table.getCellEditor();
        if(cellEditor != null){
            cellEditor.stopCellEditing();
        }
    }

    public static void main(String... strings) {
        new TestFrame();
    }

    private class RowData{

        private Map<Integer, Object> values = new HashMap<Integer, Object>();

        public Object getValueForCol(int columnIndex) {
            if(values.containsKey(columnIndex)){
                return values.get(columnIndex);
            }
            return "";
        }

        public void setValueForCol(Object aValue, int columnIndex) {
            values.put(columnIndex, aValue);
        }

    }

    private class MyModel extends AbstractTableModel{

        int colIndex=0;
        private List<Integer> cols = new ArrayList<Integer>();
        private List<RowData> rows = new ArrayList<TestFrame.RowData>();

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return true;
        }

        @Override
        public String getColumnName(int column) {
            return cols.get(column).toString();
        }

        @Override
        public int getRowCount() {
            return rows.size();
        }

        public void addRow() {
            rows.add(new RowData());
            fireTableRowsInserted(rows.size(), rows.size());
        }


        public void removeRow(int selectedRow) {
            rows.remove(selectedRow);
            fireTableRowsDeleted(selectedRow, selectedRow);
        }

        public void removeColumn(int selectedColumn) {
            cols.remove(table.convertColumnIndexToModel(selectedColumn));
            fireTableStructureChanged();
        }

        public void addColumn() {
            cols.add(++colIndex);
            fireTableStructureChanged();
        }

        @Override
        public int getColumnCount() {
            return cols.size();
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            RowData rowData = rows.get(rowIndex);
            return rowData.getValueForCol(cols.get(columnIndex));
        }

        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            RowData rowData = rows.get(rowIndex);
            rowData.setValueForCol(aValue,cols.get(columnIndex));
            fireTableCellUpdated(rowIndex, columnIndex);
        }

    }
person alex2410    schedule 07.05.2014
comment
Спасибо, я попробую это сегодня вечером и дам отзыв. - person user3595179; 07.05.2014