Results 1 to 7 of 7
  1. #1
    Nicola is offline Member
    Join Date
    Feb 2009
    Posts
    4
    Rep Power
    0

    Default TableRowSorter, explicit comparator is not working

    Hi guys
    I've got a problem with the TableRowSorter.
    Cotext is this: I'd like to set up an explicit comparator for one of the columns of a JTable. In the customized table model I've got, I cannot override the getColumClass in my table model, so I need to specify an ad-hoc comparator. Problem's that once I click the column header the "sorting arrow" changes as to the sorting was taking place, but actually no sorting happens. Further, each entry of the table is an instance of a specific class.
    I've coded a small test case base on the actual one.
    Any help would be highly appreciated.

    Regards
    Nicola


    Here's the actual(dummy) testing code:

    Entry point to create the JTable:
    import java.awt.*;
    import java.util.*;

    import javax.swing.DefaultListSelectionModel;
    import javax.swing.*;
    import javax.swing.table.TableRowSorter;

    import com.enterprise.filmmanager.Film;
    import com.enterprise.filmmanager.table.FilmTableCell;
    import com.enterprise.filmmanager.table.FilmTableModelExt ended;

    public class FilmTableGUITestCase {

    final static List<Film> repository = new ArrayList<Film>();
    final static JFrame frame = new JFrame("Film Monitor");
    final static JTable table = new JTable();

    static {
    repository.add(new Film(10L, new Date(), "Not so1 bad", "1,000,000", false, Film.Category.FANTASY));
    repository.add(new Film(13L, new Date(), "Not so bad", "1,210", false, Film.Category.ACTION));
    repository.add(new Film(20L, new Date(), "Not so6 bad", "1,710", false, Film.Category.ACTION));
    repository.add(new Film(21L, new Date(), "Not so bad", "1,130", false, Film.Category.EPIC));
    repository.add(new Film(22L, new Date(), "Not so bad", "1,110", false, Film.Category.COMEDY));
    }

    private static class MyComparator1 implements Comparator<Object> {
    @Override
    public int compare(final Object f1, final Object f2) {
    try {
    final Long l1 = new Long(((FilmTableCell)f1).getData().replace(",","") );
    final Long l2 = new Long(((FilmTableCell)f2).getData().replace(",", ""));
    System.out.println("First: "l1", Second: "+l2);
    return l1.compareTo(l2);
    }
    catch(Exception e) {
    e.printStackTrace();
    return 0;
    }
    }
    }

    private static void initGUI() {
    final JPopupMenu popupMenu = new JPopupMenu();

    final JPanel tablePanel = new JPanel(new BorderLayout());
    table.setComponentPopupMenu(popupMenu);
    final FilmTableModelExtended filmTableModel = new FilmTableModelExtended(repository);
    table.setModel(filmTableModel);
    final ListSelectionModel filmTableSelectionModel = new DefaultListSelectionModel();
    filmTableSelectionModel.setSelectionMode(ListSelec tionModel.SINGLE_INTERVAL_SELECTION);
    table.setSelectionModel(filmTableSelectionModel);
    final TableRowSorter<FilmTableModelExtended> sorter = new TableRowSorter<FilmTableModelExtended>(filmTableMo del);
    sorter.setComparator(1, new MyComparator1());
    sorter.sort();
    table.setRowSorter(sorter);
    final JScrollPane tablePane = new JScrollPane(table);
    tablePanel.add(tablePane, BorderLayout.NORTH);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E);
    frame.setLocationRelativeTo(null);
    frame.setLocation(new Point(300, 300));
    final Container contentPane = frame.getContentPane();
    contentPane.add(tablePanel);
    frame.setSize(new Dimension(500, 500));
    frame.setVisible(true);
    }


    public static void main(String[] args) {
    final Runnable runnable = new Runnable() {
    public void run() {
    initGUI();
    }
    };
    EventQueue.invokeLater(runnable);
    }

    }

    TableModel and utility classes:
    package com.enterprise.filmmanager.table;
    import java.util.List;
    import javax.swing.table.AbstractTableModel;
    import com.enterprise.filmmanager.Film;
    public class FilmTableModelExtended extends AbstractTableModel {
    private List<Film> data;
    private String[] columns = new String[] {"ID", "Title", "Evaluation", "Download Data", "Watched", "Category"};
    private final FilmTableCell tableCell = new FilmTableCell();

    public FilmTableModelExtended(final List<Film> data) {
    this.data = data;
    }

    @Override
    public int getColumnCount() {
    return columns.length;
    }

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

    @Override
    public Object getValueAt(int row, int column) {
    tableCell.setAlert(false);
    if (row > data.size()) {
    tableCell.setData("");
    }
    else {
    final Film film = data.get(row);
    switch (column) {
    case 0:
    tableCell.setData(film.getId().toString());
    break;
    case 1:
    tableCell.setData(film.getTitle());
    break;
    case 2:
    tableCell.setData(film.getEvaluation());
    break;
    case 3:
    tableCell.setData(film.getDownloadDate().toString( ));
    break;
    case 4:
    tableCell.setData(film.isWatched().toString());
    break;
    case 5:
    tableCell.setData(film.getCategory().toString());
    break;
    default:
    throw new IllegalArgumentException("Unexpected Column on FilmTableModel: " + column);
    }
    }
    return tableCell;
    }

    public String getColumnName(int col) {
    switch (col) {
    case 0:
    return "ID";
    case 1:
    return "Title";
    case 2:
    return "Evaluation";
    case 3:
    return "Download Data";
    case 4:
    return "Watched";
    case 5:
    return "Category";
    }
    return "";
    }

    }

    package com.enterprise.filmmanager.table;

    public class FilmTableCell {

    private String data;
    private boolean alert;

    public FilmTableCell(final String data, final boolean alert) {
    this.data = data;
    this.alert = alert;
    }

    public FilmTableCell() {
    this.data = "";
    this.alert = false;
    }

    public void setData(final String data) {
    this.data = data;
    }

    public void setAlert(final boolean alert) {
    this.alert = alert;
    }

    public final String getData() {
    return data;
    }

    public final boolean isAlert() {
    return alert;
    }
    }

    package com.enterprise.filmmanager;
    import java.util.Comparator;
    import java.util.Date;

    public final class Film {

    public enum Category {
    ALL, FANTASY, ACTION, COMEDY, EPIC
    }

    private final Long id;
    private final String title;
    private final Boolean watched;
    private final Date downloadDate;
    private final String evaluation;
    private final Category category;

    public Film(final Long id, final Date downloadDate, final String evaluation, final String title,
    final Boolean watched, final Category category) {
    this.id = id;
    this.downloadDate = downloadDate;
    this.evaluation = evaluation;
    this.title = title;
    this.watched = watched;
    this.category = category;
    }

    public Category getCategory() {
    return category;
    }

    public Long getId() {
    return id;
    }

    public String getTitle() {
    return title;
    }
    public Boolean isWatched() {
    return watched;
    }
    public Date getDownloadDate() {
    return downloadDate;
    }
    public String getEvaluation() {
    return evaluation;
    }

    @Override
    public String toString() {
    return id + " " + title + " " + evaluation + " " + downloadDate + " " + category;
    }
    }

  2. #2
    Steve11235's Avatar
    Steve11235 is offline Senior Member
    Join Date
    Dec 2008
    Posts
    1,046
    Rep Power
    7

    Default

    First, you can look at Sorting and Filtering in the Sun Tutorial.

    Second, the easiest way I can see to sort a column is avoid implementing any sort of custom TableRowSort and simply ensure that the column you want to sort implements the Comparator interface. You may need to extend an existing class to do that, but that is easy. You just need a compareTo() method.

    I don't have time to analyze exactly what you did in your code, but I would suggest getting rid of the comparator and the sorter.

    In the TableModel interface implementation, implement the getColumnClass() method. In the column you want to sort on, modify the class to implement Comparator.

    Essentially, you are letting the framework do all the work by putting the specifics in TableModel.

  3. #3
    Nicola is offline Member
    Join Date
    Feb 2009
    Posts
    4
    Rep Power
    0

    Default

    Hi Steve
    Thank you for the reply. I've already read the tutorial and I know how it works sorting table's columns overriding the getColumnClass() in the table model. Unfortunately, I cannot override it, so I was looking for setting an explicit compator. I already did it plenty of times, the problem now is that, in my JTable, each entry is an instance of an ad-hoc class which holds the current value to be set in the entry itself. This is the only difference I see with my previos trials. The tricky point is that, after setting the TableRowSorter's comporator or extending TableRowSorter itself overriding the getComparator method, is that when the user click on the column with the explicit comparator all the machinery takes life (I mean, the vertical arrow), but the actual data remains unsorted, 'couse comparator uses the same data for both the entries to compare!
    Usually, you have int compare(Obj a1, Obj a2), what I see in my debug session is that the undelying infrastructure is passing the same value for both a1 and a2, where a1 and a2 are instances of my TableCell holder class.

    Cheers
    Nicola
    Last edited by Nicola; 02-18-2009 at 04:50 PM.

  4. #4
    Steve11235's Avatar
    Steve11235 is offline Senior Member
    Join Date
    Dec 2008
    Posts
    1,046
    Rep Power
    7

    Default

    OK, you are in over my head ;-)

  5. #5
    Nicola is offline Member
    Join Date
    Feb 2009
    Posts
    4
    Rep Power
    0

    Default

    No way! I had to restructure my TableModel to properly override the getColumnClass to solve the issue. It seems that wheenver you've got a proprer table cell value holder, there's no way make it working the customer comparator with the magic TableRowSorter.

  6. #6
    Steve11235's Avatar
    Steve11235 is offline Senior Member
    Join Date
    Dec 2008
    Posts
    1,046
    Rep Power
    7

    Default

    Why didn't I think of that... :-(

  7. #7
    Nicola is offline Member
    Join Date
    Feb 2009
    Posts
    4
    Rep Power
    0

    Default

    Quote Originally Posted by Steve11235 View Post
    Why didn't I think of that... :-(
    You know mate, that was the last ratio in my mind but I had to implement it since it seems there's something strnage I don't get in the TableRowSorter when applying a custom comparator and having a custom table cell holder.

    Cheers
    Nicola

Similar Threads

  1. Jtable + TableRowSorter
    By Ralphw in forum AWT / Swing
    Replies: 8
    Last Post: 02-05-2009, 10:39 AM
  2. Use different comparator for SortedSet
    By linus_k in forum New To Java
    Replies: 0
    Last Post: 11-21-2008, 03:46 PM
  3. How to search with a Comparator
    By Java Tip in forum java.lang
    Replies: 0
    Last Post: 04-15-2008, 08:39 PM
  4. How to write your own Comparator
    By Java Tip in forum java.lang
    Replies: 0
    Last Post: 04-15-2008, 08:38 PM
  5. Using Comparable and Comparator interfaces
    By barney in forum New To Java
    Replies: 1
    Last Post: 08-07-2007, 08:10 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •