简体   繁体   中英

JTable Reverts JComboBox and JCheckBox to Values after Selection

I have a JTable with a column of JComboBox<Integer> s and a column of JCheckBox s. The JTable is set with the appropriate renderers and editors. The table looks fine at first, but after selecting a value from the combobox or checkbox, the cells seem to revert to the values of Integer and Boolean. The issue appears to be more than cosmetic, as methods that anticipate the cell having a combobox or a checkbox throw errors at finding an Integer or a Boolean.

Here is a picture of what it looks like:

在此处输入图片说明

And here is the code:

    dataTable.removeAll();
    numberOfVariables = 7;
    Object[] header = new Object[numberOfVariables];
    header[0] = new String("Ring Number");
    header[1] = new String("Radius (cm)");
    header[2] = new String("Plume Distribution");
    header[3] = new String("Thickness (A)");
    header[4] = new String("Deposition Time (s)");
    header[5] = new String("Rate (A/s)");
    header[6] = new String("Optimize (y/n)");

    Object[][] data = new Object[numberOfRings][numberOfVariables];
    for(int k=0;k<numberOfRings;++k){
        Object[] row = new Object[numberOfVariables];
        row[0] = Integer.toString(k+1);
        row[1] = String.format("%.2f", plume.getRingRadius(k));
        row[2] = createDistributionComboBoxForRing(k);
        row[3] = String.format("%.2f", plume.getThicknessOfRing(k));
        row[4] = String.format("%.2f", plume.getTimeForRing(k));
        row[5] = String.format("%.2f", plume.getRateForRing(k));
        row[6] = new JCheckBox();
        ((JCheckBox) row[6]).setSelected(true);
        data[k] = row;
    }
    tableModel = new DefaultTableModel(data,header);
    dataTable.setModel(tableModel);
    dataTable.getColumnModel().getColumn(2).setCellRenderer(new ControlTableRenderer());
    //dataTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor( createDistributionComboBoxForRing(0) ));
    dataTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor( (JComboBox<Integer>) data[0][2] ));
    dataTable.getColumnModel().getColumn(6).setCellRenderer(new ControlTableRenderer());
    dataTable.getColumnModel().getColumn(6).setCellEditor(new DefaultCellEditor( (JCheckBox) data[0][6] ));
    dataTable.updateUI();
row[2] = createDistributionComboBoxForRing(k);
row[3] = String.format("%.2f", plume.getThicknessOfRing(k));
row[4] = String.format("%.2f", plume.getTimeForRing(k));
row[5] = String.format("%.2f", plume.getRateForRing(k));
row[6] = new JCheckBox();
((JCheckBox) row[6]).setSelected(true);

The TableModel for a JTable stores data, not components.

So if column 3 contains an Integer object then you store an Integer in the TableModel and you set the editor for the column to be a combo box containing the list of valid Integers.

Same for the column containing the check box renderer/editor. In this case you store a Boolean object.

For example:

row[2] = new Integer(1);
row[6] = Boolean.TRUE

Now in the TableModel you need to tell the table what type of data is in each column so you need to override the getColumnClass(...) method. Something like:

tableModel = new DefaultTableModel(data,header)
{
    @Override
    public Class getColumnClass(int column)
    {
        switch (column)
        {
            case 2: return Integer.class;
            case 6: return Boolean.class;
            default: return Object.class;
        }
    }
};

Now the table can choose the appropriate renderer and editor for each column.

However, in the case of the combo box you do have to create a custom editor with the values for the combo box. See the section from the Swing tutorial on Using a Combo Box as an Editor for a working example on how to do this.

Also, you are incorrectly using some other methods:

dataTable.removeAll();

Not sure what that is for. That is a Container method to remove components from the panel. All you need is the setModel(...) statement to reset the table.

dataTable.updateUI();

There is no need to use the updateUI() method. That method is used internally when the LAF is changed. You are not changing the LAF so get rid of that statement.

The idea of cell renderers and editors is that you only have one component and that gets moved around and data changed for each row. The code uses a different JComponent instance for each cell. Just put the data in the table model and let the cell renderer and editors manage the components.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM