Hi I am able to render the Boolean column as a JToggleButton but if I keep the button pressed, I am seeing the checkbox instead of the button.
TableColumnModel tcm = smartAlertsTable.getColumnModel();
TableColumn tc = tcm.getColumn( Index of the boolean column);
tc.setCellRenderer(new ActiveAlertRenderer());
where ActiveAlertRenderer is
public class ActiveAlertRenderer extends JToggleButton implements
TableCellRenderer
{
public ActiveAlertRenderer()
{
super();
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column)
{
boolean isActive = ((Boolean) value).booleanValue();
if (isActive)
{
this.setText("Armed");
this.setSelected(false);
value = Boolean.TRUE;
}
else
{
this.setText("Triggered");
this.setSelected(true);
value = Boolean.FALSE;
}
return this;
}
}
How do I prevent the checkbox from appearing?
JTable uses a checkbox as a default renderer and editor for boolean columns. You provided your own renderer but the editor remains default. This is the checkbox that you see when you edit the cell. You'd have to provide a custom editor (implementation of TableCellEditor) in a similar fashion you did the renderer. You can set it up using JTable.setDefaultEditor() or TableColumn.setCellRenderer.
See Concepts: Editors and Renderers in How to Use Tables tutorial for more details.
Try like this:
public class ActiveAlertRenderer extends DefaultTableRenderer {
private JToggleButton toggleButton = new JToggleButton();
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (column==INDEX_OF_TOGGLE_BUTTON_COLUMN) {
boolean active = (Boolean) argValue;
if (active) {
toggleButton.setText("Armed");
} else {
toggleButton.setText("Triggered");
}
toggleButton.setSelected(active);
return toggleButton;
}
else {
return super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
}
}
}
Related
I have a JTable on a Netbeans 8.2 project which shows the data of a list a class (let's call it Client) and a checkbox on the first column of each line. I've setup this way changing the data type of the column in the object's properties menu. How can I not show this checkbox in case that a client's attribute is false?
I assume the first column is not editable. If you want to hide the JCheckBox when cell value is false, you can use a customer cell renderer:
private class MyCellRenderer extends DefaultTableCellRenderer
{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col)
{
Component c;
if (((Boolean)value).equals(true))
{
// Use the default renderer for Boolean which is JCheckBox based
c = myTable.getDefaultRenderer(table.getColumnClass(col)).getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
} else
{
// Use the standard default renderer which is a JLabel
c = super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
if (c instanceof JLabel)
{
((JLabel) c).setText(null);
}
}
return c;
}
}
And apply it on the first boolean column:
myTable.getColumnModel().getColumn(0).setCellRenderer(new MyCellRenderer());
I have a JTable, that I want I want to be able to change the color of a single cell that is clicked on.
Here is a simplified version of my code:
public class TableFrame extends JFrame {
public TableFrame() {
JTable table = new JTable(8, 8);
table.setGridColor(Color.BLACK);
table.setDefaultRenderer(CustomCellRenderer.class, new CustomCellRenderer());
getContentPane().add(table);
}
public class CustomCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (hasFocus) {
l.setBackground(Color.red);
l.setText("Hello");
}
return l;
}
}
}
When I click a certain cell, I expect it to change color to red and add "Hello" to it. It changes the text, but for some weird reason, it changes the color of all the cells after it? And when I click an uncolored cell, it does the same, but not always in an organised way if that makes sense? Like, it won't color all the cells after it, but maybe some that are just above and leave others blank..
It's really weird and makes no sense whatsoever. What is happening??
Having dug around the DefaultTableCellRenderer class a bit, when you call setBackground on the JLabel component, which is backing the DefaultTableCellRenderer, it is storing the value you use...
public void setBackground(Color c) {
super.setBackground(c);
unselectedBackground = c;
}
When the cell is painted again, it's this value (unselectedBackground) which is been used to repaint the cell in "default" mode...
if (isSelected) {
//...
} else {
Color background = unselectedBackground != null
? unselectedBackground
: table.getBackground();
if (background == null || background instanceof javax.swing.plaf.UIResource) {
Color alternateColor = DefaultLookup.getColor(this, ui, "Table.alternateRowColor");
if (alternateColor != null && row % 2 != 0) {
background = alternateColor;
}
}
super.setForeground(unselectedForeground != null
? unselectedForeground
: table.getForeground());
super.setBackground(background);
}
This means, the moment you use setBackground and pass it Color.RED, the DefaultTableCellRenderer assumes that this becomes the default color for ALL unselected cells.
The only choice you have is to reset the background color manually, for example...
public class CustomCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (hasFocus) {
l.setBackground(Color.red);
l.setText("Hello");
} else if (!isSelected) {
l.setBackground(table.getBackground());
}
return l;
}
}
Also, you should really be using something more like...
table.setDefaultRenderer(Object.class, new CustomCellRenderer());
to register the cell renderer, as it's the Class type returned by TableModel#getColumnClass which determines which cell renderer is used ;)
Since the OP only wants help with the rendered and not with the data... here goes (assuming there is a function called hasBeenClicked(row,column) method available to determine whether the cell has been visited yet.
public class CustomCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (hasBeenClicked(row,column)) {
l.setBackground(Color.red);
l.setText("Hello");
} else {
// reset the label to white background
l.setBackground(Color.white);
l.setText("Hello");
}
return l;
}
}
}
Also note that the registration of the renderer should be
table.setDefaultRenderer(Object.class, new CustomCellRenderer());
Since we want all columns to have this renderer (renderers are registered against the class of the column in the model).
I tested with the below as the hasBeenClicked method.
public boolean hasBeenClicked(int row, int column){
return (row%2==0 && column%2==0);
}
Just implement your own tracking of whether a cell has been clicked or not and you should be good to go. Remember that you should not use the renderer to track the clicks, use some kind of listener instead.
I am trying to create a TableCellRenderer which changes the background of row. I am overriding the prepareRenderer, it changes the background of row on selection but as soon as I change the selection the default background color(white) is set to previous selected row and newer row gets the background color(light grey).
Here is my code:
final JTable table = new JTable(model)
{
#Override
public Component prepareRenderer(TableCellRenderer renderer,int row,int column)
{
Component comp=super.prepareRenderer(renderer,row, column);
int modelRow=convertRowIndexToModel(row);
if(!isRowSelected(modelRow))
comp.setBackground(Color.WHITE);
else
comp.setBackground(Color.LIGHT_GRAY);
return comp;
}
};
My output screen:
I want to do like this:
For your requirement you can do the following:
IN your model keep a hidden column of flag values. Assume that your hidden column is 5 column and you can code as below:
final JTable table = new JTable(model)
{
#Override
public Component prepareRenderer(TableCellRenderer renderer,int row,int column)
{
Component comp=super.prepareRenderer(renderer,row, column);
int modelRow=convertRowIndexToModel(row);
if((Boolean)getValueAt(row,5))
comp.setBackground(Color.LIGHT_GRAY);
else
comp.setBackground(Color.WHITE);
return comp;
}
};
Your flag values contain the Boolean object.
Try this:
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);
//table.setBackground(Color.YELLOW);
//table.setSelectionBackground(Color.YELLOW);
if(isSelected){
c.setBackground(Color.YELLOW);
}else{
if (row%2 == 0){
c.setBackground(Color.WHITE);
}
else {
c.setBackground(Color.LIGHT_GRAY);
} }
return c;
}
});
I know I can set the whole column's background color with this code, but how can I set a different color for each cell? I have a table with two columns and one to one thousand rows.
words.getColumn("columnNameHere").setCellRenderer(
new DefaultTableCellRenderer() {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText(value.toString());
setBackground(Color.RED);
return this;
}
}
);
The row and column number are passed into getTableCellRendererComponent. So you could do something like:
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
setText(value.toString());
if (row==12 && column==2) {
setBackground(Color.RED);
}
return this;
}
I have a column in a JTable with cells rendered as checkboxes below:
How do I prevent the checkboxes from moving every time I click on it? Here is my cell renderer and cell editor:
protected class CheckBoxCellRenderer extends JCheckBox implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.setSelected((Boolean) tableModel.getValueAt(row, 0));
return this;
}
}
protected class CheckBoxCellEditor extends AbstractCellEditor implements TableCellEditor, ActionListener {
private final CheckBoxCellRenderer cell = new CheckBoxCellRenderer();
private int row;
public CheckBoxCellEditor() {
cell.addActionListener(this);
}
#Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int rowIndex, int vColIndex) {
cell.setSelected(((Boolean) value).booleanValue());
row = rowIndex;
return cell;
}
#Override
public Object getCellEditorValue() {
return cell.isSelected();
}
}
Thanks!
Don't create a custom renderer/editor.
JTable already supports a default renderer. Just override the getColumnClass(...) method of the TableModel or JTable to return Boolean.class for the first column and the JTable will use the default renderer/editor.