Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > Changing the Background Color for One Cell in a JTable

Reply
Thread Tools

Changing the Background Color for One Cell in a JTable

 
 
Hal Vaughan
Guest
Posts: n/a
 
      01-19-2008
I've been working on this for a few hours. I've read tutorials and seen
different examples, but this is still driving me nuts.

I have a table and want to be able to change the color of one cell in it.
It seems to do this, I can't get a cell renderer and just change the color,
I have to create my own class to do that. I've tried that and a number of
other things and can't get it to work.

I finally took the SimpleTableDemo from Sun and checked to make sure it was
running. Once it was, I added four lines:

boolean isSelected = table.isCellSelected(1, 1);
DefaultTableCellRenderer defRender = (DefaultTableCellRenderer)
table.getCellRenderer(1, 1);
Component cellRenderer = defRender.getTableCellRendererComponent(table,
"Huml", isSelected, false, 1, 1);
cellRenderer.setBackground(Color.blue);

(The whole example is at the bottom of this post.)

When I use this example, it turns ALL the cells in the table blue, not just
the one at 1,1.

I've got several questions about this:
1) Do I have to create my own cell renderer to change a cell background
color, or can't I just do it like above? Even when I used my own renderer,
I still got the actual Component named cellRenderer using the same
parameters, so what difference would doing it in a separate class make?
2) The renderer needs the value that is in the cell currently. In my own
program, I got that from the DefaultTableModel I was using. Here I just
used the text that was put in that cell. Is there any way to get the cell
value directly from the table? In this example, I tried getting a
DefaultTableModel (by casting) from the table, but it didn't work, so I
couldn't get the data by reading the cell.
3) Why does this code (above) set the entire table and not just the cell at
1,1?

If anyone has a simpler example of how to set the background color in just a
few lines, I'd be glad to see it. I can't believe how much I need to do
just to change the background color in one table cell!

Thanks for any help/insight!

Hal

----------------example code----------------

/*
* SimpleTableDemo.java requires no other files.
*/

import java.awt.Color;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

import com.hal.gui.HalCellRenderer;

public class SimpleTableDemo extends JPanel {
private boolean DEBUG = false;

public SimpleTableDemo() {
super(new GridLayout(1,0));

String[] columnNames = {"First Name",
"Last Name",
"Sport",
"# of Years",
"Vegetarian"};

Object[][] data = {
{"Mary", "Campione",
"Snowboarding", new Integer(5), new Boolean(false)},
{"Alison", "Huml",
"Rowing", new Integer(3), new Boolean(true)},
{"Kathy", "Walrath",
"Knitting", new Integer(2), new Boolean(false)},
{"Sharon", "Zakhour",
"Speed reading", new Integer(20), new Boolean(true)},
{"Philip", "Milne",
"Pool", new Integer(10), new Boolean(false)}
};

final JTable table = new JTable(data, columnNames);
table.setPreferredScrollableViewportSize(new Dimension(500, 70));
// table.setFillsViewportHeight(true);

if (DEBUG) {
table.addMouseListener(new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
printDebugData(table);
}
});
}

//Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);

//Add the scroll pane to this panel.
add(scrollPane);

//================================================== ====
//Only part I have added is the next four lines
//================================================== ====
boolean isSelected = table.isCellSelected(1, 1);
DefaultTableCellRenderer defRender = (DefaultTableCellRenderer)
table.getCellRenderer(1, 1);
Component cellRenderer =
defRender.getTableCellRendererComponent(table, "Huml", isSelected, false,
1, 1);
cellRenderer.setBackground(Color.blue);
}

private void printDebugData(JTable table) {
int numRows = table.getRowCount();
int numCols = table.getColumnCount();
javax.swing.table.TableModel model = table.getModel();

System.out.println("Value of data: ");
for (int i=0; i < numRows; i++) {
System.out.print(" row " + i + ":");
for (int j=0; j < numCols; j++) {
System.out.print(" " + model.getValueAt(i, j));
}
System.out.println();
}
System.out.println("--------------------------");
}

/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("SimpleTableDemo");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOS E);

//Create and set up the content pane.
SimpleTableDemo newContentPane = new SimpleTableDemo();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane);

//Display the window.
frame.pack();
frame.setVisible(true);
}

public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

 
Reply With Quote
 
 
 
 
Hal Vaughan
Guest
Posts: n/a
 
      01-20-2008
Hal Vaughan wrote:

> I've been working on this for a few hours. I've read tutorials and seen
> different examples, but this is still driving me nuts.
>
> I have a table and want to be able to change the color of one cell in it.
> It seems to do this, I can't get a cell renderer and just change the
> color,
> I have to create my own class to do that. I've tried that and a number of
> other things and can't get it to work.
>
> I finally took the SimpleTableDemo from Sun and checked to make sure it
> was
> running. Once it was, I added four lines:
>
> boolean isSelected = table.isCellSelected(1, 1);
> DefaultTableCellRenderer defRender = (DefaultTableCellRenderer)
> table.getCellRenderer(1, 1);
> Component cellRenderer =
> defRender.getTableCellRendererComponent(table,
> "Huml", isSelected, false, 1, 1);
> cellRenderer.setBackground(Color.blue);
>
> (The whole example is at the bottom of this post.)
>
> When I use this example, it turns ALL the cells in the table blue, not
> just the one at 1,1.
>
> I've got several questions about this:
> 1) Do I have to create my own cell renderer to change a cell background
> color, or can't I just do it like above? Even when I used my own renderer,
> I still got the actual Component named cellRenderer using the same
> parameters, so what difference would doing it in a separate class make?
> 2) The renderer needs the value that is in the cell currently. In my own
> program, I got that from the DefaultTableModel I was using. Here I just
> used the text that was put in that cell. Is there any way to get the cell
> value directly from the table? In this example, I tried getting a
> DefaultTableModel (by casting) from the table, but it didn't work, so I
> couldn't get the data by reading the cell.
> 3) Why does this code (above) set the entire table and not just the cell
> at 1,1?


Answering my own questions:

Yes, it's necessary to create a special table cell rendering class to do
this. To change the color of any cells, you've got to create your own
renderer, then use JTable.setDefaultRenderer(Class columnClass,
TableCellRenderer renderer). What confuses me is that this takes two
arguments, the first works for me if I just use Object.class. If someone
can clue me in with what the heck goes on with that, I'd appreciate it.
The 2nd must be your special renderer. Then WITHIN your render, you have
the method getTableCellRendererComponent() with 5 arguments I won't list.
You'll never call this, but JTable does when rendering. Within your class,
in that method, put the code that will determine the conditions under which
a cell should be rendered a certain way.

In my case, I wanted cells to be rendered in certain colors if their row
number was one of the members of a LinkedList. I had to include routines
in my renderer to add row numbers to that list and I also had to check, in
getTableCellRendererComponent() to see if a row number was a member of that
list. If it was, then I specified my special background color.

It's not necessary to supply the renderer with any info about the cell
that's being rendered because the JTable will do that.

The hard part for me to understand was that I was trying to set just one or
a few cells to a different background color and, like I've found so often
in Java, you can't get there from here. To change one cell's color, you
have to write a renderer and add it to the table as a renderer and have the
code in that renderer, more specifically in the method
getTableCellRendererComponent() in that renderer, check for the cell you
want and use the special color. It's just a personal gripe, but it's
another case where, in order to do one thing in Java, I have to do an
additional 5 other things to get to the point where I can do it.

I've answered this to help others searching for this kind of info in the
future. If anyone has corrections, I hope they add them, since, as I often
point out, I'm self taught, and I often miss things that many people just
take for granted in Java.

Hal
 
Reply With Quote
 
 
 
 
Roedy Green
Guest
Posts: n/a
 
      01-20-2008
I would write a OneCellRenderer that looked something like this:

package com.mindprod.vercheck;

import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableCellRenderer;
import java.awt.*;

/**
* render JTable String column, in a selected font, colours and
alignment. Engage with: columnModel.getColumn( col
* ).setCellRenderer( new RainbowRenderer( font, foreground,
background, JLabel.CENTER ) )
*/
final class RainbowRenderer extends DefaultTableCellRenderer
implements TableCellRenderer
{
private final Color foreground;

private final Font font;

private final int horizontalAlignment;

// -------------------------- PUBLIC INSTANCE METHODS
--------------------------
/**
* constructor
*
* @param font for to render the column
* @param foreground foreground colour
* @param horizontalAlignment e.g. JLabel.CENTER
*/
public RainbowRenderer( Font font,
Color foreground,
int horizontalAlignment )
{
this.foreground = foreground;
this.font = font;
this.horizontalAlignment = horizontalAlignment;
}

public Component getTableCellRendererComponent( JTable table,
Object value,
boolean
isSelected,
boolean hasFocus,
int row,
int column )
{
JLabel template = (JLabel)
super.getTableCellRendererComponent( table, value,
isSelected, hasFocus, row, column );
if ( ???? the special cell )
{
template.setFont( specialFont );
template.setForeground( specialForeground );
}
else
{
template.setFont( font );
template.setForeground( foreground );
}
// we don't handle setting selected background here.
// We don't get called when selection changes.
// leave it up to JTable to set the background to selected or
normal.
template.setHorizontalAlignment( horizontalAlignment );
if ( value != null )
{
template.setText( value.toString() );
}
else
{
template.setText( null );
}
return template;
}
--
Roedy Green, Canadian Mind Products
The Java Glossary, http://mindprod.com
 
Reply With Quote
 
Filip Larsen
Guest
Posts: n/a
 
      01-20-2008
Hal Vaughan skrev:

> Answering my own questions:
>
> Yes, it's necessary to create a special table cell rendering class to do
> this. To change the color of any cells, you've got to create your own
> renderer, then use JTable.setDefaultRenderer(Class columnClass,
> TableCellRenderer renderer). What confuses me is that this takes two
> arguments, the first works for me if I just use Object.class. If someone
> can clue me in with what the heck goes on with that, I'd appreciate it.


You set default renderers with JTable.setDefaultRenderer and column
renderes with TableColumn.setCellRenderer, where the table column for
instance can be found using JTable.getColumnModel().getColumn(columnIndex).

If you want to understand how JTable decides which cell renderer to use,
look in JTable.getCellRendrer (snippet below from Java 1.4 source):

public TableCellRenderer getCellRenderer(int row, int column) {
TableColumn tableColumn = getColumnModel().getColumn(column);
TableCellRenderer renderer = tableColumn.getCellRenderer();
if (renderer == null) {
renderer = getDefaultRenderer(getColumnClass(column));
}
return renderer;
}

If your table model implement the TableModel.getColumnClass method to
return the special class you have for relevant column, you can register
your special renderer as a default renderer for that class. Note that if
you use DefaultTableModel it will just return Object.class for all
columns, which again means that only the default renderer registered for
Object.class will ever be used by the table. So, for default renderers
to be found the table model must return the right class.

Alternatively you can register your renderer with the table column. This
can for instance be useful if you have two columns with same class you
want to render with different renderers or if you dont want to "polute"
your table model with knowledge of column classes.

As to the definition of the renderer itself there are several ways to do
it depending on what you want. A fairly simple solution is to make a
wrapper renderer that delegates as much as possible, like

final TableCellRenderer r = table.getDefaultRenderer(String.class);
table.setDefaultRenderer(Special.class, new TableCellRenderer() {
public Component getTableCellRendererComponent(...) {
Color bg = figureOutBackgroundColor(value);
Component c = r.getTableCellRendererComponent(...);
c.setBackground(bg);
return c;
}
});

This assumes that your Special class uses toString() to construct the
textual value for the cell. If you want to use another method, say,
Special.getBalance() which for instance returns a Float, you can do

final TableCellRenderer r = table.getDefaultRenderer(Float.class);
table.setDefaultRenderer(Special.class, new TableCellRenderer() {
public Component getTableCellRendererComponent(...) {
Color bg = figureOutBackgroundColor(value);
value = ((Special)value).getBalance();
Component c = r.getTableCellRendererComponent(...);
c.setBackground(bg);
return c;
}
});


If you want to make sure your cell renderering appears as a standard
string renderer with just the changed background, you can extend from
DefaultTableCellRenderer instead of using delegation:

table.setDefaultRenderer(Special.class, new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(...) {
Component c = super.getTableCellRendererComponent(...);
c.setBackground(figureOutBackgroundColor(value));
return c;
}
});



Regards,
--
Filip Larsen
 
Reply With Quote
 
Hal Vaughan
Guest
Posts: n/a
 
      01-20-2008
Thanks for a lot of good info!

Hal

Filip Larsen wrote:

> Hal Vaughan skrev:
>
>> Answering my own questions:
>>
>> Yes, it's necessary to create a special table cell rendering class to do
>> this. To change the color of any cells, you've got to create your own
>> renderer, then use JTable.setDefaultRenderer(Class columnClass,
>> TableCellRenderer renderer). What confuses me is that this takes two
>> arguments, the first works for me if I just use Object.class. If someone
>> can clue me in with what the heck goes on with that, I'd appreciate it.

>
> You set default renderers with JTable.setDefaultRenderer and column
> renderes with TableColumn.setCellRenderer, where the table column for
> instance can be found using
> JTable.getColumnModel().getColumn(columnIndex).
>
> If you want to understand how JTable decides which cell renderer to use,
> look in JTable.getCellRendrer (snippet below from Java 1.4 source):
>
> public TableCellRenderer getCellRenderer(int row, int column) {
> TableColumn tableColumn = getColumnModel().getColumn(column);
> TableCellRenderer renderer = tableColumn.getCellRenderer();
> if (renderer == null) {
> renderer = getDefaultRenderer(getColumnClass(column));
> }
> return renderer;
> }
>
> If your table model implement the TableModel.getColumnClass method to
> return the special class you have for relevant column, you can register
> your special renderer as a default renderer for that class. Note that if
> you use DefaultTableModel it will just return Object.class for all
> columns, which again means that only the default renderer registered for
> Object.class will ever be used by the table. So, for default renderers
> to be found the table model must return the right class.
>
> Alternatively you can register your renderer with the table column. This
> can for instance be useful if you have two columns with same class you
> want to render with different renderers or if you dont want to "polute"
> your table model with knowledge of column classes.
>
> As to the definition of the renderer itself there are several ways to do
> it depending on what you want. A fairly simple solution is to make a
> wrapper renderer that delegates as much as possible, like
>
> final TableCellRenderer r = table.getDefaultRenderer(String.class);
> table.setDefaultRenderer(Special.class, new TableCellRenderer() {
> public Component getTableCellRendererComponent(...) {
> Color bg = figureOutBackgroundColor(value);
> Component c = r.getTableCellRendererComponent(...);
> c.setBackground(bg);
> return c;
> }
> });
>
> This assumes that your Special class uses toString() to construct the
> textual value for the cell. If you want to use another method, say,
> Special.getBalance() which for instance returns a Float, you can do
>
> final TableCellRenderer r = table.getDefaultRenderer(Float.class);
> table.setDefaultRenderer(Special.class, new TableCellRenderer() {
> public Component getTableCellRendererComponent(...) {
> Color bg = figureOutBackgroundColor(value);
> value = ((Special)value).getBalance();
> Component c = r.getTableCellRendererComponent(...);
> c.setBackground(bg);
> return c;
> }
> });
>
>
> If you want to make sure your cell renderering appears as a standard
> string renderer with just the changed background, you can extend from
> DefaultTableCellRenderer instead of using delegation:
>
> table.setDefaultRenderer(Special.class, new DefaultTableCellRenderer() {
> public Component getTableCellRendererComponent(...) {
> Component c = super.getTableCellRendererComponent(...);
> c.setBackground(figureOutBackgroundColor(value));
> return c;
> }
> });
>
>
>
> Regards,


 
Reply With Quote
 
Tod Tod is offline
Junior Member
Join Date: Oct 2008
Posts: 1
 
      10-28-2008
I am tryingto change the background color on a boolean column (aka checkbox) in a JTable. I can do this successfully with a String column, but not for the boolean column. Any advice? Here is how I do it for a String column:

class NamedColor extends Color {
String name;
public NamedColor(Color color, String name) {
super(color.getRGB());
this.name = name;
}

public String toString() {
return name;
}
}

<elsewhere in the code>
DefaultTableCellRenderer colorRenderer =
new DefaultTableCellRenderer() {
public void setValue(Object value) {
if (value instanceof NamedColor) {
NamedColor c = (NamedColor)value;
setBackground(c);
// setForeground(c.getTextColor());
setText(c.toString());
// this.setToolTipText();
} else
{
super.setValue(value);
}
}
};

pKgList.getColumnModel().getColumn(1).setCellRende rer(colorRenderer);

<elsewhere in code>
Vector vct = new Vector(7);
vct.add(Boolean.FALSE);
String cnt2char;
cnt2char = pkg.substring(0,2).toUpperCase();
NamedColor nm3 = new NamedColor(Color.WHITE, "String Text");
vct.add(nm3);
<Vector vct is then added to JTable>

<elsewhere in code, I want to make a change to the background>
c1 = new NamedColor(new Color(165, 231, 255), this.pkg.pKgdefmodel.getValueAt(loop,1).toString() ); /*Blue*/
this.pkg.pKgdefmodel.setValueAt(c1, loop, 1);
<JTable cell now has a Blue color>

So how can I change this to support a boolean column? I tried making a BooleanColor Class, but I don't know how to handle the boolean value. Name tracked String value in NamedColor, but what tracks the boolean value?
 

Last edited by Tod; 10-28-2008 at 06:59 PM..
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Changing font color from current font color to black color Kamaljeet Saini Ruby 0 02-13-2009 04:58 PM
[xlwt] Changing Cell Background Color Chanman Python 0 06-19-2008 07:46 PM
Putting a JTable inside a JTable cell? Tivo Escobar Java 1 04-12-2007 11:09 AM
changing background color of a cell effendi@epitome.com.sg Javascript 1 03-27-2005 04:36 PM
Q: Automatically Changing Background Color of a Table Cell? Arthur Shapiro Javascript 29 01-02-2005 12:15 AM



Advertisments