javaswingjtablejxtable

How to set a JTable column as String and sort as Double?


I'm still fairly new to Java and have a question in regards to JTable (more specifically JXTable) and sorting rows by column class with mixed data type... Let me elaborate...

I have a JXTable that holds data for a product listing. This table has a column for price which I have set to String.class only so that I can display a price with a '$' prepended.

The problem I'm having is when the rows are sorted by price, they are not sorted as Doubles, but rather they are sorted as strings so these values:

89.85, 179.70, 299.40, 478.80

are sorted as:

179.70, 299.40, 478.80, 89.85 (Ascending) and 89.85, 478.80, 299.40, 179.70 (Descending)

What I would like to do is remove the '$' at the time of sorting and sort the column as Doubles. How would I accomplish this?

EDIT:

Thank you very much Jiri Patera for your response. It was a great help in helping me to understand that the tablecellrenderer is responsible for manipulating values in these types of situations. Below is the finished excerpt that has finally accomplished what I want.

public Component getTableCellRendererComponent(JTable pTable, Object pValue, boolean pIsSelected, boolean pHasFocus, int pRow, int pColumn) {

        // Use the wrapped renderer
        Component renderedComponent = mWrappedRenderer.getTableCellRendererComponent(pTable, pValue, pIsSelected, pHasFocus, pRow, pColumn);
        Component renderedComponentHeader = pTable.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(pTable, pValue, pIsSelected, pHasFocus, pRow, pColumn);

        if (pColumn == 4 && pValue instanceof Double){
            DecimalFormat df = new DecimalFormat("$###,##0.00");
            Double d = (Double) pValue;
            String s = df.format(d);
            renderedComponent = mWrappedRenderer.getTableCellRendererComponent(pTable, s, pIsSelected, pHasFocus, pRow, pColumn);
        }

        // Set the alignment
        Integer alignment = mSpecialColumnAlignmentMap.get(pColumn);
        Integer width = mSpecialColumnWidthMap.get(pColumn);
        if (alignment != null) {
            ((JLabel) renderedComponent).setHorizontalAlignment(alignment);
            ((JLabel) renderedComponentHeader).setHorizontalAlignment(alignment);
        } else {
            ((JLabel) renderedComponent).setHorizontalAlignment(mDefaultAlignment);
            ((JLabel) renderedComponentHeader).setHorizontalAlignment(mDefaultAlignment);
        }

        if (width != null){
            pTable.getColumnModel().getColumn(pColumn).setPreferredWidth(width);
            pTable.getColumnModel().getColumn(pColumn).setMaxWidth(width);
        }

        return renderedComponent;
    }

As you can see, I already had a custom tablecellrenderer. I used the DecimalFormat to format the price as I want it.

Hope this helps someone else out in the future.


Solution

  • HFOE is right. However, this may be tricky for a Java newbie. Pardon me for using anonymous inner classes. See the following example to get some hints...

    
    package test;
    
    import java.awt.Component;
    import java.util.ArrayList;
    import java.util.List;
    
    import javax.swing.JFrame;
    import javax.swing.JScrollPane;
    import javax.swing.JTable;
    import javax.swing.table.AbstractTableModel;
    import javax.swing.table.DefaultTableCellRenderer;
    
    
    public class TableTest {
    
      public static void main(String[] args) {
        TableTest tt = new TableTest();
        tt.start();
      }
    
      private void start() {
        JTable t = new JTable(new AbstractTableModel() {
          private static final long serialVersionUID = 1L;
          private List<Double> values = new ArrayList<Double>();
          {
            values.add(Double.valueOf(179.70d));
            values.add(Double.valueOf(299.40d));
            values.add(Double.valueOf(478.80d));
            values.add(Double.valueOf(89.85d));
          }
          @Override
          public String getColumnName(int column) {
            return "Double";
          }
          @Override
          public Class<?> getColumnClass(int column) {
            return Double.class;
          }
          @Override
          public int getRowCount() {
            return values.size();
          }
          @Override
          public int getColumnCount() {
            return 1;
          }
          @Override
          public Object getValueAt(int rowIndex, int columnIndex) {
            return values.get(rowIndex);
          }
        });
        t.setDefaultRenderer(Double.class, new DefaultTableCellRenderer() {
          private static final long serialVersionUID = 1L;
          @Override
          public Component getTableCellRendererComponent(JTable table,
              Object value, boolean isSelected, boolean hasFocus, int row,
              int column) {
            Double d = (Double)value;
            String s = "$" + String.valueOf(d.doubleValue());
            Component c = super.getTableCellRendererComponent(table, s, isSelected, hasFocus,
                row, column);
            return c;
          }
        });
        t.setAutoCreateRowSorter(true);
        JFrame f = new JFrame();
        f.setSize(320, 200);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JScrollPane sp = new JScrollPane(t);
        f.getContentPane().add(sp);
        f.setVisible(true);
      }
    
    }