I have a JTable that is showing some records in a Java Swing application. The user only works with whole rows, not with individual cells. Is there any way I can focus on a whole row of a JTable? The default is to focus only the cell that the user has clicked on. I use a different color for the focus, so it doesn't look good if only a cell is focused instead of the whole row.
UPDATE: This is my current code of my custom TableCellRenderer, the issue is that when a row has focus and is painted with the "focus" color, and then the JTable loses focus, only the cell that had focus is repainted with the "selected" color but all cells in the selected row should be repainted with the "selected" color.
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
// Has any cell in this row focus?
if(table.getSelectedRow() == row && table.hasFocus()) {
hasFocus = true;
}
if (hasFocus) {
this.setBackground(CustomColors.focusedColor);
} else if (isSelected) {
this.setBackground(CustomColors.selectedColor);
} else {
// alternate the color of every second row
if(row % 2 == 0) {
this.setBackground(Color.WHITE);
} else {
this.setBackground(CustomColors.grayBg);
}
}
setValue(value);
return this;
}
Sounds like you're looking for the setRowSelectionAllowed() method.
Since you said just changing the color would be sufficient, you might want to look at the custom cell renderer section of the Swing Tutorial. You'd just have to set the logic to check on whether a given cell was in a selected row, and paint the background color accordingly.
A first idea would be something like
JTable jTable = new JTable() {
public TableCellRenderer getCellRenderer(int row, int column) {
final TableCellRenderer superRenderer = super.getCellRenderer(row, column);
return new TableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object object, boolean isSelected, boolean hasFocus, int row, int column) {
// determine focus on row attribute only
hasFocus = hasFocus() && isEnabled() && getSelectionModel().getLeadSelectionIndex() == row;
return superRenderer.getTableCellRendererComponent(table, object, isSelected, hasFocus, row, column);
}
};
}
};
where I use my own logic to determine the focus based on the row attribute only. It uses the underlying cell renderers but looks strange if focus border is used.
Related
So I know this may be a duplicate question, but I've looked through many of the ones already on here and none of them seem to work for me, so I thought I would post my own and hopefully some of the other people having trouble with this will find this helpful also.
Here is my code
table.getColumn("Name").setCellRenderer(
new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText(value.toString());
if (row==3)
{
setForeground(Color.RED);
}
return this;
}
}
);
Here is what is displayed in the JFrame. As you can see I am trying to to only color the text in the third row of the Column "Name" but it colors the whole row.
Any suggestions?
Thanks!
Canaan
The render is unique for column "Name". You are setting Red as foreground color when row is 3 but you dont reset it for others rows, so when painter is called it always paint red.
You have to set red when row is 3 but you also have to reset the original color in other case.
EDITED: Performed version. Now original foreground color is backed up, and super is used to render like others columns.
table.getColumn("Name").setCellRenderer(
new DefaultTableCellRenderer() {
Color originalColor = null;
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (originalColor == null) {
originalColor = getForeground();
}
if (value == null) {
renderer.setText("");
} else {
renderer.setText(value.toString());
}
if (row == 3) {
renderer.setForeground(Color.RED);
} else {
renderer.setForeground(originalColor); // Retore original color
}
return renderer;
}
});
I'm trying to change the colour of one or more particular cells in a column in my JTable. The answers I have seen on here all refer to this particular method;
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
{
Component y = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
y.setBackground(new Color(255,0,0));
return y;
}
But the problem is I do not understand in any way how this works, in my other class I have a Jtable of strings and I want to change the colour of certain cells according to their string value, however the solutions i find only allow me to change the colour of an entire column of cells in the jtable and not a specific one.
I have a Jtable of strings and I want to change the colour of certain cells according to their string value
The same renderer is used for all cells so you need to reset the background every time.
You will need an if condition in your custom renderer code. Something like:
if (!isSelected)
if (value.equals(...))
y.setBackground(new Color(255,0,0));
else
y.setBackground(table.getBackground())
You can use DefaultTableCellRenderer to color alternate row from JTable.
table.setDefaultRenderer(Object.class, new TableCellRenderer(){
private DefaultTableCellRenderer DEFAULT_RENDERER = new DefaultTableCellRenderer();
#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){
c.setBackground(Color.WHITE);
}
else {
c.setBackground(Color.LIGHT_GRAY);
} }
//Add below code here
return c;
}
});
If you want to color your row using the value of a particular row then you can use something like this. Add these line to above
if(table.getColumnModel().getColumn(column).getIdentifier().equals("Status")){//Here `Status` is column name
if(value.toString().equals("OK")){//Here `OK` is the value of row
c.setBackground(Color.GREEN);
}
}
I have created one Jtable.This table consist of two columns name and timestamp. I want to make color of row yellow if name is "jane". Following is the code for that :-
class CustomRenderer extends DefaultTableCellRenderer {
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);
String name = table.getModel().getValueAt(row, 0).toString();
if (name.trim().equals("jane")) {
c.setBackground(Color.YELLOW);
}
return c;
}
}
However instead of changing color of row to yellow for particular name, it is changing color of every row.I am setting data of table as following
tableModelName = (DefaultTableModel)jTableName.getModel();
jTableName.setDefaultRenderer(Object.class,new CustomRenderer());
for(int i=0; i<records.size(); i++)
{
tableModelName.addRow(records.get(i));
}
What I am doing wrong ?
You need an else clause to set the background color to something besides yellow if the name is not "jane". A single renderer instance is used for all rendering, so once you set the color to yellow on that instance, it stays yellow.
Take a look at the JTable source code to see how the built-in renderers work:
if (isSelected) {
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
}
else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
For an easier way of doing this, you might try subclassing JTable and overriding prepareRenderer. This is handy for changes that affect entire rows like this, so you can use custom renderers for the individual cells, and tweak all renderers for a row in the prepareRenderer method.
Trying to achieve this on Jtable.
I was trying to align two words like one on left side and another on right side but in the same line.
String html="<html><div style='float:left;width:50%;'>left</div><div style='float:right;width:50%;'>right</div></html>";
Object rowData[][] = { { html, "Column2-data"}};
unfortunately it didn't work. I tried with p tag and font tag as well.
Please help me on how can I achieve this using HTML tags.
You can create your own table cell renderer to center the text in your JTable
public class CenterCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int column) {
JLabel renderedLabel = (JLabel) super
.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
renderedLabel.setHorizontalAlignment(JLabel.CENTER);
return renderedLabel;
}
}
To use this table cell renderer for the entire table:
TableCellRenderer renderer = new CenterCellRenderer();
table.setDefaultRenderer(Object.class, renderer);
To define a column specific renderer, you need to define a JTable subclass that overrides the getCellRenderer method
table = new JTable(...) {
public TableCellRenderer getCellRenderer(int row, int column) {
if (column == 2) {
return renderer;
}
// else...
return super.getCellRenderer(row, column);
}
};
Now that I've thought about your question a bit more, I'd put the text in two columns. If necessary, you can right align the text in the second column using a right justify cell renderer similar to the one I created for centering text.
I have created a custom cell renderer class to achieve this.
public class MatchTableCellRenderer extends DefaultTableCellRenderer{
public Component getTableCellRendererComponent (JTable table,
Object obj, boolean isSelected, boolean hasFocus, int row, int column) {
Component cell;
cell = super.getTableCellRendererComponent(
table, obj, isSelected, hasFocus, row, column);
if( ((String[]) ((MatchTableModel) table.getModel()).getRow(row)).length==7 ){
System.out.println(((String[]) ((MatchTableModel) table.getModel()).getRow(row))[0]+" "+((String[]) ((MatchTableModel) table.getModel()).getRow(row))[6]);
cell.setForeground(Color.green);
}
return cell;
}
}
And I have set this renderer to be used by my table's columns:
tempColumn = table.getColumnModel().getColumn(0);
tempColumn.setCellEditor(new MacColumnEditor());
tempColumn.setCellRenderer(new MatchTableCellRenderer());
tempColumn = table.getColumnModel().getColumn(1);
tempColumn.setCellEditor(new IpColumnEditor());
tempColumn.setCellRenderer(new MatchTableCellRenderer());
tempColumn = table.getColumnModel().getColumn(2);
DefaultCellEditor dfEditor=new DefaultCellEditor(new JTextField());
dfEditor.setClickCountToStart(2);
tempColumn.setCellEditor(dfEditor);
tempColumn.setCellRenderer(new MatchTableCellRenderer());
I want the rows which contain a String[] of length=7 green and the others with the default color. But it is interesting that all my rows become green. I have a print line as you can see. It is printed 4 times (my table has 12 rows), but all rows are made green, instead of 4. What am I doing wrong?
The reason is the infamous color memory (TM) of the DefaultTableCellEditor: you have to set the colors always, instead of only in one branch.
if (myCondition) {
setBackground(...) {
} else {
setBackground(...)
}
the exact details are explained in a recent thread
You can use XxxCellRenderer, but better and easiest is to use prepareRenderer()
for correct code you have to override or test inside if-else follows patameters
isSelected
hasFocus
column
row
more in answers and question about similair issue