A JTable with all column headers customized with a same renderer
A JTable with multi renderers for different column headers
Basically we create a custom renderer by writing a class that implements the TableCellRender interface and extends a Swing component (e.g. JLabel) like this:public class SimpleHeaderRenderer extends JLabel implements TableCellRenderer { public SimpleHeaderRenderer() { // code to initilize the GUI... } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { // code to customize the GUI based on the parameters return this; } }Then we set this renderer for all column headers in the table like this:
table.getTableHeader().setDefaultRenderer(new SimpleHeaderRenderer());Or set this renderer for a specific column, e.g. the 3rd column in this example:
table.getColumnModel().getColumn(2).setHeaderRenderer(new SimpleHeaderRenderer());Now let’s see how to create tables with custom renderers that look like the above screenshots.
package net.codejava.swing.jtable; import java.awt.Color; import java.awt.Component; import java.awt.Font; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; /** * A simple renderer class for JTable component. * @author www.codejava.net * */ public class SimpleHeaderRenderer extends JLabel implements TableCellRenderer { public SimpleHeaderRenderer() { setFont(new Font("Consolas", Font.BOLD, 14)); setForeground(Color.BLUE); setBorder(BorderFactory.createEtchedBorder()); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value.toString()); return this; } }Code of a demo program, JTableHeaderRendererSimple.java:
package net.codejava.swing.jtable; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; /** * A Swing program demonstrates how to use a custom renderer for * all column headers of a JTable component. * @author www.codejava.net * */ public class JTableHeaderRendererSimple extends JFrame { private JTable table; public JTableHeaderRendererSimple(){ super("JTable Column Header Custom Renderer Basic"); // constructs the table String[] columnNames = new String[] {"Title", "Author", "Publisher", "Published Date", "Pages", "Rating"}; String[][] rowData = new String[][] { {"Effective Java", "Joshua Bloch", "Addision-Wesley", "May 08th 2008", "346", "5"}, {"Thinking in Java", "Bruce Eckel", "Prentice Hall", "Feb 26th 2006", "1150", "4"}, {"Head First Java", "Kathy Sierra & Bert Bates", "O'Reilly Media", "Feb 09th 2005", "688", "4.5"}, }; table = new JTable(rowData, columnNames); table.getTableHeader().setDefaultRenderer(new SimpleHeaderRenderer()); add(new JScrollPane(table)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(640, 150); setLocationRelativeTo(null); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new JTableHeaderRendererSimple().setVisible(true); } }); } }Output when running the demo program:
package net.codejava.swing.jtable; import java.awt.Color; import java.awt.Component; import java.awt.Font; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; /** * A simple renderer class for JTable component. * @author www.codejava.net * */ public class DefaultHeaderRenderer extends JLabel implements TableCellRenderer { public DefaultHeaderRenderer() { setFont(new Font("Consolas", Font.BOLD, 14)); setOpaque(true); setForeground(Color.WHITE); setBackground(Color.BLACK); setBorder(BorderFactory.createEtchedBorder()); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value.toString()); return this; } }Code of the renderer class for the “Won” column header, WonHeaderRenderer.java:
package net.codejava.swing.jtable; import java.awt.Color; import java.awt.Component; import java.awt.Font; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; /** * A simple renderer class for JTable component. * @author www.codejava.net * */ public class WonHeaderRenderer extends JLabel implements TableCellRenderer { public WonHeaderRenderer() { setFont(new Font("Consolas", Font.BOLD, 14)); setOpaque(true); setForeground(Color.WHITE); setBackground(Color.BLUE); setBorder(BorderFactory.createEtchedBorder()); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value.toString()); return this; } }Code of the renderer class for the “Drawn” column header, DrawnHeaderRenderer.java:
package net.codejava.swing.jtable; import java.awt.Color; import java.awt.Component; import java.awt.Font; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; /** * A simple renderer class for JTable component. * @author www.codejava.net * */ public class DrawnHeaderRenderer extends JLabel implements TableCellRenderer { public DrawnHeaderRenderer() { setFont(new Font("Consolas", Font.BOLD, 14)); setOpaque(true); setForeground(Color.BLACK); setBackground(Color.YELLOW); setBorder(BorderFactory.createEtchedBorder()); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value.toString()); return this; } }Code of the renderer class for the “Lost” column header, LostHeaderRenderer.java:
package net.codejava.swing.jtable; import java.awt.Color; import java.awt.Component; import java.awt.Font; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; /** * A simple renderer class for JTable component. * @author www.codejava.net * */ public class LostHeaderRenderer extends JLabel implements TableCellRenderer { public LostHeaderRenderer() { setFont(new Font("Consolas", Font.BOLD, 14)); setOpaque(true); setForeground(Color.WHITE); setBackground(Color.GRAY); setBorder(BorderFactory.createEtchedBorder()); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value.toString()); return this; } }Code of a demo program, JTableHeaderMultiRenderers.java:
package net.codejava.swing.jtable; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; /** * A Swing program demonstrates how to use multi custom renderers for * column headers of a JTable component. * @author www.codejava.net * */ public class JTableHeaderMultiRenderers extends JFrame { private JTable table; public JTableHeaderMultiRenderers() { super("JTable Column Header Multi Custom Renderers"); // constructs the table String[] columnNames = new String[] {"Position", "Team", "Won", "Drawn", "Lost", "Points"}; String[][] rowData = new String[][] { {"1", "Manchester United", "28", "5", "5", "89"}, {"2", "Manchester City", "23", "9", "6", "78"}, {"3", "Chelsea", "22", "9", "7", "75"}, {"4", "Arsenal", "21", "10", "7", "73"}, }; table = new JTable(rowData, columnNames); table.getTableHeader().setDefaultRenderer(new DefaultHeaderRenderer()); table.getColumnModel().getColumn(2).setHeaderRenderer(new WonHeaderRenderer()); table.getColumnModel().getColumn(3).setHeaderRenderer(new DrawnHeaderRenderer()); table.getColumnModel().getColumn(4).setHeaderRenderer(new LostHeaderRenderer()); add(new JScrollPane(table)); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setSize(640, 150); setLocationRelativeTo(null); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new JTableHeaderMultiRenderers().setVisible(true); } }); } }Output when running the demo program:
package net.codejava.swing.jtable; import java.awt.Color; import java.awt.Component; import java.awt.Font; import javax.swing.BorderFactory; import javax.swing.JLabel; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; /** * A simple renderer class for JTable component, but keep the sort icons. * @author www.codejava.net * */ public class KeepSortIconHeaderRenderer implements TableCellRenderer { private TableCellRenderer defaultRenderer; public KeepSortIconHeaderRenderer(TableCellRenderer defaultRenderer) { this.defaultRenderer = defaultRenderer; } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component comp = defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); if (comp instanceof JLabel) { JLabel label = (JLabel) comp; label.setFont(new Font("Consolas", Font.BOLD, 14)); label.setForeground(Color.BLUE); label.setBorder(BorderFactory.createEtchedBorder()); } return comp; } }The trick here is to update the default renderer (which is usually a JLabel instance) instead of returning a completely new JLabel component. Code to use this renderer is as follows:
JTableHeader header = table.getTableHeader(); header.setDefaultRenderer(new KeepSortIconHeaderRenderer(header.getDefaultRenderer()));
TableColumn column = table.getColumnModel().getColumn(2); column.setHeaderRenderer(new KeepSortIconHeaderRenderer(table.getTableHeader().getDefaultRenderer()));