2016-01-16 5 views
1

У меня есть следующий код для RowSorterListener. Целью этого является сортировка столбца без влияния на другие столбцы.Неверная сортировка столбца при нажатии JTable Header

import javax.swing.event.RowSorterListener; 
import javax.swing.event.RowSorterEvent; 
import javax.swing.JTable; 
import javax.swing.RowSorter.SortKey; 
import java.util.List; 
import java.util.Arrays; 

public class UnrelateData implements RowSorterListener { 
    JTable table; 
    int columnSorted = -1; 
    Object[][] dataStore; 

    public UnrelateData(JTable table) { 
     this.table = table; 
    } 

    @Override 
    public void sorterChanged(RowSorterEvent e) 
    { 
     if(e.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) { 
      List<SortKey> keys = e.getSource().getSortKeys(); 
      for (SortKey key : keys) { 
       if (key.getColumn() == -1) { 
        columnSorted = -1; 
        break; 
       } else { 
        columnSorted = key.getColumn(); 
        break; 
       } 
      } 
      dataStore = getData(); 
     } 

     if(e.getType() == RowSorterEvent.Type.SORTED) { 
      List<SortKey> keys = e.getSource().getSortKeys(); 
      for (SortKey key : keys) { 
       if (key.getColumn() == -1) { 
        columnSorted = -1; 
        break; 
       } else { 
        columnSorted = key.getColumn(); 
        break; 
       } 
      } 

      for(int i = 0; i < table.getColumnCount(); i++) { 
       if(i != columnSorted && columnSorted != -1) { 
        for (int j = 0; j < table.getRowCount(); j++) { 
         table.setValueAt(dataStore[i][j], j, i); 
        } 
       } 
      } 
     } 
    } 

    private Object[][] getData() { 
     int columnCount = table.getColumnCount(); 
     int rowCount = table.getRowCount(); 
     Object[][] tempData = new Object[columnCount][rowCount]; 

     for(int i = 0; i < columnCount; i++) { 
      for(int j = 0; j < rowCount; j++) { 
       tempData[i][j] = table.getValueAt(j, i); 
      } 
     } 

     return tempData; 
    }; 
} 

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

Column 2 and 3 switched

В то время как она должна выглядеть (где «Колонка 1» и «Колонка 2» остаются несортированный)

Column 2 and 3 switch properly

ли кто-то сможет объяснить, почему это происходит и как это исправить Это?

Примечание: Я не хочу использовать JTableHeader.reorderingAllowed(false)

Редактировать

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

Попытка 1

if(e.getType() == RowSorterEvent.Type.SORTED) { 
    int[] actualColumn = new int[table.getColumnCount()]; 
    for(int i = 0; i<table.getColumnCount(); i++){ 
     actualColumn[i] = table.convertColumnIndexToModel(i); 
    } 

    int[] actualRow = new int[table.getRowCount()]; 
    for(int i = 0; i<table.getRowCount(); i++){ 
     actualRow[i] = table.convertRowIndexToModel(i); 
    } 

    List<SortKey> keys = e.getSource().getSortKeys(); 
    for (SortKey key : keys) { 
     if (key.getColumn() == -1) { 
      columnSorted = -1; 
      break; 
     } else { 
      columnSorted = key.getColumn(); 
      break; 
     } 
    } 

    for(int i = 0; i < table.getColumnCount(); i++) { 
     if(i != columnSorted && columnSorted != -1) { 
      for (int j = 0; j < table.getRowCount(); j++) { 
       table.setValueAt(dataStore[i][j], actualRow[j], actualColumn[i]); 
      } 
     } 
    } 
} 

Покушение 2

private Object[][] getData() { 
    int columnCount = table.getColumnCount(); 
    int rowCount = table.getRowCount(); 

    int[] actualColumn = new int[columnCount]; 
    for(int i = 0; i<table.getColumnCount(); i++){ 
     actualColumn[i] = table.convertColumnIndexToModel(i); 
    } 

    int[] actualRow = new int[rowCount]; 
    for(int i = 0; i<table.getRowCount(); i++){ 
     actualRow[i] = table.convertRowIndexToModel(i); 
    } 

    Object[][] tempData = new Object[columnCount][rowCount]; 

    for(int i = 0; i < columnCount; i++) { 
     for(int j = 0; j < rowCount; j++) { 
      tempData[i][j] = table.getValueAt(actualRow[j], actualColumn[i]); 
     } 
    } 

    return tempData; 
}; 

Попытка 3 была и попытка один и два вместе взятые

+1

пожалуйста, Что 'если (key.getColumn() == -1) {', это значение может быть достигнуто исключением из 'RepaintManager' (некоторые из' indexOfBoundsException' может сделать это) – mKorbel

ответ

2

Из вашего описания проблемы (не смотрел на код), вы, вероятно, не преобразовывать индексы сообщенные из поля зрения индексов для моделирования индекса или наоборот.

Cf JTable общее описание, процитировать соответствующую часть:

Аналогично при использовании функции сортировки и фильтрации, обеспечиваемой RowSorter лежащих в основе TableModel не нужно знать, как сделать сортировку, а RowSorter будет обрабатывать его , Преобразование координат будет необходимо при использовании методов на основе строк JTable с базовым TableModel. Все методы JTables основаны на RowSorter, что не обязательно совпадает с TableModel. Например, выбор всегда равен JTable, поэтому при использовании RowSorter вам необходимо будет конвертировать с помощью convertRowIndexToView или convertRowIndexToModel. [...]

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

Для обработки этих преобразований, следующие методы существуют в JTable:

Небольшой пример, чтобы объяснить модель против зрения в JTable по отношению к йо ур проблема. Модель таблицы содержит данные. Представление - это то, что показано на экране. Представление сопоставляет столбцы с столбцами в модели. Когда столбец перетаскивается в другую позицию в представлении (т. Е. То, что вы видите на экране), ваша модель не изменяется (т. Е. Данные в контейнере данных не изменяются). Что происходит, так это изменение отображения из представления в модель.

Например, у вас есть три столбца A, B и C в вашей модели данных, и вы перетаскиваете второй столбец на экране в первую позицию, чтобы порядок стал B, A, C на экране. То, что делает вид, это изменение его отображения, чтобы показать столбец B в первой позиции, A во второй позиции и C в третьей позиции. Таким образом, отображение было view:1->model:A, view:2->model:B, view:3->model:C и после перетаскивания стало view:1->model:B, view:2->model:A, view:3->model:C.

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

Значит, вам всегда нужно знать, какие индексы вы получаете и что вы намереваетесь делать с ними. Если вы получаете индексы из таблицы (т. Е. Представление), и хотите использовать их для поиска значений в модели, сначала необходимо перевести индексы с помощью методов convertXXXToModel.

+0

К сожалению, это сделано не разница в проблеме извините – Dan

+1

@ Dan Я видел ваше обновление, и вы используете его неправильно. Пожалуйста, проверьте документацию по этим методам. Они имеют возвращаемое значение (преобразованный индекс), и вы не используете преобразованный индекс. По крайней мере, я не вижу этого в коротком фрагменте кода, который вы опубликовали. –

+0

Справедливая точка Я сейчас проверю – Dan

3
  • код в RowSorterListener является designatet для возвращения индекса правильно (с RowSorterListener сек события)

  • по умолчанию вам не нужно знать заказ от JTable посмотреть, все эти события models events,

  • добавить TableColumnModelListener в том случае, если вы хотите отследить columnMoved, все события сортировки программно окрашены в JTable s вид правильно

  • 1-й. attemtp без изменения порядка следования колонны,

enter image description here

Column NO. - 0 is sorted 
Column NO. - 1 is sorted 
Column NO. - 2 is sorted 
Column NO. - 3 is sorted 
Column NO. - 4 is sorted 

... and so on 
BUILD SUCCESSFUL (total time: 21 seconds) 

.

  • 2-й. Попытка с колонкой переназначения (путем перетаскивания мышью)

enter image description here

.

Column NO. - 0 is sorted 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
Column NO. - 1 is sorted 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnSelectionChanged from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
Column NO. - 2 is sorted 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
columnMoved from ColumnModelListener 
Column NO. - 3 is sorted 
Column NO. - 4 is sorted 
Column NO. - 0 is sorted 
Column NO. - 1 is sorted 
Column NO. - 2 is sorted 
BUILD SUCCESSFUL (total time: 10 seconds) 
  • третий. попытаться тот же правильный вывод, если свинг таймер не инициализирован, и все события сделаны пользователями вручную

  • , например

.

import java.awt.EventQueue; 
import java.awt.event.ActionEvent; 
import java.util.Arrays; 
import java.util.List; 
import java.util.Random; 

import javax.swing.*; 
import javax.swing.RowSorter.SortKey; 
import javax.swing.event.*; 
import javax.swing.table.*; 

public class SortTest1 { 

    private JFrame frame = new JFrame(getClass().getSimpleName()); 

    private DefaultTableModel model = new DefaultTableModel(10, 5) { 
     private static final long serialVersionUID = 1L; 

     @Override 
     public Class<?> getColumnClass(int column) { 
      return getValueAt(0, column).getClass(); 
     } 
    }; 
    private JTable table = new JTable(model); 
    private TableRowSorter<?> sorter; 
    private static final Random rnd = new Random(); 
    private Timer timer; 
    private int columnNo = 0; 


    public SortTest1() { 
     for (int row = model.getRowCount(); --row >= 0;) { 
      int i = 20 + row % 20; 
      model.setValueAt(row + " " + i, row, 0); 
      model.setValueAt(i + row, row, 1); 
      model.setValueAt(rnd.nextBoolean(), row, 2); 
      model.setValueAt(rnd.nextDouble(), row, 3); 
      model.setValueAt(row + " " + i * 1, row, 4); 
     } 
     table.setAutoCreateRowSorter(true); 
     sorter = (TableRowSorter<?>) table.getRowSorter(); 
     sorter.setSortsOnUpdates(true); 
     sorter.addRowSorterListener(new RowSorterListener() { 

      @Override 
      public void sorterChanged(RowSorterEvent rse) { 
       if (rse.getType() == RowSorterEvent.Type.SORT_ORDER_CHANGED) { 
        List<SortKey> keys = rse.getSource().getSortKeys(); 
        for (SortKey key : keys) { 
         System.out.println("Column NO. - " + key.getColumn() + " is sorted"); 
         if (key.getColumn() == 0) { 
          break; 
         } else { 
          break; 
         } 
        } 
       } 
      } 
     }); 
     frame.add(new JScrollPane(table)); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     table.getColumnModel().addColumnModelListener(new TableColumnModelListener() { 
      // just handle columnMarginChanged to re-paint headings 
      @Override 
      public void columnMarginChanged(ChangeEvent e) { 
       System.out.println("columnMarginChanged from ColumnModelListener"); 
      } 

      @Override 
      public void columnAdded(TableColumnModelEvent e) { 
       System.out.println("columnAdded from ColumnModelListener"); 
      } 

      @Override 
      public void columnRemoved(TableColumnModelEvent e) { 
       System.out.println("columnRemovedfrom ColumnModelListener"); 
      } 

      @Override 
      public void columnMoved(TableColumnModelEvent e) { 
       System.out.println("columnMoved from ColumnModelListener"); 
      } 

      @Override 
      public void columnSelectionChanged(ListSelectionEvent e) { 
       System.out.println("columnSelectionChanged from ColumnModelListener"); 
      } 
     }); 
     frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
     timer = new javax.swing.Timer(1000, updateCol()); 
     timer.setRepeats(true); 
     timer.start(); 
    } 

    private Action updateCol() { 
     return new AbstractAction("Sort JTable") { 
      private static final long serialVersionUID = 1L; 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       if (columnNo > 4) { 
        columnNo = 0; 
        sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(columnNo, SortOrder.ASCENDING)));    
       } else { 
        sorter.setSortKeys(Arrays.asList(new RowSorter.SortKey(columnNo, SortOrder.ASCENDING))); 
        columnNo++; 
       } 
      } 
     }; 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(() -> { 
      new SortTest1(); 
     }); 
    } 
} 
Смежные вопросы