Обновление TableModel составной ячейки setHorizontalSpan вызывает исключение IllegalArgumentException

Использование con.setHorizontalSpan(2); выдает IllegalArgumentException при попытке обновить TableModel. Если я удалю эту строку кода, таблица обновится нормально; В основном мне нужно охватывать определенные ячейки и скрывать те ячейки, которые мне не нужно отображать, если я обновляю данные, диапазоны ячеек могут меняться в соответствии с новыми данными,

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();
}

Ошибка:

java.lang.IllegalArgumentException: Строка: 2 и столбец: 0 уже заняты [EDT] 0:0:26,270 - Исключение: java.lang.IllegalArgumentException - Строка: 2 и столбец: 0 уже заняты в com.codename1.ui.table. TableLayout.addLayoutComponent(TableLayout.java:931) в com.codename1.ui.table.TableLayout.removeLayoutComponent(TableLayout.java:1069) в com.codename1.ui.Container.removeComponentImplNoAnimationSafety(Container.java:1320) в com.codename1 .ui.Container.removeComponentImpl(Container.java:1309) в com.codename1.ui.Container.removeComponent(Container.java:1258) в com.codename1.ui.table.Table$Listener.dataChanged(Table.java:1013 ) в com.alhanah.samicalapp.SamiApplication$MyTable.update(SamiApplication.java:95)


person Jari    schedule 28.08.2020    source источник


Ответы (1)


Если у вас есть две ячейки, одна рядом с другой, и одна наложена поверх другой, скрывая другую, это вызовет проблему, поскольку мы не знаем, какую из них отображать. Таким образом, ваша модель должна учитывать это и предоставлять нулевые данные для ячейки, скрытой охватом.

Вы также не можете охватить последний столбец, поэтому вам также необходимо защититься от этого.

Таким образом, вам нужно будет внести следующие два изменения в модель таблицы, я сделал это относительно просто. Это в таблице, просто не охватывайте последний столбец:

        @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;
        }

Так это в модели. Просто верните null для перекрывающихся столбцов:

        @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;
        }
person Shai Almog    schedule 29.08.2020
comment
Я не вижу, где вы возвращаете null в любом из ваших кодов, также, если я отобразил составную ячейку над другой, я вижу, что обе ячейки отображаются, и данные будут отображаться над другими, но это не проблема, поскольку я могу установить текст к проблеме, ЕСЛИ вы ОБНОВЛЯЕТЕ TableModel и переключаетесь между расположением данных, которые охватывают ячейки, вы получите эту ошибку! Я предполагаю, что модель обновляет разные ячейки, прежде чем другие вызывают исключение. Пожалуйста, попробуйте обновить TableModel, спасибо, я попытался сейчас вернуть нулевую погоду в createcell или getValueAt, это не помогло решить проблему. - person Jari; 29.08.2020
comment
Я исправил ответ. Поскольку вы обновляете всю таблицу и эффективно перестраиваете ее, попробуйте избежать метода update() и просто используйте table.setModel(model), который перестроит таблицу. - person Shai Almog; 30.08.2020
comment
На самом деле то, что я в конечном итоге сделал, это создавать новую TableModel каждый раз, когда происходят обновления, и используя метод setModel, я не думал об использовании той же модели, которую вы предложили, все работало. Пока не уверен, как это повлияет на моих слушателей для tableModel и запуск событий, но spanning теперь работает - person Jari; 30.08.2020