I want to add hairline cross highlighting to a JXTable
. But I can either highlight the current row or the current column; never both.
What I currently have is the red part, the yellow part is what I want to add.
Below a SSCCE1.
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.util.ArrayList;
import java.util.List;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import org.jdesktop.swingx.JXTable;
public class Application
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame();
JXTable table = new JXTable(new CustomTableModel());
boolean highlightRow = false;
table.setRowSelectionAllowed(highlightRow);
table.setColumnSelectionAllowed(!highlightRow);
table.setDefaultRenderer(Object.class, new CustomTableCellRenderer());
frame.add(new JScrollPane(table));
frame.setVisible(true);
frame.pack();
}
});
}
public static class CustomTableCellRenderer extends DefaultTableCellRenderer
{
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
Component component = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (row == table.getSelectedRow()) { component.setBackground(Color.YELLOW); }
if (column == table.getSelectedColumn()) { component.setBackground(Color.RED); }
return component;
}
}
static class CustomTableModel extends AbstractTableModel
{
private final List<Object[]> data = new ArrayList<>();
public CustomTableModel()
{
data.add(new Object[] {1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10});
data.add(new Object[] {1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10});
data.add(new Object[] {1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10});
data.add(new Object[] {1, 2, 3, "A", "Collection", "of", "Random", "Strings", 9, 10});
}
@Override
public int getRowCount() { return data.size(); }
@Override
public int getColumnCount() { return 10; }
@Override
public Object getValueAt(int rowIndex, int columnIndex) { return data.get(rowIndex)[columnIndex]; }
}
}
Update
Using the code and suggestions provided by @camickr yields this:
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;
import org.jdesktop.swingx.JXTable;
public class Application
{
public static void main(String[] args)
{
EventQueue.invokeLater(new Runnable()
{
@Override
public void run()
{
JFrame frame = new JFrame();
DefaultTableModel model = new DefaultTableModel(5, 10);
JXTable table = new JXTable(model)
{
@Override
public Component prepareRenderer(
TableCellRenderer renderer, int row, int column)
{
Component c = super.prepareRenderer(renderer, row, column);
if (column == getSelectedColumn()) { c.setBackground(Color.RED); }
else if (row == getSelectedRow()) { c.setBackground(Color.YELLOW); }
else c.setBackground(getBackground());
return c;
}
};
frame.add(new JScrollPane(table));
frame.setVisible(true);
frame.pack();
}
});
}
}
But unfortunately I have problems with artifacts now. Similar to the picture below (which is taken from a version which is colored in red only).
I'm using Java 1.8.0_74 on Windows 10.0.16299 Build 16299. JXTable
is from
<dependency>
<groupId>org.swinglabs.swingx</groupId>
<artifactId>swingx-all</artifactId>
<version>1.6.5-1</version>
</dependency>
It seems to work when using a JTable (although the order of the if statements needs to be changed if you want the column to have priority). So it seems that JXTable does some additional rendering that is causing the problem.
So here is an alternative approach based on Table Row Rendering that appears to work for JXTable:
JXTable table = new JXTable(new CustomTableModel())
{
public Component prepareRenderer(
TableCellRenderer renderer, int row, int column)
{
Component c = super.prepareRenderer(renderer, row, column);
if (column == getSelectedColumn()) { c.setBackground(Color.RED); }
else if (row == getSelectedRow()) { c.setBackground(Color.YELLOW); }
else c.setBackground(getBackground());
return c;
}
};
The above code replaces the custom renderer:
//table.setDefaultRenderer(Object.class, new CustomTableCellRenderer());
Note: in your "MCVE" of my suggestion you removed:
boolean highlightRow = false;
table.setRowSelectionAllowed(highlightRow);
table.setColumnSelectionAllowed(!highlightRow);
Why? I only gave you the above 2 changes.
This is why you need to post a proper "MCVE" so we can be sure you implemented the suggestion properly.