Java Forum / GUI / January 2005
Funky problem with JTable cell rendering
Jan Danielsson - 31 Dec 2004 10:16 GMT Hello all,
I know: "This has been answered a thousand times before, search Google Groups".
But I'd like to add something..
This is my problem, it's a well known one - I've found it on several Java forums:
I have a JTable, a table model for it, and a custom cell renderer which should change the text color to red. The problem is that the text never becomes red.
I've added a System.out.println("Check!") line to getTableCellRendererComponent() in my cell renderer. I never see any "Check" message.
At this point, I expect to get the most common answer: "You need to implement getColumClass() in your table model".
I already did that, look: ------- public Class getColumClass(int col) { System.out.println("Returning: " + getValueAt(0, col).getClass()); return getValueAt(0, col).getClass(); } -------
Now, that function doesn't get called. Ever.
"So, you messed up. You forgot to associate the table with this model".
Actually, no, because the table header and table test data shows up as expected -- which they wouldn't if the table model wasn't in use.
The "good" news: When I change the most relevant line of all:
monthlyTable.setDefaultRenderer(Double.class, renderer);
to
monthlyTable.setDefaultRenderer(Object.class, renderer);
..then it works, or rather -- the getTableCellRendererComponent does get called, and the text color of each cell is red (which isn't exactly what I wanted, but closer), and I see my "Check" message. What am I doing wrong?
Thankful for any pointers.
Oh, and to those whome it may concern: Happy new year!
-- Kind regards, Jan Danielsson
Igor Buzatovic - 31 Dec 2004 10:40 GMT instead of giving us only some parts of the code please provide whole code, it will be lot easyer to help.
> Hello all, > [quoted text clipped - 51 lines] > Kind regards, > Jan Danielsson Dag Sunde - 31 Dec 2004 11:18 GMT > Hello all, > > I know: "This has been answered a thousand times before, search Google > Groups". <snipped>
> The "good" news: When I change the most relevant line of all: > [quoted text clipped - 7 lines] > called, and the text color of each cell is red (which isn't exactly what > I wanted, but closer), and I see my "Check" message. What am I doing wrong? And what does that tell you? You tell your table to use a red-painting renderer on data of the type Double, and it doesn't. You tell it to use the red-painting renderer on data of the type Object (any), and, viola! it paints red...
Are you not a little bit suspicious that the data in that particular column of your datamodel is after all, *not* Double.class, but maybe a String, containing a text-representation of a double number?
Check your DM, and its setValueAt, and most important; getValueAt(...) and take a look at what that method return (type) for the column in question
 Signature Dag.
Jan Danielsson - 31 Dec 2004 13:33 GMT >>I know: "This has been answered a thousand times before, search Google >>Groups". [quoted text clipped - 16 lines] > > And what does that tell you? I'm guessing; a lot.
> You tell your table to use a red-painting renderer on data of the type > Double, > and it doesn't. > You tell it to use the red-painting renderer on data of the type Object > (any), > and, viola! it paints red... That is correct.
> Are you not a little bit suspicious that the data in that particular column > of your datamodel is after all, *not* Double.class, but maybe a String, > containing a text-representation of a double number? I'm *very* suspicious, which is why I tried to change Double.class to Integer.class, and String.class (my table contains all three types). None would work. Only Object.class works. I'm assuming that there's something very basic that I'm missing. (I've just started programming Java, so I know .. well .. almost nothing about it).
> Check your DM, and its setValueAt, and most important; getValueAt(...) > and take a look at what that method return (type) for the column in question I don't use setValueAt(). Do I need to? Could that be the problem?
FWIW, I included the code (I already know that the cell-code is suboptimal, but it's just test code):
-------------------------------------------- class TransListCellRenderer extends DefaultTableCellRenderer { private Color c1 = new Color(255, 255, 255); private Color c2 = new Color(250, 230, 250); public Component getTableCellRendererComponent (JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component cell = super.getTableCellRendererComponent (table, value, isSelected, hasFocus, row, column); System.out.println("Check!"); if(!isSelected) { if((row % 2) == 0) cell.setBackground(c1); else cell.setBackground(c2); }
cell.setForeground(Color.black); if(value instanceof Double ) { Double amount = (Double)value; if(amount.doubleValue() < 0.0) { cell.setForeground(Color.red); } }
// test code: illustrates the problem. cell.setForeground(Color.red);
return cell; } }
class TransListNode { private int id; private String category; private java.util.Date date; private double amount; private String description;
public TransListNode(Connection con, int id) throws java.sql.SQLException { String Q = "SELECT T.ID,C.TITLE,T.DATE,T.AMOUNT,T.DESCRIPTION FROM " + "TRANSACTIONS AS T, CATEGORIES AS C WHERE T.CATEGORY_ID=C.ID AND " + "T.ID=" + id;
System.out.println(Q); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(Q); System.out.println(rs);
if(rs.next()) { id = rs.getInt(1); category = rs.getString(2); date = rs.getDate(3); amount = rs.getDouble(4);
Clob clob = rs.getClob(5); if(rs.wasNull()) description = "<null>"; else { int len = (int)clob.length(); if(len > 64) description = clob.getSubString(1, 64) + "..."; else description = clob.getSubString(1, len); } }
// Clean up.. rs.close(); stmt.close(); }
public int getId() { return id; } public String getCategory() { return category; } public java.util.Date getDate() { return date; } public String getDescription() { return description; } public double getAmount() { return amount; }
public String toString() { return "" + id + "," + category + "," + date + "," + amount + "," + description; } }
class TransListTableModel extends AbstractTableModel { private String[] columnNames = { "Id", "Category", "Date", "Amount", "Description" }; private Vector<TransListNode> rowList;
public TransListTableModel() { rowList = new Vector<TransListNode>(); }
public void addRow(TransListNode tln) {
// Add to database!! try { rowList.add(tln); } catch(Exception e) { JdbcException jdbcExc = new JdbcException(e); jdbcExc.handle(); } }
public int getColumnCount() { return columnNames.length; } public int getRowCount() { return rowList.size(); } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { TransListNode tln = (TransListNode)rowList.get(row); switch(col) { case 0: return tln.getId(); case 1: return tln.getCategory(); case 2: return tln.getDate(); case 3: return tln.getAmount(); case 4: return tln.getDescription(); } return null; } public Class getColumClass(int col) { System.out.println("Returning: " + getValueAt(0, col).getClass()); return getValueAt(0, col).getClass(); } } --------------------------------------------
I'm assuming that since this doesn't work, I'm using getColumnClass() and getValueAt() all wrong.
..or I'm simply missing something else.
As I said, I'm a Java newbie, please keep it simple if possible.
PS. For future reference; how much code is accepted per post here without people throwing a fit?
-- Kind Regards, Jan Danielsson
Andrew McDonagh - 31 Dec 2004 11:33 GMT snipped...
Can you post your code, then we will be able to show you where the problem is and then talk about why the problem exists. At this point you posting is a little too vague (for me at least) to answer.
However, the basic means of getting the renderer to be called is when either the table model's contents have changed or a repaint is required.
Dag's response about the renderer working when you set the renderer for the Object data type is a good starting point.
Andrew
Christian Kaufhold - 31 Dec 2004 19:19 GMT > At this point, I expect to get the most common answer: "You need to > implement getColumClass() in your table model". [quoted text clipped - 6 lines] > } > ------- The method to override is called "getColumnClass".
Your implementation is wrong in some places: 1. It will fail with an exception if the TableModel happens to have zero rows at one time. 2. It will give wrong results if the class of the element in the first row is not the same or a superclass of the elements in the other rows, e.g. if the first row contains a String, but the other rows don't all also contain Strings, but other objects.
Christian
Jan Danielsson - 31 Dec 2004 22:56 GMT >>At this point, I expect to get the most common answer: "You need to >>implement getColumClass() in your table model". [quoted text clipped - 8 lines] > > The method to override is called "getColumnClass". Wadd'ya know! :-) Thanks!
Makes me wonder: I wonder if those other having the same problem as I had copied code from the same webpage as I did?
> Your implementation is wrong in some places: > 1. It will fail with an exception if the TableModel happens to have > zero rows at one time. How come? When does getColumnClass() get called, other than when there are rows?
> 2. It will give wrong results if the class of the element in the > first row is not the same or a superclass of the elements in the > other rows, e.g. if the first row contains a String, but the other > rows don't all also contain Strings, but other objects. This limitation I am aware of, but since the colums are directly mapped to columns in an SQL database, that doesn't matter.
Thanks for spotting that typo..
Christian Kaufhold - 04 Jan 2005 14:37 GMT >> Your implementation is wrong in some places: >> 1. It will fail with an exception if the TableModel happens to have >> zero rows at one time. > > How come? When does getColumnClass() get called, other than when there > are rows? By default, probably never. But nowhere is it stated that the class of column is not undefined just because there are no rows.
Christian
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|