Custom TableCellRenderer not working (table row rendering) - java

I'm trying to render an specific row of my jtable (it should have a different background color and it should have bold characters).
I found several questions regarding how to implement a custom TableCellRenderer (here and here) and the tutorial How to Use Tables and this one (Table Row Rendering).
I'm using a JInternalFrame to display the JTable. I tried to implement both solutions but neither getCellRenderer nor prepareRenderer are being called. When debugging, I can see my new jtable being created, but, my breakpoint inside the methods aren't called.
My code looks like:
this.add(createData(model));
private JComponent createData(ProfitLossTableModel model) {
JTable table = new JTable(model) {
public TableCellRenderer getCellRenderer(int row, int column) {
if ((row == 0) && (column == 0)) {
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer();
renderer.setHorizontalAlignment(JLabel.RIGHT);
renderer.setBackground(Color.red);
return renderer;
} else {
return super.getCellRenderer(row, column);
}
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.changeSelection(0, 0, false, false);
table.setAutoCreateRowSorter(true);
return new JScrollPane(table);
}
As you can see, model is my implementation of a AbstractTableModel.
Of course that I'm missing something. I tried to call repaint() to see if something happened, but nothing occurred.
I also tried to put a JPane inside my JInternalFrame and them add the JScrollPane into it, but nothing occurred also.
Any help?
TIA,
Bob

As discussed in Concepts: Editors and Renderers, "the table invokes the table model's getColumnClass method, which gets the data type of the column's cells." You should verify that your implementation of AbstractTableModel returns a suitable value, as suggested in this example.
Addendum:
I'm trying to render a row, not a column.
Rob Camick's Table Row Rendering approach that overrides prepareRenderer() seems apropos.
tabbedPane.addTab("FirstRow", createFirstRow(model));
...
private JComponent createFirstRow(DefaultTableModel model) {
final Font font = new Font("Serif", Font.BOLD, 14);
JTable table = new JTable(model) {
public Component prepareRenderer(
TableCellRenderer renderer, int row, int column) {
Component c = super.prepareRenderer(renderer, row, column);
if (!isRowSelected(row)) {
c.setBackground(row == 0 ? Color.yellow: getBackground());
c.setFont(row == 0 ? font : getFont());
}
return c;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
table.changeSelection(1, 1, false, false);
return new JScrollPane(table);
}

Related

Table Renderer not working correctly in Java

I read a lot of articles and finally got my JTable rendering as per my requirements but the problem is when the table is scrolled by user, some of the other hidden parts of jtable are also colored as shown in image below
And when the user scrolls the table, other parts are also got colored like this
Why this happens? I read many articles and and all of them show exactly the same thing but this...
Here is my code
JTable table = new JTable()
{
public boolean isCellEditable(int rowIndex, int colIndex)
{
return false;
}
};
(DefaultTableCellRenderer)table.getTableHeader().getDefaultRenderer())
.setHorizontalAlignment(JLabel.CENTER);
table.setModel(new DefaultTableModel(new Object [][] {}, Columns));
table.setRowHeight(25);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().removeColumn(table.getColumnModel().getColumn(0));
table.setDefaultRenderer(Object.class, new 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);
if(!table.getModel().getValueAt(row, 10).toString().equals("true"))
{
setBackground(new Color(246,137,137));
}
return this;
}
});
JScrollPane areaScrollPane = new JScrollPane(table);
areaScrollPane.setPreferredSize(new Dimension(width, height));
MyPanel.add(areaScrollPane);
All the articles show this way to render custom row on condition base. What's wrong in my code? Thanks for any support.
if(!table.getModel().getValueAt(row, 10).toString().equals("true"))
{
setBackground(new Color(246,137,137));
}
The same renderer is used for all cells so once you set the background it will apply for all cells. So, I think you need something like:
if(!table.getModel().getValueAt(row, 10).toString().equals("true"))
{
setBackground(new Color(246,137,137));
}
else
setBackground( table.getBackground() );
You should also add code to make sure the cell is not selected so that the default selection color can be painted.
Instead of using a custom renderer you can also override the prepareRenderer(...) method of JTable. Table Row Rendering show how you can render a row based on a value in that row.

Java How to disable the JTable editable when click it

public class AdminControlPanel extends javax.swing.JFrame
I'm using the JFrame class...so it will automatically inherit the JFrame class...
But problem now is I want to disable the cell editing in the JTable...How to do it even I'm not inherit the AbstractTableModel???
If you want to use a custom table model:
//instance table model
DefaultTableModel tableModel = new DefaultTableModel() {
#Override
public boolean isCellEditable(int row, int column) {
return false; // or a condition at your choice with row and column
}
};
table.setModel(tableModel);
Or in a quick and dirty way:
table.setEnabled(false);
This second approach is inconsistent with some L&F (it looks grayed out).

JTable all column aligned right

Is there a way to align all the column in jtable at the same time?
using this:
DefaultTableCellRenderer rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment( JLabel.RIGHT );
JTAB_TABLE.getColumnModel().getColumn(0).setCellRenderer( rightRenderer );
will let me align only one column but i need to align all.
Normally, a table contains different kinds of data, (Date, Number, Boolean, String) and it doesn't make sense to force all types of data to be right aligned.
If however you have a table with all the same type of data and you want to force the renderering of all columns to be the same, then you should probably use the same renderer. Assuming you are using the default renderer you can use:
DefaultTableCellRenderer renderer = (DefaultTableCellRenderer)table.getDefaultRenderer(Object.class);
renderer.setHorizontalAlignment( JLabel.RIGHT );
You can do so by overriding prepareRenderer(...) in JTable. This assumes that any custom renderers are JLabels (they're JLabels by default). You'd have to guard against it otherwise.
import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;
public class TableDemo implements Runnable
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new TableDemo());
}
public void run()
{
JTable table = new JTable(5, 5)
{
#Override
public Component prepareRenderer(TableCellRenderer renderer,
int row, int col)
{
Component comp = super.prepareRenderer(renderer, row, col);
((JLabel) comp).setHorizontalAlignment(JLabel.RIGHT);
return comp;
}
};
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
JFrame frame = new JFrame();
frame.getContentPane().add(scrollPane);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}

JTable change Column Font

I'm making a table where I want to make the first column with a higher Font Size.
For example in column 0 I want Font size of 30 and on columns 1-3 y want Font size of 13.
Here's my code
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import java.io.*;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.*;
public class kanji_list extends JFrame {
kanji_list(){
JTable table = new JTable();
JScrollPane scroll = new JScrollPane();
Image icon = Toolkit.getDefaultToolkit().getImage("JLPT.jpg");
ImageIcon ima = new ImageIcon("JLPT.jpg");
DefaultTableModel model = new DefaultTableModel(get_data(), get_header());
table = new JTable(model){
public boolean isCellEditable(int rowIndex, int vColIndex){
return false;
}
};
JTableHeader th = table.getTableHeader();
TableColumnModel tcm = th.getColumnModel();
TableColumn column = null;
table.setFont(new Font("Microsoft JhengHei", Font.BOLD, 13));
for (int i = 0; i < 4; i++) {
column = table.getColumnModel().getColumn(i);
DefaultTableCellRenderer tcr = new DefaultTableCellRenderer();
tcr.setHorizontalAlignment(SwingConstants.CENTER);
column.setCellRenderer(tcr);
if (i==0) {
column.setPreferredWidth(50);
}
else{
if(i==1){
column.setPreferredWidth(175);
}
else{
if(i==2){
column.setPreferredWidth(200);
}
else{
column.setPreferredWidth(875);
}
}
}
}
table.setRowHeight(table.getRowHeight()+30);
table.setModel(model);
scroll.add(table);
this.add(scroll);
this.setTitle("Katakana");
this.setSize(1350, 700);
this.setIconImage(icon);
this.setVisible(true);
this.setLocationRelativeTo(null);
scroll.setViewportView(table);
}
Object [][]get_data(){
Object data[][] = new Object[][]{
{"\u4e00", "Uno, 1", "ICHI, ITSU", "hito-, hitotsu"},
{"\u4e8c", "Dos, 2", "NI, JI", "futa, futatsu, futatabi"},
{"\u4e09", "Tres, 3", "SAN, JOU", "mi, mitsu, mittsu"},
{"\u99c5", "EstaciĆ³n", "EKI", ""}
};
return data;
}
String []get_header(){
String header [] = new String[]{"KANJI", "SIGNIFICADO", "LECTURA ON", "LECTURA KUN"};
return header;
}
}
This is a Japanese learning system, and Kanjis on unicode on 1st column aren't visible at all with my 13 size font, but if I make all the table on a higher size, all the other columns get bigger and it doesn't looks fine.
In core JTable you basically need a custom renderer which sets the Font to something different from the table's font, f.i. in a subclass of DefaultTableCellRenderer. Note that setting the font on DefaultTableCellRenderer once after instantiation won't work because it's reset on each call to getTableCellRendererComponent.
JTable table = new JTable(new AncientSwingTeam());
// the default renderer uses the table's font,
// so set it as appropriate
table.setFont(fontToUseForAllColumnsExceptFirst);
// a custom renderer which uses a special font
DefaultTableCellRenderer r = new DefaultTableCellRenderer() {
Font font = fontToUseForFirstColumn;
#Override
public Component getTableCellRendererComponent(JTable table,
Object value, boolean isSelected, boolean hasFocus,
int row, int column) {
super.getTableCellRendererComponent(table, value, isSelected, hasFocus,
row, column);
setFont(font);
return this;
}
};
// doesn't work because the default renderer's font is reset
// to the table's font always
// r.setFont(font);
// set the custom renderer for first column
table.getColumnModel().getColumn(0).setCellRenderer(r);
An alternative is the renderer decoration approach, supported in the SwingX project (biased me can't resist :-) Then the above would be a two-liner (assuming table is of type JXTable):
Highlighter hl = new FontHighlighter(font);
table.getColumnExt(0).setHighlighter(hl);

Adding Buttons inside cell of JTable along with data?

Is it possible to add buttons inside the JTable cell along with data?
What I am trying to do is to create a table with columns which display data(number) from the database, and two buttons to increase/decrease the number inside the same cell.
|ID | Quantity|
|06| 2 [+][-] |
it would be something like above with [+][-] being buttons. So when I press [+], the number will change to 3 and 1 if pressing [-].
Yes, it is possible, although It won't be easy.
You have to write your own custom cell renderer and your own cell editor.
This is a sample I made in 5 minutes:
It is far from perfect, but shows the concept.
Here's the source code:
import java.awt.Component;
import java.awt.Font;
import javax.swing.*;
import javax.swing.table.*;
import java.awt.Dimension;
public class CustomCell {
public static void main( String [] args ) {
Object [] columnNames = new Object[]{ "Id", "Quantity" };
Object [][] data = new Object[][]{ {"06", 1}, {"08", 2} };
JTable table = new JTable( data, columnNames ) {
public TableCellRenderer getCellRenderer( int row, int column ) {
return new PlusMinusCellRenderer();
}
};
table.setRowHeight( 32 );
showFrame( table );
}
private static void showFrame( JTable table ) {
JFrame f = new JFrame("Custom Cell Renderer sample" );
f.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
f.add( new JScrollPane( table ) );
f.pack();
f.setVisible( true );
}
}
class PlusMinusCellRenderer extends JPanel implements TableCellRenderer {
public Component getTableCellRendererComponent(
final JTable table, Object value,
boolean isSelected, boolean hasFocus,
int row, int column) {
this.add( new JTextField( value.toString() ) );
this.add( new JButton("+"));
this.add( new JButton("-"));
return this;
}
}
Here's a thread that may be interesting and here.
As discussed in the tutorial you'll need both a renderer to display your value and an editor to detect events from the cell being edited. In this example, the Component is a JCheckBox. Note that this requires a custom DataModel that extends AbstractTableModel to supply the correct Class for a given column. Joonas' suggestion to use JSpinner is a good one that works well.
I think you need to create a custom cell renderer if you want to show anything else than text (or numbers) in the cell. The cell renderer's job is to paint whatever you need to show in the cell.
See Table Renderer documentation.
So in this case you could create a small JPane which contains the text field and the tiny + and - buttons - or a just a JSpinner component, if does what you need. A bit tricky, for sure, but should be possible.

Categories