问题
I have read so many questions on this website concerning this problem and I cannot find why it is still not working.
The Problem:
I made a JTable to be displayed inside a JScrollPane. The JTable is constructed as follows:
table = new JTable(new DataTableModel());   
As you can see, I use a custom AbstractDataModel called DataTableModel. Now, when I display this the checkboxes appear, but they are not able to be selected. They are editable as you can see below. Here is the pertinent code in the DataTableModel class: (note that my column for check boxes is the first column, at index 0, and that my data in my array at this column is "null"). For some 
public class DataTableModel extends AbstractTableModel
{
    private String[][] data;
    private String[] header =
    { "", "KB Name", "fpGUID" };
    public DataTableModel() throws SQLException
    {
        // ========= CONNECTS TO DB AND PULLS RESULTS ==========
        // GETS RESULTS SET CALLED "rs"
        // populate data array
        int counter = 0;
        while (rs.next())
        {
            //data[counter][0] = "sfsdfsdfs ";
            data[counter][1] = (String) rs.getObject(2);
            data[counter][2] = (String) rs.getObject(4);
            counter++;
        }
        // =====================================================
    }
@Override
public String getValueAt(int rowIndex, int columnIndex)
{
    return data[rowIndex][columnIndex];
}
public boolean isCellEditable(int row, int col)
{
    return col == 0;
}
public Class getColumnClass(int column)
{
    if (column == 0)
    {
        return Boolean.class;
    } else
    {
        return String.class;
    }
}
So, it seems my getColumnClass() method is fine, so what is the problem? Could it be something with my "data" which I store the data for the table. Here is the data array:
回答1:
There are a number of things that jump out...
- (As has already begin pointed out) getValueAtappears to be declared wrong. It should be returningObject. Think about it for a second. Your expectation is that the first column will beboolean, so how can you returnStringfrom this method...which leads to...
- Your dataarray is an array ofString...where, again, the expectation is that the first value should beboolean. Now you can actually keep this, but you will need to translate the value tobooleanfrom thegetValueAtmethod and back again for thesetValueAtmethod...which leads to...
- You've not implemented setValueAt, so there is no way that the changes to the cell value can be stored
- You're also not implementing getRowCount, which is required,getColumnCount, which is required and you should implementgetColumnName, since you actually have some.
 
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.sql.SQLException;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.AbstractTableModel;
public class TestTableModel02 {
    public static void main(String[] args) {
        new TestTableModel02();
    }
    public TestTableModel02() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }
                JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JScrollPane(new JTable(new DataTableModel())));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }
    public class DataTableModel extends AbstractTableModel {
        private Object[][] data;
        private String[] header = {"", "KB Name", "fpGUID"};
        public DataTableModel() {//throws SQLException {
            // ========= CONNECTS TO DB AND PULLS RESULTS ==========
            // GETS RESULTS SET CALLED "rs"
            // populate data array
//            int counter = 0;
//            while (rs.next()) {
//                //data[counter][0] = "sfsdfsdfs ";
//                data[counter][1] = (String) rs.getObject(2);
//                data[counter][2] = (String) rs.getObject(4);
//
//                counter++;
//            }
            // =====================================================
            data = new Object[4][3];
            data[0] = new Object[]{false, "Help", "1234"};
            data[1] = new Object[]{false, "On fire", "5648"};
            data[2] = new Object[]{false, "Drowning", "9012"};
            data[3] = new Object[]{false, "Micky Mouse", "3456"};
        }
        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return data[rowIndex][columnIndex];
        }
        @Override
        public boolean isCellEditable(int row, int col) {
            return col == 0;
        }
        @Override
        public Class getColumnClass(int column) {
            if (column == 0) {
                return Boolean.class;
            } else {
                return String.class;
            }
        }
        @Override
        public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
            if (columnIndex == 0) {
                if (aValue instanceof Boolean) {
                    data[rowIndex][columnIndex] = (Boolean)aValue;
                    fireTableCellUpdated(rowIndex, columnIndex);
                }
            }
        }
        @Override
        public int getRowCount() {
            return data.length;
        }
        @Override
        public int getColumnCount() {
            return header.length;
        }
        @Override
        public String getColumnName(int column) {
            return header[column];
        }
    }
}
Now, there are ways you can get around the whole "first column must be boolean" issue, but to be frank, it's much less code to do it this way.
I would also, strongly, recommend that you take a look at SwingWorker and do all your data loading using it, otherwise you may find that your UI comes to a grinding halt while the data is begin loaded, which is generally rather unpleasant.
Take a look at...
- Concurrency in Swing
- How to use Tables
For more details
来源:https://stackoverflow.com/questions/17604459/check-boxes-not-able-to-be-selected-they-are-editable-java-swing