После добавления TableRowSorter добавление значений в модель вызывает java.lang.IndexOutOfBoundsException: недопустимый диапазон - PullRequest
11 голосов
/ 29 мая 2011

После добавления TableRowSorter в таблицу и соответствующую ей модель любые соответствующие добавления, в частности, в firetabletablerowsinserted вызывают исключения. Из тестирования видно, что GetRowCount () возвращает значение за пределами диапазона моделей. Однако мне не имеет смысла, как продолжать добавлять значения в таблицу после добавления сортировщика или фильтра?

В качестве примера я устанавливаю фильтр строк перед добавлением чего-либо в таблицу, затем добавляю значение в таблицу со следующими вызовами в моей модели:

this.addRow(row, createRow(trans,row));
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

Количество строк имеет размер 1, и выдается исключение:

java.lang.IndexOutOfBoundsException: Invalid range
at javax.swing.DefaultRowSorter.checkAgainstModel(Unknown Source)
at javax.swing.DefaultRowSorter.rowsInserted(Unknown Source)
at com.gui.model

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

this.addRow(row, createRow(trans,row));
this.fireTableStructureChanged()
this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

Я даже пытался уведомить сортировщик внутри модели о том, что значение было добавлено в модель, прежде чем вызывать fire, как показано ниже, но это также не удается:

 this.addRow(row, createRow(trans,row));
 if(sorter.getRowFilter() != null){
      //if a sorter exists we are in add notify sorter
      sorter.rowsInserted(getRowCount(), getRowCount());
  }
  this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

Наконец, я жестко закодировал FireTableRowsInsterted (0,0), и он не выдает никаких исключений. Но ничего не добавляется в таблицу? Итак, я знаю, что это определенно какая-то проблема OutOfBounds. Я оглянулся и не могу найти ответ. Если у кого-то есть идеи, как это работает, это будет очень полезно. Вот код, который устанавливает сортировщик внутри jpanel:

    messageTable.setRowSorter(null);
     HttpTransactionTableModel m = getTransactionTableModel();
     final int statusIndex = m.getColIndex("status");
     RowFilter<Object,Object> startsWithAFilter = new RowFilter<Object,Object>() {
           public boolean include(Entry<? extends Object, ? extends Object> entry) {

               for(char responseCode:responseCodes)
               {
                   if (entry.getStringValue(statusIndex).startsWith(Character.toString(responseCode))) {
                         return true;
                       }
               }


             // None of the columns start with "a"; return false so that this
             // entry is not shown
             return false;
           }
         };


        m.sorter.setRowFilter(startsWithAFilter);
        messageTable.setRowSorter(m.sorter);

Вот код внутри моей модели, который добавляет ценность модели:

public void update(Observable o, Object evt) {
    if (evt instanceof ObservableEvent<?>) {

        ObservableEvent<?> event = (ObservableEvent<?>) evt;

        if (event.getElement() instanceof HttpTransaction) {

            HttpTransaction trans = (HttpTransaction) event.getElement();

            // handle adding of an element
            if (event.getAction() == PUT) {

                if (includeTransaction(trans)) {

                    // handle request elements
                    if (trans.getRequest() != null && idMap.get(trans.getID()) == null) {

                        idMap.put(trans.getID(), count++);
                       // transactionManager.save(trans);
                        int row = idMap.get(trans.getID());
                        this.addRow(row, createRow(trans,row));
                        if(sorter.getRowFilter() != null){
                            sorter.rowsInserted(getRowCount(), getRowCount());
                        }
                        this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());

                    }

Ответы [ 3 ]

3 голосов
/ 03 июня 2011

У вас ошибка 1 на выходе.Правильный код для запуска события:

this.fireTableRowsInserted(this.getRowCount()-1, this.getRowCount()-1);
2 голосов
/ 16 августа 2012

Я вернулся и лучше посмотрел на это, увидев комментарий Клеопатры.Я изменял свою TableModel после создания RowSorter, но до подключения RowSorter к JTable.Вот пример, который показывает проблему, с которой я столкнулся.

import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableRowSorter;
import java.util.ArrayList;
import java.util.List;

public class TestTableMain {
    public static void main(String[] args) {
        new TestTableMain();
    }

    public TestTableMain() {
        SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                buildAndShowMainFrame();
            }
        });
    }

    private void buildAndShowMainFrame() {
        JFrame frame = new JFrame();
        JScrollPane scrollPane = new JScrollPane();

        TestTableModel model = new TestTableModel();
        JTable table = new JTable(model);

        TableRowSorter<TestTableModel> rowSorter = new TableRowSorter<>(model);
        rowSorter.setRowFilter(null);

        model.add("First added item.");
        /* The RowSorter doesn't observe the TableModel directly. Instead,
         * the JTable observes the TableModel and notifies the RowSorter
         * about changes. At this point, the RowSorter(s) internal variable
         * modelRowCount is incorrect.  There are two easy ways to fix this:
         *
         * 1. Don't add data to the model until the RowSorter has been
         * attached to the JTable.
         *
         * 2. Notify the RowSorter about model changes just prior to
         * attaching it to the JTable.
         */

        // Uncomment the next line to notify rowSorter that you've changed
        // the model it's using prior to attaching it to the table.
        //rowSorter.modelStructureChanged();
        table.setRowSorter(rowSorter);

        scrollPane.setViewportView(table);
        frame.setContentPane(scrollPane);

        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);

        model.add("Second added item.");
    }

    private class TestTableModel extends AbstractTableModel {
        private List<String> items = new ArrayList<>();

        public TestTableModel() {
            for(int i=0;i<5;i++) {
                add("Item " + i);
            }
        }

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

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

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            return items.get(rowIndex);
        }

        public void add(String item) {
            items.add(item);
            fireTableRowsInserted(items.size() - 1, items.size() - 1);
        }
    }
}
0 голосов
/ 29 мая 2011

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

                         if(sorter.getRowFilter() != null){
                             sorter.modelStructureChanged();
                           }
                           else
                         this.fireTableRowsInserted(this.getRowCount(), this.getRowCount());
...