Removing added custom cell renderer - java

I have created a custom cell renderer to fill a cell by a particular color.
public class ColorInCellRenderer extends DefaultTableCellRenderer
{
private final Map<Point, Color> cellColors = new HashMap<Point, Color>();
public void setCellColor(int row, int column, Color color)
{
if (color == null)
{
cellColors.remove(new Point(row, column));
}
else
{
cellColors.put(new Point(row, column), color);
}
}
private Color getCellColor(int row, int column)
{
Color color = cellColors.get(new Point(row, column));
return color;
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
Color color = getCellColor(row, column);
c.setBackground(color);
return c;
}
}
i used it in adding a row into jTable as follows.
private void addTableRow(String type, String name, String rank, String notes, String location, Color color)
{
tableModel.addRow(new Object[]
{
type,
name,
rank,
notes,
location
});
colorInCellRenderer.setCellColor(tableModel.getRowCount() - 1, INDEX_OF_THE_COLOR_COLUMN, color);
JTable.repaint();
}
It works properly and fill the cell correctly. But when I remove the row it does not remove the filled color cell. Instead of it the color column replaces with the color cell in the next row. I tried by repainting the jTable after removing a row. But it does not work.

But when I remove the row it does not remove the filled color cell.
Because you store the cells to be painted in your "cellColors" Map.
When you remove a row from the table you also need to remove the Point from the Map.
You can add a TableModelListener to the TableModel. You will be notified when a row is removed and then you can also remove the Point from the Map.

Related

JTable ImageIcon and String

I want to create a JTable where in the cells there could be an ImageIcon, String or both. I've already tried solutions like table.setvalue() or just adding the Icon to the Object Array for creating the JTable.
for (int n = 0; n < tableHeight; n++) {
for (int m = 0; m < tableWidth; m++) {
if ((n + m) == labelArray.size()) {
break;
}
if (labelArray.get(n + m).iconMode) { //iconMode is True if there is an icon instead of line text
data[n][m] = null;
} else {
String text = new String("<html><p>" + labelArray.get(n + m).lineOne + "<br>" + labelArray.get(n + m).lineTwo + "<p></html>");
data[n][m] = text;
}
}
}
table = new JTable(data, columnNames);
renderer = new DefaultTableCellRenderer();
renderer.setHorizontalTextPosition(JLabel.CENTER);
renderer.setHorizontalAlignment(JLabel.CENTER);
for (int n = 0; n < tableWidth; n++) {
table.getColumnModel().getColumn(n).setCellRenderer(renderer);
table.getColumnModel().getColumn(n).setWidth(50);
}
there could be an ImageIcon, String or both.
You will need to create a custom object to store in the TableModel. This object will contain two properties:
text
icon
Then you will need to create a custom renderer (not use the default renderer) to display this object.
The custom renderer might look something like:
class CustomRenderer extends DefaultTableCellRenderer
{
public CustomRenderer()
{
super();
setHorizontalTextPosition(JLabel.CENTER);
setHorizontalAlignment(JLabel.CENTER);
}
#Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
CustomObject custom = (CustomObject)value;
setText( custom.getText() );
setIcon( custom.getIcon() );
return this;
}
}

JTable Specifying column and row number on setBackground()

I recently learned that I can create a custom DefaultTableCellRenderer class for a JTable.
However, my code only colors the entire row but not the specific columns / cells I want to color based on a condition.
How can I specify the row and column in the DefaultTableCellRenderer class I created?
So here are the classes I created.
public class Schedule extends JPanel(){
public Schedule(){
schedulesJtbl.setDefaultRenderer(Object.class, new ScheduleTableCellRenderer());
int startTime = 1230, endTime = 1330;
int jtStartTime = scheduleJtbl.getValueAt(0,1);
int jtEndTime = scheduleJtbl.getValueAt(0,2);
int conflictCheck = 0;
// duplicate startTime and endTime
if((startTime == jtStartTime) && (endTime == jtEndTime)){
conflictCheck++
ScheduleTableCellRenderer.setConflict(conflictCheck);
}
//duplicate startTime
else if(startTime == jtStartTime){
conflictCheck++
ScheduleTableCellRenderer.setConflict(conflictCheck);
}
}
and here's the ScheduleTableCellRenderer
public class ScheduleTableCellRenderer extends DefaultTableCellRenderer {
static int conflict = 0;
#Override
public Component getTableCellRendererComponent(
JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int col) {
Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
if (conflict > 0) {
c.setBackground(Color.RED);
} else if (conflict == 0) {
c.setBackground(Color.GREEN);
}
return c;
}
public static void setConflict(int aConflict) {
conflict = aConflict;
}
}
If it's only startTime(as second condition on if) that duplicated, how can I color only column 2 but not the entire row just like what is happening right now on my JTable.
I hope you can help me.
Thank you.
schedulesJtbl.setDefaultRenderer(Object.class, new ScheduleTableCellRenderer());
That sets the default renderer for all Objects in any row/column.
To set the renderer for a specific column you do:
table.getColumnModel().getColumn(???).setCellRenderer( ... );
You also need to reset the default background:
if (conflict > 0) {
c.setBackground(Color.RED);
} else if (conflict == 0) {
c.setBackground(Color.GREEN);
} else {
c.setBackgrund( table.getBackground() );
}

conditional jtable background row

Hi I have a problem I have a list of Persnäs in a table, also have a list of bad people at a vector and I want to load jtable, poor people are marked in red
tabla= table
conteo= count
the problem of the code that I have is that only one match brand eventhough it has several
tabla.setDefaultRenderer(Object.class, new DefaultTableCellRenderer()
{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
try {
String sql;
String driver = "org.apache.derby.jdbc.EmbeddedDriver";
String bdd = "616c756d6e6f";
String par = "create=true";
String conexion = "jdbc:derby:" + bdd + ";" + par;
Connection con = DriverManager.getConnection(conexion);
sql="select matricula from bajas";
PreparedStatement st = con.prepareStatement(sql);
ResultSet rs= st.executeQuery();
Vector<String> vec = new Vector<String>();
while(rs.next())
{
vec.addElement(rs.getString("matricula"));
}
con.close();
for(int x=0;x<tabla.getRowCount();x++)
{
int conteo=0;
for(String valor:vec)
{
if(valor.equals(tabla.getValueAt(x, 0)))
{
conteo++;
}
}
if(conteo!=0)
{
final Component c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
c.setBackground(row ==x ? Color.RED:null);
return c;
}
}
} catch (SQLException ex) {
Logger.getLogger(InicioAlumnos.class.getName()).log(Level.SEVERE, null, ex);
}
return null;
}
Don't do anything in your renderers that could be time consuming (this is pretty good rule for GUI's generally). EACH cell that the renderer is responsible for could call this renderer (have 1000 lines, expect to be hit 1000 times). Instead, pre-load you "black" list and use the cached values. If you need to, provide a means by which the list can reloaded
Always return a value from the cell renderers, failing to do so may cause other problems.
This...
for(int x=0;x<tabla.getRowCount();x++)
{
int conteo=0;
for(String valor:vec)
{
if(valor.equals(tabla.getValueAt(x, 0)))
{
conteo++;
}
}
Doesn't make sense. A TableCellRenderer is responsible for a individual cell, not the entire table.
Assuming you only want to mark the row that matches your blacklist, you should be using...
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (vec.contains(table.getValueAt(row, 0)) {
setBackground(Color.RED);
}
return this;

Ho to fill JTable in such a way that each cell contains a `String` consisted of two lines?

Is it possible to fill JTable in such a way that each cell contains a String consisted of two lines?
String cellText = "Line 1 \n Line 2";
In my JTable I see cellText displayed as a single line.
You'll want to use a custom JTextArea renderer.
http://www.coderanch.com/t/340609/GUI/java/JTable-Custom-Cell-Renderer-JTextArea
This is one I've used over the years:
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.util.*;
public class TextAreaRenderer extends JTextArea implements TableCellRenderer {
private final DefaultTableCellRenderer adaptee = new DefaultTableCellRenderer();
/** map from table to map of rows to map of column heights */
private final Map cellSizes = new HashMap();
public TextAreaRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
}
public Component getTableCellRendererComponent(
JTable table, Object obj, boolean isSelected,
boolean hasFocus, int row, int column) {
// set the colours, etc. using the standard for that platform
adaptee.getTableCellRendererComponent(table, obj,
isSelected, hasFocus, row, column);
setForeground(adaptee.getForeground());
setBackground(adaptee.getBackground());
setBorder(adaptee.getBorder());
setFont(adaptee.getFont());
setText(adaptee.getText());
// This line was very important to get it working with JDK1.4
TableColumnModel columnModel = table.getColumnModel();
setSize(columnModel.getColumn(column).getWidth(), 100000);
int height_wanted = (int) getPreferredSize().getHeight();
addSize(table, row, column, height_wanted);
height_wanted = findTotalMaximumRowSize(table, row);
if (height_wanted != table.getRowHeight(row)) {
table.setRowHeight(row, height_wanted);
}
return this;
}
#SuppressWarnings("unchecked")
private void addSize(JTable table, int row, int column, int height) {
Map rows = (Map) cellSizes.get(table);
if (rows == null) {
cellSizes.put(table, rows = new HashMap());
}
Map rowheights = (Map) rows.get(new Integer(row));
if (rowheights == null) {
rows.put(new Integer(row), rowheights = new HashMap());
}
rowheights.put(new Integer(column), new Integer(height));
}
/**
* Look through all columns and get the renderer. If it is
* also a TextAreaRenderer, we look at the maximum height in
* its hash table for this row.
*/
private int findTotalMaximumRowSize(JTable table, int row) {
int maximum_height = 0;
Enumeration columns = table.getColumnModel().getColumns();
while (columns.hasMoreElements()) {
TableColumn tc = (TableColumn) columns.nextElement();
TableCellRenderer cellRenderer = tc.getCellRenderer();
if (cellRenderer instanceof TextAreaRenderer) {
TextAreaRenderer tar = (TextAreaRenderer) cellRenderer;
maximum_height = Math.max(maximum_height,
tar.findMaximumRowSize(table, row));
}
}
return maximum_height;
}
private int findMaximumRowSize(JTable table, int row) {
Map rows = (Map) cellSizes.get(table);
if (rows == null) {
return 0;
}
Map rowheights = (Map) rows.get(new Integer(row));
if (rowheights == null) {
return 0;
}
int maximum_height = 0;
for (Iterator it = rowheights.entrySet().iterator();
it.hasNext();) {
Map.Entry entry = (Map.Entry) it.next();
int cellHeight = ((Integer) entry.getValue()).intValue();
maximum_height = Math.max(maximum_height, cellHeight);
}
return maximum_height;
}
}
which you would call with something like this:
table.getColumn("Column").setCellRenderer(new TextAreaRenderer());
JTable Cell data follows html syntax and rules. So you can use <br> to put line separator. hope this helps.

Set a cell's background in JTable based on some other inputs

All - I'm trying to set a specific cell's background color after it is clicked AND a successful operation has occurred. I cant seem to do it. Here is the code:
JTable table = new JTable(new DefaultTableModel());
String [] colNames = {"col1", "col2", "ClickMe"};
for (String name : colNames)
table.addColumn(name);
.... some code .....
String [] someArray = {"t", "t2", "t3"};
....
for (int i=0; i<someArray.length;i++) {
Object [] row = new Object[3];
row[0] = "bla";
row[1] = "bla";
row[2] = "Update";
((DefaultTableModel)table.getModel()).addRow(row);
((DefaultTableCellRenderer)gameTable.getCellRenderer(i, 2)).setBackground(Color.LIGHT_GRAY);
((DefaultTableCellRenderer)gameTable.getCellRenderer(i, 2)).setHorizontalAlignment(JLabel.CENTER);
}
table.addMouseListener(new MouseListener() {
public void mouseClicked(MouseEvent e) {
int row = gameTable.rowAtPoint(e.getPoint());
int col = gameTable.columnAtPoint(e.getPoint());
if (col == 2) {
Color cellColor = ((DefaultTableCellRenderer)gameTable.getCellRenderer(row,col)).getBackground();
if (cellColor == Color.LIGHT_GREY) {
String val1 = (String)table.getModel().getValueAt(row,1);
String val2 = (String)table.getModel().getValueAt(row,0);
if (doSomething(val1, val2)) { //this returns either true or false, its a Database operations
((DefaultTableCellRenderer)table.getCellRenderer(row, 2)).setBackground(Color.BLUE);
}
}
}
};
Even thought i am specific calling setBackground on a row & column, it makes every cell in every row in column "2" change background color instead of just one specific one.
All the examples with customRenderers seem to just change the color based on when its clicked just change it to something else, i need to do some processing as well.
any thoughts here?
Thanks-
Try this
table.setDefaultRenderer(Object.class, new TableCellRenderer(){
private DefaultTableCellRenderer DEFAULT_RENDERER = new DefaultTableCellRenderer();
private Component comp;
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = DEFAULT_RENDERER.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if(isSelected){
c.setBackground(Color.YELLOW);
}else{
if (row%2 == 0){
if (column==2){
c.setBackground(Color.WHITE);
}
else {
c.setBackground(Color.LIGHT_GRAY);
} } }
return c;
}
});

Categories