Updating TableModel of spanned cell setHorizontalSpan causes IllegalArgumentException

36 Views Asked by At

Using con.setHorizontalSpan(2); produces IllegalArgumentException when trying to update TableModel, If I remove this line of code, the table updates normally; I basically need to span specific cells, and hide those cells that I don't need displayed, if I update data, cell spans might change according to new data,

class MyTable extends AbstractTableModel {

    public int getRowCount() {
        return 3;
    }

    @Override
    public int getColumnCount() {
        return 3;
    }

    @Override
    public String getColumnName(int arg0) {
        return arg0*10 + "";
    }

    @Override
    public boolean isCellEditable(int arg0, int arg1) {
        return false;
    }

    @Override
    public Object getValueAt(int arg0, int arg1) {
        return ((arg0 * cst + arg1) % 10);
    }

    @Override
    public void setValueAt(int arg0, int arg1, Object arg2) {

    }
    List<DataChangedListener> list = new ArrayList<DataChangedListener>();

    @Override
    public void addDataChangeListener(DataChangedListener arg0) {
        list.add(arg0);
    }

    @Override
    public void removeDataChangeListener(DataChangedListener arg0) {
        list.remove(arg0);
    }

    public void update() {
        for (int i = 0; i < 3; i++) {
            for (int o = 0; o < 3; o++) {
                for (DataChangedListener d : list) {
                    d.dataChanged(i, o);
                }
            }
        }

    }
}

public void testTable() {
    MyTable tm = new MyTable();

    current = new Form("Test");

    Table b = new Table(tm) {
        protected TableLayout.Constraint createCellConstraint(Object value, int row, int column) {

            TableLayout.Constraint con = super.createCellConstraint(value, row, column);
            con.setHorizontalSpan(1);
            if (value.toString().equals("1")) {
                //IF I REMOVE THIS LINE< THE PROGRAM WORKS
                con.setHorizontalSpan(2);
            }
            con.setWidthPercentage(100 / 3);
            return con;
        }

        @Override
        protected Component createCell(Object value, int row, int column, boolean editable) { // (1)

            Label label = new Label();
            System.err.println("c: " + column + " r: " + row);
            if (column != 0) {
                if (value.equals("2")) {
                    return label;
                }
            }
            label.setText(value.toString());
            return label;
        }
    };
    Button bt = new Button("test");

    bt.addActionListener(
            new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent arg0) {
            cst++;
            tm.update();
        }
    }
    );
    current.setLayout(
            new BoxLayout(BoxLayout.Y_AXIS));
    current.add(bt);

    current.add(b);

    current.show();
}

Error:

java.lang.IllegalArgumentException: Row: 2 and column: 0 already occupied [EDT] 0:0:26,270 - Exception: java.lang.IllegalArgumentException - Row: 2 and column: 0 already occupied at com.codename1.ui.table.TableLayout.addLayoutComponent(TableLayout.java:931) at com.codename1.ui.table.TableLayout.removeLayoutComponent(TableLayout.java:1069) at com.codename1.ui.Container.removeComponentImplNoAnimationSafety(Container.java:1320) at com.codename1.ui.Container.removeComponentImpl(Container.java:1309) at com.codename1.ui.Container.removeComponent(Container.java:1258) at com.codename1.ui.table.Table$Listener.dataChanged(Table.java:1013) at com.alhanah.samicalapp.SamiApplication$MyTable.update(SamiApplication.java:95)

1

There are 1 best solutions below

3
Shai Almog On

If you have two cells one next to the other and one is spanned on top of the other hiding the other it would cause a problem as we don't know which one to render. So your model needs to account to that and provide null data for the cell that's "hidden" by spanning.

You also can't span the last column so you need to protect against that too.

So you would need to make the following two changes to the table model, I made it relatively simple. This is in the table just don't span the last column:

        @Override
        protected TableLayout.Constraint createCellConstraint(Object value, int row, int column) {

            TableLayout.Constraint con = super.createCellConstraint(value, row, column);
            con.setHorizontalSpan(1);
            if (column != 2 && value.toString().equals("1")) {
                con.setHorizontalSpan(2);
            }
            // another minor fix so this adds up to 100
            if(col < 2) {
                 con.wp(33);
            } else {
                 con.wp(34);
            }
            return con;
        }

So this is in the model. Just return null for spanned over columns:

        @Override
        protected Component createCell(Object value, int row, int column, boolean editable) { 

            Label label = new Label();
            System.err.println("c: " + column + " r: " + row);
            if (column != 0) {
                if (value.equals("2")) {
                    return label;
                }
                Object o = getModel().getValueAt(row, column - 1);
                if(o != null && o.equals("1")) return null;
            }
            label.setText(value.toString());
            return label;
        }