Updating cell renderer after a DefaultCellEditor derived instance does its job - java

I use a JTable which has its own cell renderer and cell editor.
Say, this table contains 2 columns and x rows:
The first column contains a boolean value, its own cell rendering and cell editor (a radiobutton)
The second column contains a string value, its own cell renderer: it makes it bold when the first column of the current row is set to true (radiobutton checked)
All the values are correctly updated by the editor but the 2nd row does not become bold when the radio button is set to true...
I have to check a radio button from a different row to see the changes
Where can I fire thoses changes ?
Cheers and thanks for your help
RadiobuttonTableCellEditor.java
public class RadiobuttonTableCellEditor extends DefaultCellEditor
implements ItemListener {
JRadioButton rb = new JRadioButton();
public RadiobuttonTableCellEditor(JCheckBox pCheckBox) {
super(pCheckBox);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
if (value == null)
return null;
rb.addItemListener(this);
rb.setSelected((Boolean)value);
return rb;
}
public void itemStateChanged(ItemEvent e) {
super.fireEditingStopped();
}
public Object getCellEditorValue() {
rb.removeItemListener(this);
return rb.isSelected();
}
}

In your table model whenever your value changes you have to fire appropriate event. If your model is inherited from AbstractTableModel you can use several fireXXX methods. My guess is you should call them from setValueAt method.
If you know exact column and row - you can call fireTableCellUpdated, otherwise you can you probably have to use fireTableChanged since you have to update different column.
And of course you renderer should properly render new value.

It doesn't seem to make any sense to extend DeafultCellEditor there. Implementing a listener interface like that is also not a great idea.
Renderers work best as a thin layer. If another cell should change, then that needs to be reflected in the table model which should fire a relevant update event.

I guess it could help people with a similar problem, make a true radiobutton unique in a row, you'll have to extend the DefaultTableModel to modify its behaviour especially the setValueAt method
Cheers
/**
* When <code>column</code> is the column that contains the Boolean (in fact the radio button):
* If aValue == false and that it had a previous value set to true we don't do anything
* If aValue == true and that it had a previous value set to false, we set all the other booleans to false and this one to true
*/
#Override
public void setValueAt(Object aValue, int row, int column) {
if (column == colonneBoutonradio)
{
if (((Boolean)aValue && !(Boolean)super.getValueAt(row, column)))
for (int i = 0; i < this.getRowCount(); i++)
// i==row permet de vérifier si la ligne courante est celle à modifier (et donc celle à mettre à true)
super.setValueAt(i==row, i, colonneBoutonradio);
}
else
super.setValueAt(aValue, row, column);
}

Related

How to set the focus to the JTable cell if validation fails in java?

Every time it is setting focus to first cell of any row after validation. I need to set the focus to particular cell in any row, not the first cell.Here in my code every time the row is changing, but every time the column value comming as 0 and i am unable to find from where this method is calling.
public class TestRenderer implements TableCellRenderer
{
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected,boolean hasFocus, int row, int column)
{
if(mandatoryValue == true)
{
setBackground(Color.RED);
}
}
}
}

JTable CustomRenderer Issue

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.

Change the color of some rows but not all in a JTable

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

GWT Celltable How to make Non-Editable cell in Editable column

I added EditTextCell(stringTestEditTextCell) to Column(testColumn).
EditTextCell editTextCell = new EditTextCell();
Column stringColumn = new Column(
editTextCell) {
#Override
public String getValue(Record object) {
return object.getValue();
}
};
All cells in testColumn are editable.
I want 1st cell of column such way that 1st cell of column should be Non-Editable.
Following class is answer to my question. I Solved it and works fine. But getting error when user clicking on 1st cell of column.
class CustomEditTextCell extends EditTextCell{
#Override
public void render(com.google.gwt.cell.client.Cell.Context context,
String value, SafeHtmlBuilder sb) {
// context.getColumn()==2 indicate Record ID column and context.getIndex()==0 indicate non editable cell in 1st empty row
if(context.getColumn()==2 && ( context.getIndex()==0 || context.getIndex()%10 == 0)){
sb.appendHtmlConstant("<div contentEditable='false' unselectable='true'></div>");
}else{
super.render(context, value, sb);
}
}
}
You might extend EditTextCell and override the edit()-Method so that it only edits when you have not set a boolean flag that you that you need to set for the first cell.

JTable disable Checkbox in Cell

Hello I have a JTable And i want to grey out all the disabled checkbox cells i tried with a custom renderer checking isEnabled() and then changing the background color but still not workin.
Any suggestions?
thanks!!!
As noted in Concepts: Editors and Renderers, "a single cell renderer is generally used to draw all of the cells that contain the same type of data." You'll need to maintain the enabled state in your table model.
Addendum: As a concrete example, the data model in this example is a simple array of Date instances. Overriding getTableCellRendererComponent() as shown below causes odd days to be disabled. In this case, being odd is a property inherent to the Date value itself, but the model could be queried for any related property at all.
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row, int col) {
Calendar calendar = Calendar.getInstance();
calendar.setTime((Date) value);
Component c = super.getTableCellRendererComponent(
table, value, isSelected, hasFocus, row, col);
c.setEnabled(calendar.get(Calendar.DAY_OF_MONTH) % 2 == 0);
return c;
}
Addendum: In the example above, the DateRenderer is evoked because the TableModel returns the type token Date.class, for which it has been made the default.
table.setDefaultRenderer(Date.class, new DateRenderer());
An identical appearance can be obtained by overriding prepareRenderer() as shown below, but the method is invoked for all cells, irrespective of class. As a result, prepareRenderer() is ideal for affecting entire rows, as shown in Table Row Rendering.
private final JTable table = new JTable(model) {
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
Component c = super.prepareRenderer(renderer, row, col);
if (col == DATE_COL) {
Calendar calendar = Calendar.getInstance();
calendar.setTime((Date) model.getValueAt(row, col));
c.setEnabled(calendar.get(Calendar.DAY_OF_MONTH) % 2 == 0);
}
return c;
}
};

Categories