> Hi,
> i have a table whose columns can contain either Strings, Integers, or
[quoted text clipped - 16 lines]
> and still maintain the underlying class type of Value so that i can be
> properly sorted....
It's not clear to me how you do the sorting. I'm assuming that you are
using your own TableModel that takes care of this. Then, make sure that
your TableModel (if you have one) returns the correct Class for each
column in the getColumnClass method (i.e. Float.class for the Float
columns). If this is the case then you can set the default renderer of
your table for Float.class to be your TableCellRenderer:
YourTableModel yourTableModel = ...
YourCellRenderer yourCellRenderer = ...
JTable yourTable = new JTable(yourTableModel);
yourTable.setDefaultRenderer(Float.class, yourCellRenderer);
Otherwise (or alternatively) you can specify a TableCellRenderer for
each column separately:
yourTable.getColumnModel()
.getColumn(1).setCellRenderer(yourCellRenderer);
Your TableCellRenderer could use a DecimalFormat instance, so it can
format Float values to two decimal places. The code below shows a
complete example:
import java.awt.BorderLayout;
import java.text.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableExample {
public static void main(String[] args) {
Object[][] rowData = {
{new Float(0.0),new Float(0.1),new Integer( 2),"[0,3]"},
{new Float(1.0),new Float(1.1),new Integer(12),"[1,3]"},
{new Float(2.0),new Float(2.1),new Integer(22),"[2,3]"}};
Object[] colNames = { "A", "B", "C", "D" };
YourTableModel yourTableModel =
new YourTableModel(rowData, colNames);
JTable yourTable = new JTable(yourTableModel);
yourTable.setDefaultRenderer(Float.class,
new YourCellRenderer("0.0"));
yourTable.getColumnModel().getColumn(1).setCellRenderer(
new YourCellRenderer("0.00"));
JFrame app = new JFrame();
app.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
app.getContentPane().setLayout(new BorderLayout());
app.getContentPane().add(new JScrollPane(yourTable),
BorderLayout.CENTER);
app.setSize(400, 300);
app.setLocationRelativeTo(null);
app.setVisible(true);
}
}
class YourCellRenderer extends DefaultTableCellRenderer {
private final NumberFormat formatter;
public YourCellRenderer() {
this.formatter = NumberFormat.getNumberInstance();
setHorizontalAlignment(JLabel.RIGHT);
}
public YourCellRenderer(String format) {
if (format == null) {
throw new IllegalArgumentException("format cannot be null");
}
this.formatter = new DecimalFormat(format);
setHorizontalAlignment(JLabel.RIGHT);
}
protected void setValue(Object value) {
if (value instanceof Number) {
value = formatter.format(value);
}
super.setValue(value);
}
}
class YourTableModel extends DefaultTableModel {
public YourTableModel(Object[][] data, Object[] columnNames) {
super(data, columnNames);
}
public Class getColumnClass(int columnIndex) {
switch (columnIndex) {
case 0:
return Float.class;
case 1:
return Float.class;
case 2:
return Integer.class;
case 3:
return String.class;
default:
return Object.class;
}
}
}

Signature
Regards,
Roland de Ruiter
` ___ ___
`/__/ w_/ /__/
/ \ /_/ / \
Thomas G. Marshall - 27 Jun 2005 14:59 GMT
Roland coughed up:
...[rip]...
> Your TableCellRenderer could use a DecimalFormat instance, so it can
> format Float values to two decimal places. The code below shows a
> complete example:
This raises to me an important point, to the side of this discussion, and
it's one that is often overlooked.
When creating applications that might be run /anywhere/ in any country,
which is pretty much the norm since the internet, I use NumberFormat and
it's descendents religiously.
In fact, in general, it's a /very/ good idea IMO to just start using
NumberFormat.{parse,format})() wherever possible.
You will:
1. No doubt eventually someday have a user enter in
1.000,00
in the UK.
2. It is often glitzy to have precise control over the displaying of numbers
with separators (comma, period, whatever). Furthermore there are some
locales which like these things separated by 4 digits, and then change the
rules for larger numbers. This is all built in to java automatically.
3. The issue with tables when using formatting is that you need to be
careful to supply the correct sorting mechanism, so that 1,000, for example,
does not become lexically sorted. This is always the case anyway, you must
sort by the numerical value, but this isn't always adhered to and I've seen
code place 10 before 2 when sorting on a numerical column.
...[rip]...

Signature
Doesn't /anyone/ know where I can find a credit card company that
emails me the minute something is charged to my account?
farseer - 27 Jun 2005 21:53 GMT
Thank you for the responses.
1. I would prefer setting a renderer for each column, rather than
assigning renderer for datatypes of that table. This is simply because
of the way i am implementing this. I have an interface named IBehavior
that declares one method, "doBehavior()". My TableCellRender contains
a list of Behaviors. Behaviors are rendering specific actions that
should occur for a given column/cell (i.e. change
foreground/background/border colors depending on the value being
shown). This way i can add multiple behaviors that should be executed
for a given column/cell and simply iterate thru the Behavior list for
that column and call doBheavior. I think i can implment my Formatter
as simply another IBehavior
2. I think you may have answered my question. Currently, i do use a
custom TableModel, and it does indeed override getColumnClass to return
value.getClass. This is how i have gotten sorting to work correctly
(before it sorting was incorrect because everything was being treated
as String).
The following snippet of your code i think answers my question:
protected void setValue(Object value) {
if (value instanceof Number) {
value = formatter.format(value);
}
super.setValue(value);
}
Above, formatter.format(value) will return a String. What you are
saying is that this does not matter for sorting, since my sorting is
being driven off the TableModel and there my getColumnClass method will
return the correct Class Type. Basically, the code above is strictly
for display purposes...and should not affect my sorting, is that
correct?