I'm trying to implement mouse hover effects for my JTable.
(When the mouse goes over a table's row the row's background changes).
In order to do that, I extended the DefaultTableCellRenderer like this:
public class FileTableCellRenderer extends DefaultTableCellRenderer{
public FileTableCellRenderer() {
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
FileTable fileTable = (FileTable)table;
Component c = super.getTableCellRendererComponent(fileTable, value, isSelected, hasFocus, row, column);
if(!isSelected){
if(row == fileTable.getCursorRow())
{
c.setBackground(Color.pink);
c.setForeground(Color.darkGray);
}
else
{
c.setBackground(Color.white);
c.setForeground(Color.darkGray);
}
}
this.setText(value.toString());
return this;
}
}
I set the JTable's defaultRenderer, and it works. The problem is I have one column which is Boolean. before I set my renderer I had this cute checkbox as default renderer for it.
Now, it just shows "true" or "false".
On the other hand, if I leave the defualt BooleanRenderer for the Boolean column, it will not be highlighted with the whole row...
I also tried to extned the JTable.BooleanRenderer, but it seems to be protected, so I cannot even extend it.
How can I leave this checkbox of the BooleanRenderer, but change background color with the rest of the row?
This cannot be done using inheritance since BooleanRenderer is a non-public inner class of JTable. But you can use composition instead. E.g., create a wrapper class that will accept a TableCellRenderer ('parent') as a constructor argument. If you pass a BooleanRenderer from your table as a parent, calling its getTableCellRendererComponent() method will return a Checkbox component, so you'll be able to make any further adjustments to it (I use code from the question to set the background color):
import javax.swing.*;
import javax.swing.plaf.UIResource;
import javax.swing.table.TableCellRenderer;
import java.awt.*;
public class BooleanCellRenderer implements TableCellRenderer, UIResource {
private final TableCellRenderer parent;
public BooleanCellRenderer(TableCellRenderer parent) {
this.parent = parent;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component c = parent.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
FileTable fileTable = (FileTable) table;
if (!isSelected) {
if (row == fileTable.getCursorRow()) {
c.setBackground(Color.pink);
c.setForeground(Color.darkGray);
} else {
c.setBackground(Color.white);
c.setForeground(Color.darkGray);
}
}
return c;
}
}
Then, in your main GUI class containing a JTable, take the table's default Boolean renderer and pass it to the wrapper:
FileTable fileTable = new FileTable();
fileTable.setDefaultRenderer(Boolean.class, new BooleanCellRenderer(fileTable.getDefaultRenderer(Boolean.class)));
You can leave the FileTableCellRenderer to render String cells:
FileTable fileTable = new FileTable();
fileTable.setDefaultRenderer(String.class, new FileTableCellRenderer());
fileTable.setDefaultRenderer(Boolean.class, new
Related
I want to make a JTable , where one single cell (not all rows of a column) will contain a JComponent like JdatePicker or JComboBox.
I have written this code
DefaultTableModel dm;
dm = new DefaultTableModel() {
public boolean isCellEditable(int rowIndex, int columnIndex) {
return !(columnIndex == 0); //make 0th column non-editable
}
};
Object [] columnHeaders=new Object[]{"Field", "Value"};
Object [][] data=new Object[][]{{"ID",""},{"Reg Year",""},{"Reg Date", ""}} ;
regFormTable.setModel(dm); //regFormTable is a Jtable object
I also have a class that implements TableCellrenderer:
public class datePickerCellRenderer extends JFrame implements TableCellRenderer{
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
this.add(new JDateChooser());
return this;
}
}
How can I use datePickerCellRenderer class to implement as I described. I tried a few ways. None of those worked.
[Using Netbeans GUI builder is there a way to do that?]
Plaese ask if any more code I need to add
I would like to make an editable table and then check the data to make sure its valid. Im not sure how to change the color of just one cell. I would like to get a cell, for example (0,0) and color the foreground to red. I have read the other posts on SO as well as Oracle about the custom ColorRenderer, but i just don't get how i would use this.
Thanks.
Say that the cell you would like to render with a different color represents a status (I'll take Rejected and Approved as examples). I'd then implement a method in my table model called getStatus(int row) which returns the status for any given row.
Then, when that is in place, I'd go about creating a cell renderer responsible for rendering the column which the cell belongs to. The cell renderer would be something in the lines of the below code.
public class StatusColumnCellRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int col) {
//Cells are by default rendered as a JLabel.
JLabel l = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, col);
//Get the status for the current row.
CustomTableModel tableModel = (CustomTableModel) table.getModel();
if (tableModel.getStatus(row) == CustomTableModel.APPROVED) {
l.setBackground(Color.GREEN);
} else {
l.setBackground(Color.RED);
}
//Return the JLabel which renders the cell.
return l;
}
Then, when the renderer is in place, simply "apply" the renderer to the table with the following piece of code:
Table.getColumnModel().getColumn(columnIndex).setCellRenderer(new StatusColumnCellRenderer());
With regard to making a cell editable, simply implement the isCellEditable(int rowIndex, int columnIndex) method in your table model. You also need to implement the method
setValueAt(Object value, int rowIndex, int columnIndex) if you would like to keep the value which the user provides (which i assume you do!).
I would like to make an editable table and then check the data to make sure its valid.
Another approach would be to edit the data before it is saved to the table model to prevent invalid data from being entered.
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableEdit extends JFrame
{
TableEdit()
{
JTable table = new JTable(5,5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollpane = new JScrollPane(table);
getContentPane().add(scrollpane);
// Use a custom editor
TableCellEditor fce = new FiveCharacterEditor();
table.setDefaultEditor(Object.class, fce);
}
class FiveCharacterEditor extends DefaultCellEditor
{
FiveCharacterEditor()
{
super( new JTextField() );
}
public boolean stopCellEditing()
{
try
{
String editingValue = (String)getCellEditorValue();
if(editingValue.length() != 5)
{
JTextField textField = (JTextField)getComponent();
textField.setBorder(new LineBorder(Color.red));
textField.selectAll();
textField.requestFocusInWindow();
JOptionPane.showMessageDialog(
null,
"Please enter string with 5 letters.",
"Alert!",JOptionPane.ERROR_MESSAGE);
return false;
}
}
catch(ClassCastException exception)
{
return false;
}
return super.stopCellEditing();
}
public Component getTableCellEditorComponent(
JTable table, Object value, boolean isSelected, int row, int column)
{
Component c = super.getTableCellEditorComponent(
table, value, isSelected, row, column);
((JComponent)c).setBorder(new LineBorder(Color.black));
return c;
}
}
public static void main(String [] args)
{
JFrame frame = new TableEdit();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo( null );
frame.setVisible(true);
}
}
I believe the correct way to do colouring in a table is via a ColorHighlighter. The table renderers have problems to render different colours in the same column.
Here is an example of how to use highlighters. In this case it is for highlighting a cell that is not editable.
public class IsCellEditablePredicate implements HighlightPredicate {
private JXTable table;
public IsCellEditablePredicate (final JXTable table) {
this.table = table;
}
#Override
public boolean isHighlighted(Component component, ComponentAdapter componentAdapter) {
return !table.isCellEditable(componentAdapter.row,
componentAdapter.column);
}
}
and then in your code for setuping the table you add the highlighter and its colour parameters:
ColorHighlighter grayHighlighter = new ColorHighlighter(new IsCellEditablePredicate(table));
grayHighlighter.setBackground(Color.LIGHT_GRAY);
grayHighlighter.setForeground(table.getForeground());
grayHighlighter.setSelectedBackground(table.getSelectionBackground().darker());
grayHighlighter.setSelectedForeground(table.getSelectionForeground().darker());
table.setHighlighters(grayHighlighter);
This is the simplest way to color a particular Column or cell in a jTable.
First just create a simple class of CustomRenderer
class CustomRenderer extends DefaultTableCellRenderer <br />
{
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);
setForeground(Color.blue); >
return c;
}
}
This code gets the column of cell to render
TableColumn col = tblExamHistoryAll.getColumnModel().getColumn(5);
DefaultTableModel model3 = (DefaultTableModel)tblExamHistoryAll.getModel();
col.setCellRenderer(new CustomRenderer());
This is to clear all previous rows from your table. If you do not want them just remove these lines
model3.getDataVector().removeAllElements();
model3.fireTableDataChanged();
#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);
int control = row;
control = control % 2;
control = (control == 0) ? 1 : 0;
if (control == 1) {
c.setBackground(Color.green);
} else {
c.setBackground(Color.cyan);
}
return c;
}
The most straightforward way is to write a simple TableCellRenderer by extending the DefaultTableCellRenderer and overwriting the getTableCellRendererComponent method to setBackground( Color.RED ). For example:
final JTable table = new JTable(...);
table.setCellRenderer( new DefaultTableCellRenderer() {
public Component getTableCellRenderer(JTable table, Object value, ...) {
super.getTableCellRenderer(...);
if ( value should be highlighted ) {
setBackground( Color.RED );
}
return this;
}
});
You can extend DefaultTableCellRenderer, override getTableCellRendererComponent and call something like
if (myConditions) setBackground(myColor);
before returning "this" when conditions apply but it has a very annoying side-effect of changing the default back-color due to the way DefaultTableCellRenderer.setBackGround is coded.
The trick I found was to entirely duplicate the code of DefaultTableCellRenderer in a class named HackedDefaultTableCellRenderer, add a method that calls directly the Component's setBackground implementation:
public void setComponentBackground(Color c) {
super.setBackground(c);
}
then derive my customized rendered from this hacked class instead of from DefaultTableCellRenderer, and finally call setComponentBackground instead of setBackground in my customized getTableCellRendererComponent.
The drawback is that this HackedDefaultTableCellRenderer relies on a snapshot of DefaultTableCellRenderer.
im using JXTable and trying to color the row based on value, BUT the show empty(but the render is running because it show the syso in console)
public class MyCellRenderer extends JLabel implements TableCellRenderer {
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
SimpleTableModel mymodel = (SimpleTableModel) jxtableListar.getModel();
ModelProtocolo actualModel= (ModelProtocolo ) mymodel.getProtocolo(rowIndex) ;
if(actualModel.getValue() > 0) {
System.out.println("Yep the Render is working");
}
return this;
}
}
jxtableListar.setDefaultRenderer(Object.class, new MyCellRenderer ());
i did not found any usefull "tutorial" how to use the JXTable renderer, since they talk about something about Hightlight, but all the tutorials are "out of information" to learn
is there any good way/tutorial to color a JXTable row base on a value of the cell?
Your renderer is returning a JLabel (itself) that hasn't had anything set on it. Instead, extend DefaultTableCellRenderer:
public class MyCellRenderer extends DefaultTableCellRenderer {
#override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int rowIndex, int vColIndex) {
SimpleTableModel mymodel = (SimpleTableModel) jxtableListar.getModel();
ModelProtocolo actualModel= (ModelProtocolo ) mymodel.getProtocolo(rowIndex) ;
JLabel label = (JLabel) super.getTableCellRendererComponent(/* pass in all params */);
label.setText(/*whatever the text should be*/);
label.setBackground(/*whatever the color should be*/);
return label;
}
}
I have a JTable with three columns in each row, see the image:
For some reason depending on the column i select i get the little dark blue border around it (V140116554) in the image above.
I currently use this to select the entire row:
vTable.setRowSelectionAllowed(true);
How can i disable this?
EDIT:
Added a class:
public class VisitorRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setBorder(noFocusBorder);
return this;
}
}
And added it:
vTable.setDefaultRenderer(String.class, new VisitorRenderer());
But still get the border
The TableCellRenderer is responsible for drawing the focus rectangle around the currently focused cell. You need to supply your own renderer that is capable of either overriding this feature or providing its own...
For example;
public class MyRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setBorder(noFocusBorder);
return this;
}
}
This uses the DefaultTableCellRenderer as the base renderer and sets the component's Border to noFocusBorder which is defined in DefaultTableCellRenderer as a EmptyBorder
You will then need to set this renderer as the default renderer for the effected columns. Check out How to use tables for more details
Update with example
Works fine for me...
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.LineBorder;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
public class TableRenderer {
public static void main(String[] args) {
new TableRenderer();
}
public TableRenderer() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
DefaultTableModel model = new DefaultTableModel(new Object[][]{{"", "One"}, {"", "Two"}}, new Object[]{"Check", "Vistor"}) {
#Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
};
JTable table = new JTable(model);
table.setRowSelectionAllowed(true);
table.setShowGrid(false);
table.setDefaultRenderer(String.class, new VisitorRenderer());
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.add(new JScrollPane(table));
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class VisitorRenderer extends DefaultTableCellRenderer {
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
setBorder(noFocusBorder);
return this;
}
}
}
And just to be sure, I changed setBorder(noFocusBorder); to...
if (hasFocus) {
setBorder(new LineBorder(Color.RED));
}
From the looks of things, the visitor column class type isn't being reported as String by the TableModel...
Updated with proxy renderer concept
Because you want to remove the focus border from every cell. You have three choices...
Write a custom cell renderer for every possibility of Class type you might need for your table. This can time consuming and repeats a lot of code to achieve only a small effect.
Do nothing a live with it...
Use a "proxy" renderer. This is a renderer that uses another TableCellRenderer to perform the actual rendering process, but applies some minor changes to the result, for example, remove the border...
...
public static class ProxyCellRenderer implements TableCellRenderer {
protected static final Border DEFAULT_BORDER = new EmptyBorder(1, 1, 1, 1);
private TableCellRenderer renderer;
public ProxyCellRenderer(TableCellRenderer renderer) {
this.renderer = renderer;
}
#Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
Component comp = renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
if (comp instanceof JComponent) {
((JComponent)comp).setBorder(DEFAULT_BORDER);
}
return comp;
}
}
Instead of doing something like...
table.setDefaultRenderer(String.class, new VisitorRenderer());
Which we did before, we would do this instead...
table.setDefaultRenderer(String.class,
new ProxyCellRenderer(table.getDefaultRenderer(String.class)));
This means we can take advantage of the what ever default renderer is already available without knowing what that might be, but also supply our own custom requirements to it...
Instead of creating your own TableCellRenderer you could also do:
#Override
public Component prepareRenderer(TableCellRenderer renderer, int row, int col) {
Component c = super.prepareRenderer(renderer, row, col);
if (c instanceof JComponent)
((JComponent)c).setBorder(new EmptyBorder(1, 1, 1, 1));
return c;
}
If you have absolutely no need for the border on any cell in that table, just apply MyRenderer to all cells, regardless of class. You can do it like this:
table.setDefaultRenderer(Object.class, new MyRenderer());
I have a JTable 5x5, and I want to write a procedure setColorTable(JTable table, int Row, int Col), when call Procedure setColorTable it will setBackground color for row and col in table. everyone can help me.
thank you so much.
You'll have to create a custom TableCellRenderer that extends a Swing Component (JLabel will probably suit your needs if you only want to change the colour), and implements the TableCellRenderer interface.
Try reading this or the JavaDoc
You can write your own class by extending javax.swing.table.DefaultTableCellRenderer and then overide the following method as you wish.
public class MyNewCellRenderer extends DefaultTableCellRenderer
{
#Override
public Component getTableCellRendererComponent(
JTable table, Object object,
boolean isSelected, boolean hasFocus,
int row, int column)
{
JLabel label = (JLabel) super.getTableCellRendererComponent(table, object, isSelected, hasFocus, row, column);
label.setBackground(Color.WHITE);
}
}
Finally atatch the TableCellRenderer by;
jTable1 = new javax.swing.JTable()
{
public TableCellRenderer getCellRenderer(int row, int column)
{
return new MyNewCellRenderer();
}
};
how to change color of rows in JTable
for coloring (Font, Foregroung, Backgroung, e.i.) whole row is there prepareRenderer