add image to specific table cell

Hi I'm drawing a schedule and I want certain cells to be shaded and the only way I can think of this is to load an image that looks like |/////////| (shaded.gif) and load that into each cell that I want based on start/end times.

I use preparedRenderer() to draw different background colors based on information loaded in each cell but I haven't the slightest clue on how I can add the images to certain cells. I've looked thru tutorials of Java but they all seem to use CellRenderers for a particular type. Is this possible using preparedRenderer? Do I load an imageicon when populating table or load image during preparedRendere?

public Component prepareRenderer (TableCellRenderer renderer, int row, int col)

{

Component c = super.prepareRenderer (renderer, row, col);

SingleScheduleTableModel tableModel = (SingleScheduleTableModel)this.getModel ();

int slotSize = -1;

if (!tableModel.getColumnName (col).equalsIgnoreCase ("Time"))

{

Object item = tableModel.getValueAt (row, col);

if (item instanceof Appointment)

{

//draw and setbackground

c.setBackGround(...);

}

else if(item instanceof ImageIcon) //? I don't know if this is even right

</code>

[1262 byte] By [hurrica] at [2007-11-27 10:27:06]
# 1

The best approach is to use a custom CellRenderer. This saves you alot of trouble when trying to modify your code and it also makes it possible for you to reuse code when possible.

In your case since you are using the prepareRenderer, you can still do some hacking. All you need to do is cast your Component to a JComponent (or more specifically JLabel) and use setIcon

Copy and tweak ...

Object item = tableModel.getValueAt (row, col);

if (item instanceof Appointment) {

//draw and setbackground

c.setBackGround(...);

} else if(item instanceof ImageIcon) {

If(c instanceof JLabel) {

((JLabel)c).setIcon( (ImageIcon)item );

}

}

ICE

icewalker2ga at 2007-7-28 17:43:29 > top of Java-index,Desktop,Core GUI APIs...
# 2

Thanks for the response ICE

Next question is where should I draw this image: Should I actually put an image icon in the table or should i use a flag in the cell and based on that draw an image in the prepareRenderer

it seems like the image "spills over" to other cells meaning all cells have the image now for now but I'll figure it out. At least I can display the image!

Thanks again

null

hurrica at 2007-7-28 17:43:29 > top of Java-index,Desktop,Core GUI APIs...
# 3

> it seems like the image "spills over" to other cells meaning all cells have the image now for now but I'll figure it out. At least I can display the image!

You really need to read some tutorials: http://java.sun.com/docs/books/tutorial/uiswing/components/table.html#renderer

Below is the correction for the code. The same label is just used as a rubber stamp for all the cells, so once you set the icon you, it will be used for all the cells, so you have to 'unset' for the places you dont need it.

Object item = tableModel.getValueAt (row, col);

if(c instanceof JLabel) {

((JLabel)c).setIcon(null); // here is the correction

}

if (item instanceof Appointment) {

//draw and setbackground

c.setBackGround(...);

} else if(item instanceof ImageIcon) {

If(c instanceof JLabel) {

((JLabel)c).setIcon( (ImageIcon)item );

}

}

Do a little tweaking on your own, it should make things clearer

ICE

icewalker2ga at 2007-7-28 17:43:29 > top of Java-index,Desktop,Core GUI APIs...
# 4

I can't tell from your description how your TableModel works. I see you have an Appointment class. Is an Appointment stored in every cell?, or is the Appointment designed to span several cells in a row?

The following assumes you have an appointment in every cell, in which case you should be creating a custom renderer for the Appointment instead of overriding the prepareRenderer method (as was suggested above).

> but I haven't the slightest clue on how I can add the images to certain cells.

Your data should be stored in the TableModel, then you use an appropriate renderer to render each cell. JTable already has a default renderer for ImageIcon all you need to do is tell the table which cell contains the icon. Normally this is done at the column level by overriding the getColumnClass() method.

However, in your case I'm guessing that a cell could contain an Appointment or an ImageIcon. In this case you can't override at a column level, you need to override at a cell level. So you do this by overriding the getCellRenderer() method. Something like:

public TableCellRenderer getCellRenderer(int row, int column)

{

Object cellValue = getValueAt(row, column);

if (cellvalue == null)

return super.getCellRenderer(row, column);

else

return getDefaultRenderer(cellValue.class);

}

This code assumes that you have created an "AppointmentRenderer" to render each appointment. In order to pick up the correct renderer for your Appointments you would need to add the renderer to the table. You do this by using:

table.setDefaultRenderer(Appointment.class, new AppointmentRenderer);

camickra at 2007-7-28 17:43:29 > top of Java-index,Desktop,Core GUI APIs...
# 5

Thanks ICE, camickr

You both made a lot of things clearer (I had read tutorial but never got the inkstamp idea before)

I should've instead created a customCellRender but I went with the path of prepareRenderer and I'm storing appointments in a cell and each appointment is a different color based on type of appointment and in addition I store trailing colors depending on long the appointment is in the following cells.

When I draw the table I have a populateTable() method that enters appointments in different slots of the table using the object "AppointmentItemList" which stores name of patient, color of appointment, type of appointment (list of AppointmentItem objects)

/**

* Prepare render for table cell

*/

public Component prepareRenderer (TableCellRenderer renderer, int row, int col)

{

Component c = super.prepareRenderer (renderer, row, col);

SingleScheduleTableModel tableModel = (SingleScheduleTableModel)this.getModel ();

int slotSize = -1;

if (!tableModel.getColumnName (col).equalsIgnoreCase ("Time"))

{

Object item = tableModel.getValueAt (row, col);

if (item != null)

{

if (item instanceof AppointmentItemList)

{

AppointmentItemList appointmentItemList = (AppointmentItemList)item;

if (appointmentItemList.getAppointmentCount () == 1)

{

AppointmentItem appointmentItem = (AppointmentItem)appointmentItemList.getAppointment (0);

if(appointmentItem.task.displayColor != null)

{

Color color = GuiHelper.convertColor (appointmentItem.task.displayColor);

if (color != null)

{

c.setBackground (color);

((JComponent)c).setBorder (BorderFactory.createRaisedBevelBorder());

((JLabel)c).setIcon(null);

}

}

}

else if (item instanceof SkeletonColorItem)

{

SkeletonColorItem sci = (SkeletonColorItem)item;

c.setBackground (sci.color);

((JLabel)c).setIcon(null);

if(sci.isAppointment)//raise it if it's a continuation from an appointment

((JComponent)c).setBorder (BorderFactory.createRaisedBevelBorder());

}

else if (item instanceof SkeletonColorItemList)

{

SkeletonColorItemList sciList = (SkeletonColorItemList)item;

if(sciList.getColorItemCount() == 1)

{

SkeletonColorItem sci = (SkeletonColorItem)sciList.getColorItem(0);

c.setBackground (sci.color);

((JLabel)c).setIcon(null);

if(sci.isAppointment)//raise it if it's a continuation from an appointment

((JComponent)c).setBorder (BorderFactory.createRaisedBevelBorder());

}

else if(sciList.getColorItemCount() >= 2)

{

SkeletonColorItem colorItem = findLongestSkeletonColorItem(sciList);

Color color = GuiHelper.convertColor (colorItem.colorString);

((JComponent)c).setBorder (new BevelBorder(BevelBorder.RAISED, color, color));

((JLabel)c).setIcon(null);

int timeLength = colorItem.length;

colorItem = findShortestSkeletonColorItem(sciList);

color = GuiHelper.convertColor (colorItem.colorString);

c.setBackground (color);

}

}

else if(item instanceof JLabel)

{

((JLabel)c).setIcon(null);

}

else if(item instanceof ImageIcon)

{

System.out.println(" found an image ico)");

if(c instanceof JLabel) {

((JLabel)c).setIcon((ImageIcon)item);

((JLabel)c).setText("");

((JLabel)c).setHorizontalAlignment(SwingConstants.CENTER);

((JComponent)c).setBackground(Color.WHITE);

}

else

{ c.setBackground (Color.WHITE);

((JLabel)c).setIcon(null);

}

}

else

{

c.setBackground (Color.WHITE);

((JLabel)c).setIcon(null);

}

}

else

{c.setBackground (Color.WHITE);

((JLabel)c).setIcon(null);

}

}

else

{c.setBackground (Color.WHITE);

((JLabel)c).setIcon(null);

}

return c;

}

}

I think I need to abandon the prepareRenderer and create my own CustomeCellRender

.

hurrica at 2007-7-28 17:43:29 > top of Java-index,Desktop,Core GUI APIs...
# 6

> based on type of appointment and in addition I store trailing colors

So I would see that you need at least two custom renderers.

You need a renderer to render an Appointment. Then I would simple store Color objects in the trailing cells, so you would need a custom renderer to simply use the Color object as the background color of the cell.

You processing code would then need to know whenever an appointment is added, changed or removed, so that you could update the apppriate trailing cells with your desired Color.

camickra at 2007-7-28 17:43:29 > top of Java-index,Desktop,Core GUI APIs...