2014-11-14 23 views
5

Proszę spojrzeć na poniższy kodNieprawidłowy Sortowanie data w JTable

import java.awt.*; 
import java.awt.event.*; 
import java.text.NumberFormat; 
import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.*; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.*; 
import javax.swing.table.*; 

public class TableBasic extends JFrame 
{ 
    public TableBasic() 
    { 

     String[] columnNames = {"Date", "String", "Long", "Boolean"}; 
     Object[][] data = 
     { 
      {getJavaDate("13-11-2020"), "A", new Long(1), Boolean.TRUE }, 
      {getJavaDate("13-11-2018"), "B", new Long(2), Boolean.FALSE}, 
      {getJavaDate("12-11-2015"), "C", new Long(9), Boolean.TRUE }, 
      {getJavaDate("12-11-2015"), "D", new Long(4), Boolean.FALSE} 
     }; 

     final JTable table = new JTable(data, columnNames); 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     table.setAutoCreateRowSorter(true); 
     table.getColumnModel().getColumn(0).setCellRenderer(tableCellRenderer); 

     // DefaultRowSorter has the sort() method 
     DefaultRowSorter sorter = ((DefaultRowSorter)table.getRowSorter()); 
     ArrayList list = new ArrayList(); 
     list.add(new RowSorter.SortKey(0, SortOrder.DESCENDING)); 
     sorter.setSortKeys(list); 
     sorter.sort(); 

     JScrollPane scrollPane = new JScrollPane(table); 
     getContentPane().add(scrollPane); 
    } 

    private TableCellRenderer tableCellRenderer = new DefaultTableCellRenderer() 
    { 

     SimpleDateFormat f = new SimpleDateFormat("dd-MM-yyyy"); 

     public Component getTableCellRendererComponent(JTable table,Object value, boolean isSelected, boolean hasFocus,int row, int column) 
     { 
      if(value instanceof Date) 
      { 
       value = f.format(value); 
      } 
      return super.getTableCellRendererComponent(table, value, isSelected,hasFocus, row, column); 
     } 
    }; 

    private Date getJavaDate(String s) 
    { 
     try { 
      SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); 
      Date d = sdf.parse(s); 
      return d; 

     } catch (ParseException ex) { 
      Logger.getLogger(TableBasic.class.getName()).log(Level.SEVERE, null, ex); 
      return null; 
     } 
    } 



    public static void main(String[] args) 
    { 
     TableBasic frame = new TableBasic(); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 
} 

Teraz, po prostu starają się rozwiązać to za pomocą pola Date. Sortuje to w nieprawidłowy sposób! Poniżej znajduje się wynik!

enter image description here

Dlaczego tak się dzieje w ten sposób? Użyłem nawet cell render!

Odpowiedz

4

@ Sniper nie jest answert, ale nie mogę się oprzeć, bo kod jest bardzo skomplikowane, źle zaprojektowane, brakuje tam lighweight wymagane dla ...

Kluczowym elementem brakuje jest ominięcie TableModel. getColumnClass(), jest niezbędny do sortowania tabeli funkcjonować

import java.awt.*; 
import java.text.DateFormat; 
import java.text.ParseException; 
import java.text.SimpleDateFormat; 
import java.util.*; 
import java.util.logging.Level; 
import java.util.logging.Logger; 
import javax.swing.*; 
import static javax.swing.JFrame.EXIT_ON_CLOSE; 
import javax.swing.table.*; 

public class TableBasic { 

    private JFrame frame = new JFrame(); 
    private String[] columnNames = {"Date", "String", "Long", "Boolean"}; 
    private Object[][] data = { 
     {getJavaDate("13-11-2020"), "A", new Double(1), Boolean.TRUE}, 
     {getJavaDate("13-11-2018"), "B", new Double(2), Boolean.FALSE}, 
     {getJavaDate("12-11-2015"), "C", new Double(9), Boolean.TRUE}, 
     {getJavaDate("12-11-2015"), "D", new Double(4), Boolean.FALSE} 
    }; 
    private DefaultTableModel model = new DefaultTableModel(data, columnNames) { 
     @Override 
     public Class<?> getColumnClass(int column) { 
      return getValueAt(0, column).getClass(); 
     } 
    }; 
    private JTable table = new JTable(model); 
    private JScrollPane scrollPane = new JScrollPane(table); 
    private static final DateFormat DATE_FORMAT = new SimpleDateFormat("dd/MM/yyyy"); 

    public TableBasic() { 
     table.setPreferredScrollableViewportSize(table.getPreferredSize()); 
     table.setAutoCreateRowSorter(true); 
     setRenderers(); 
     // DefaultRowSorter has the sort() method 
     table.getRowSorter().toggleSortOrder(0); 
     frame.add(scrollPane); 
     frame.setDefaultCloseOperation(EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setLocationRelativeTo(null); 
     frame.setVisible(true); 
    } 

    private void setRenderers() { 
     //TableColumnModel m = table.getColumnModel(); 
     //"Integer", "String", "Interger", "Double", "Boolean", "Double", "String", "Boolean", "Date" 
     table.setDefaultRenderer(Date.class, new DateRenderer()); 
    } 

    private Date getJavaDate(String s) { 
     try { 
      SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy"); 
      Date d = sdf.parse(s); 
      return d; 

     } catch (ParseException ex) { 
      Logger.getLogger(TableBasic.class.getName()).log(Level.SEVERE, null, ex); 
      return null; 
     } 
    } 

    public static void main(String[] args) { 

     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       TableBasic frame = new TableBasic(); 
      } 
     }); 
    } 

    private class DateRenderer extends DefaultTableCellRenderer { 

     private static final long serialVersionUID = 1L; 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { 
      super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); 
      if (!(value instanceof Date)) { 
       return this; 
      } 
      setText(DATE_FORMAT.format((Date) value)); 
      return this; 
     } 
    } 
} 
+0

Dzięki. Doceniam odpowiedź. –

+0

@Sniper, jesteś mile widziany – mKorbel

5

tabela nie wie, że kolumna zawsze zawiera Data instancji i że musi więc rodzaj chronologicznie, chyba że dasz mu te informacje, poprzez nadpisanie metody getColumnClass() modelu tabeli:

final Class<?>[] columnClasses = new Class<?>[] {Date.class, String.class, Long.class, Boolean.class}; 

DefaultTableModel model = new DefaultTableModel(...) { 
    @Override 
    public Class<?> getColumnClass(int column) { 
     return columnClasses[column]; 
    } 
}); 
JTable table = new JTable(model); 

dodatkowe bonus: kolumny liczbowe i boolowskie będą automatycznie renderowane i sortowane poprawnie.

+0

Dzięki za odpowiedź. W którym miejscu powinienem umieścić twój kod? –

+0

i, nie mam jasności co do kodu, Umysł dostarczający kompletny wykonalny przykład, proszę? –

+0

@munyul: Zrobiłem to już i ustawiłem model bez parametrów. Ale po prostu daje "wyjątek ArrayIndexOutOfBounds" –

2

Oto odpowiedź, stosując kod z JB Nizet

String[] columnNames = {"Date", "String", "Long", "Boolean"}; 
    Object[][] data = 
    { 
     {getJavaDate("13-11-2020"), "A", new Long(1), Boolean.TRUE }, 
     {getJavaDate("13-11-2018"), "B", new Long(2), Boolean.FALSE}, 
     {getJavaDate("12-11-2015"), "C", new Long(9), Boolean.TRUE }, 
     {getJavaDate("12-11-2015"), "D", new Long(4), Boolean.FALSE} 
    }; 

    final Class<?>[] columnClasses = new Class<?>[] {Date.class, String.class, Long.class, Boolean.class}; 

    DefaultTableModel model = new DefaultTableModel() { 
     @Override 
     public Class<?> getColumnClass(int column) { 
      return columnClasses[column]; 
     } 
    }; 
    model.setDataVector(data, columnNames); 

    final JTable table = new JTable(model); 

Ten kod jest przesyłany do konstruktora, zastępując kilka pierwszych wierszy w nim.