Jtable setDefaultRenderer disappears checkbox in cell - java

I have a boolean column in JTable, so i each cell there is a checkbox. When i try to set a cell renderer in order to change the background color the checkbox from cell replaced by values (true, false).. What's goin wrong!!
My cell renderer:
class BackgroundTableCellRenderer extends DefaultTableCellRenderer {
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(row%2 == 0)
{
Color bColor = Color.decode("#EFF2ED");
c.setBackground(bColor);
}
else
c.setBackground(Color.white);
return c;
}
}
I set the renderer like that:
data_table.setDefaultRenderer(Boolean.class, new BackgroundTableCellRenderer());

use prepareRenderer for line decorating
or for (Xxx)TableCellRenderer you can to try with
.
class BooleanRenderer extends JCheckBox implements TableCellRenderer, UIResource {
private static final long serialVersionUID = 1L;
private final Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
BooleanRenderer() {
super();
setHorizontalAlignment(JLabel.CENTER);
setBorderPainted(true);
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
if (isSelected) {
setForeground(table.getSelectionForeground());
super.setBackground(table.getSelectionBackground());
} else {
setForeground(table.getForeground());
setBackground(table.getBackground());
}
setSelected(value != null && ((Boolean) value).booleanValue());
if (hasFocus) {
setBorder(UIManager.getBorder("Table.focusCellHighlightBorder"));
} else {
setBorder(noFocusBorder);
}
return this;
}
}

Related

JTable how can i create custom column renderer

static class DateRenderer extends DefaultTableCellRenderer {
DateFormat formatter = new SimpleDateFormat("dd.MM.yyyy");
public DateRenderer() { super(); }
public void setValue(Object value) {
if (formatter==null) {
formatter = DateFormat.getDateInstance();
}
setText((value == null) ? "" : formatter.format(value));
}
}
I use this code to render dates. I found it as this but now i need something else. I have a column with numbers as this (1234.56). I want to render the numbers as (1234.56 TL). But i am kinda beginner so i can't find the way to do it.
TableColumnModel m = table.getColumnModel();
m.getColumn(5).setCellRenderer(new TableRendererExample());
class TableRendererExample extends DefaultTableCellRenderer {
#Override
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);
if (column == 5) {
setText(value.toString()+" TL");
}
return this;
}
}
This code works fine for answer.

Highlight a specifi row JTable

I know there are previous topics for a similar problem but even with it I wasn't able to resolve my problem.
So the thing is, when I add a new empty row to my JTable I want to highlight it in gray. So it works for the first one but when I try to add a second row, the second will be white...
I tried to debbug but without success, I didn't find my mistake.
Here is the class to highlight a row :
class GrayWhiteRenderer extends DefaultTableCellRenderer {
private int rowToColored;
GrayWhiteRenderer(int rowToColored) {
this.rowToColored = rowToColored;
Color color = UIManager.getColor ( "table.row" );
}
#Override
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);
if (UIManager.getColor ( "table.row" )==Color.GRAY) {
c.setBackground(Color.GRAY.brighter());
}
else if(row == rowToColored) {
c.setBackground(Color.GRAY.brighter());
} else {
c.setBackground(Color.WHITE);
}
return c;
}
}
I store the index of all new row in rowToAdd at the begining of it (for exemple : [19, 20, 21, -1, -1, ...]. -1 is to know when I have to stop looking if I have to highlight more) :
while(rowToAdd[k]!=-1) {
System.out.println("rowToAdd[k] : "+rowToAdd[k]);
dataTable.setDefaultRenderer(Object.class, new GrayWhiteRenderer(rowToAdd[k]));
k++;
}
And here is a class to test it :
package Graphic;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.*;
import java.awt.event.*;
class Test implements Runnable, ActionListener {
public static void main(String[] args) {
SwingUtilities.invokeLater(new Test());
}
JTable table;
#Override
public void run() {
JFrame frame = new JFrame("Custom Cell Renderer");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
table = new JTable(new DefaultTableModel(0, 2) {
#Override
public Class<?> getColumnClass(int c) {
return Object.class;
}
});
class GrayWhiteRenderer extends DefaultTableCellRenderer {
private int rowToColored;
GrayWhiteRenderer(int rowToColored) {
this.rowToColored = rowToColored;
}
#Override
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);
if (UIManager.getColor ( "table.row" )==Color.GRAY) {
c.setBackground(Color.GRAY.brighter());
}
else if(row == rowToColored) {
c.setBackground(Color.GRAY.brighter());
} else {
c.setBackground(Color.WHITE);
}
return c;
}
}
table.setDefaultRenderer(Object.class, new GrayWhiteRenderer(table.getRowCount()));
table.setTableHeader(null);
JButton btn = new JButton("Add Row");
btn.addActionListener(this);
JToolBar bar = new JToolBar();
bar.setFloatable(false);
bar.add(btn);
JPanel content = new JPanel(new BorderLayout());
content.add(bar, BorderLayout.NORTH);
content.add(new JScrollPane(table), BorderLayout.CENTER);
frame.setContentPane(content);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
#Override
public void actionPerformed(ActionEvent ae) {
int nextRow = table.getRowCount();
DefaultTableModel model = (DefaultTableModel)table.getModel();
model.addRow(new Object[] { "" + nextRow, "" + nextRow });
for(int i=0; i<model.getColumnCount(); i++) {
table.setDefaultRenderer(Object.class, new GrayWhiteRenderer(i));
}
}
}
So, I've fixed your example. Here is your code with my comments
#Override
public void actionPerformed(ActionEvent ae) {
int nextRow = table.getRowCount();
DefaultTableModel model = (DefaultTableModel) table.getModel();
model.addRow(new Object[] {"" + nextRow, "" + nextRow});
// the correct row is: nextRow. No loop required here.
table.setDefaultRenderer(Object.class, new GrayWhiteRenderer(nextRow));
}
I would also correct your renderer to provide selection highlight
class GrayWhiteRenderer extends DefaultTableCellRenderer {
private int rowToColored;
GrayWhiteRenderer(int rowToColored) {
this.rowToColored = rowToColored;
}
#Override
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);
// As I know there is no value is registered for "table.row" in UIManager
// so I've skipped the first condition
if (row == rowToColored) {
c.setBackground(Color.GRAY.brighter());
} else {
// use correct color depended on whether the cell is selected or not!
c.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground());
}
return c;
}
}

JTable - DefaultTableCellRenderer - getCurrencyInstance()

I want to change the format of column 2 (Columna 2) to currency format of all the data, I am trying with this, but it does not do anything.
Could you help me?
These are my data:
I want the data to come out like this:
With this code I am trying:
public class CurrencyCellRenderer extends DefaultTableCellRenderer {
#Override
public final Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
final Component result = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
if (value instanceof Number) {
setHorizontalAlignment(JLabel.CENTER);
setText(defaultFormat.format(value));
} else {
setText("NO");
}
return result;
}
}
jTable1.getColumnModel().getColumn(2).setCellRenderer(new CurrencyCellRenderer());
It does not do anything, could you help me?
Thanks!!!
You need to create result after changing value's value. Creating result before, will just return the same old data.
e.g.,
private class CurrencyCellRenderer extends DefaultTableCellRenderer {
#Override
public final Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) {
value = 0.0;
}
value = myFormat.format(value);
final Component result = super.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
return result;
}
}
My MCVE for proof of concept:
import java.awt.BorderLayout;
import java.awt.Component;
import java.text.NumberFormat;
import java.util.Locale;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
#SuppressWarnings("serial")
public class CurrencyTable extends JPanel {
private static final String[] TABLE_HEADERS = { "Text", "Value" };
private static final Object[][] DATA = { { "Foo", 1.1 }, { "Bar", 2.2 }, { "Bax", 3.3 } };
private DefaultTableModel tableModel = new DefaultTableModel(DATA, TABLE_HEADERS);
private JTable table = new JTable(tableModel);
private NumberFormat myFormat = NumberFormat.getCurrencyInstance(Locale.FRANCE);
public CurrencyTable() {
table.getColumnModel().getColumn(1).setCellRenderer(new CurrencyCellRenderer());
setLayout(new BorderLayout());
add(new JScrollPane(table));
}
private class CurrencyCellRenderer extends DefaultTableCellRenderer {
#Override
public final Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
if (value == null) {
value = 0.0;
}
value = myFormat.format(value);
final Component result = super.getTableCellRendererComponent(table, value, isSelected,
hasFocus, row, column);
return result;
}
}
private static void createAndShowGui() {
CurrencyTable mainPanel = new CurrencyTable();
JFrame frame = new JFrame("CurrencyTable");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().add(mainPanel);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGui());
}
}
Ok, i have the solution:
NumberFormat defaultFormat = NumberFormat.getCurrencyInstance();
public class MyRenderer extends JLabel implements TableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus, int row,
int col) {
DefaultTableCellRenderer renderer
= new DefaultTableCellRenderer();
Component c = renderer.getTableCellRendererComponent(table,
value, isSelected, hasFocus, row, col);
String s = "";
if (col == 2) {
double d = Double.parseDouble( String.valueOf(value)) ;
s = defaultFormat.format(d);
c = renderer.getTableCellRendererComponent(table, s,
isSelected, hasFocus, row, col);
((JLabel) c).setHorizontalAlignment(SwingConstants.RIGHT);
}
return c;
}
}
jTable1.getColumnModel().getColumn(2).setCellRenderer(new MyRenderer());
Image here
Thanks for all guys!

JTable row background color not changing for Double or Integer

I am changing the background color of a row in JTable using following code.
The color of row gets changed for all the cells which have String values however it does not gets changed for cells with Integer or Double values.
private JTable getNewRenderedTable(final JTable table) {
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
#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);
String status = (String)table.getModel().getValueAt(row, index);
if (Constants.seller.equals(status)) {
c.setBackground(Color.GRAY);
//setForeground(Color.WHITE);
} else {
c.setBackground(table.getBackground());
c.setForeground(table.getForeground());
}
return c;
}
});
return table;
}
Try to register the same renderer also for Integer and Double. These classes have separate default renderer registered by default. Something like this.
private JTable getNewRenderedTable(final JTable table) {
table.setDefaultRenderer(Object.class, new DefaultTableCellRenderer() {
#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);
String status = (String)table.getModel().getValueAt(row, index);
if (Constants.seller.equals(status)) {
c.setBackground(Color.GRAY);
//setForeground(Color.WHITE);
} else {
c.setBackground(table.getBackground());
c.setForeground(table.getForeground());
}
return c;
}
});
table.setDefaultRenderer(Number.class, table.getDefaultRenderer(Object.class));
table.setDefaultRenderer(Double.class, table.getDefaultRenderer(Object.class));
return table;
}

Add margin to JTable column (Mac)

I have a JTable looking like this:
Is it possible to add a margin for the column text?
I have tried to add a TableCellRenderer and add an EmptyBorder. Problem: the background color gets white like this:
Any idea how to add margin and keep the default background color?
public class JTableColumnMargin extends JFrame {
public JTableColumnMargin() {
Object rowData[][] = { { "Row1-Column1", "Row1-Column2", "Row1-Column3" }, { "Row2-Column1", "Row2-Column2", "Row2-Column3" } };
Object columnNames[] = { "Column One", "Column Two", "Column Three" };
JTable table = new JTable(rowData, columnNames);
for (int i = 0; i < table.getColumnCount(); i++) {
table.getTableHeader().getColumnModel().getColumn(i).setHeaderRenderer(new HeaderRenderer(table));
}
JScrollPane scrollPane = new JScrollPane(table);
this.add(scrollPane, BorderLayout.CENTER);
this.setSize(500, 150);
this.setVisible(true);
}
private static class HeaderRenderer implements TableCellRenderer {
private DefaultTableCellRenderer renderer;
private HeaderRenderer(JTable table) {
renderer = (DefaultTableCellRenderer) table.getTableHeader().getDefaultRenderer();
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
Component c = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
JLabel label = (JLabel) c;
label.setBorder(BorderFactory.createEmptyBorder(0, 10, 0, 10));
return label;
}
}
public static void main(String[] args) {
new JTableColumnMargin();
}
}
Delegating to the original renderer basically is the right direction to go, just slightly differently:
use a compoundBorder of the original and the emptyBorder
nudge the original renderer to re-set the border to its original by making the padded border a UIResource
Something like:
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
JComponent comp = (JComponent) originalRenderer.getTableCellRendererComponent(table, value,
isSelected, hasFocus, row, column);
Border originalBorder = comp.getBorder();
comp.setBorder(new CompoundBorderUIResource(originalBorder,
BorderFactory.createEmptyBorder(0, 20, 0, 0)));
return comp;
}
It's brittle, though, as LAFs might ignore your setting: the trick works fine for WinLAF, but not at all for Nimbus - so don't know the outcome on Mac.
Try to use next header Renderer:
private static class HeaderRenderer extends JLabel implements TableCellRenderer {
private HeaderRenderer() {
setBorder(BorderFactory.createCompoundBorder(UIManager.getBorder("TableHeader.cellBorder"),BorderFactory.createEmptyBorder(0, 10, 0, 10)));
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
setText(value.toString());
return this;
}
}

Categories