JTable column header custom renderer examples
- Details
- Written by Nam Ha Minh
- Last Updated on 06 July 2019   |   Print Email
This article shows how to create custom renderers for column headers in a JTable. Here’s a couple of examples of JTable with its column headers customized:
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.
1. A simple custom renderer for all column headers
This example shows how to create a custom renderer and apply it for all column headers of a JTable.
Code of the renderer class, SimpleHeaderRenderer.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 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:
2. Multi custom renderers for different column headers
This example shows how to create and apply different renderers for different column headers, for these table headers:
We are going to create a default render for all headers and three different renderers for the three columns “Won”, “Drawn”, and “Lost”.
Code of the default renderer class, DefaultHeaderRenderer.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 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:
3. Keeping sort icons
One problem with the custom renderer for column header is that the sort icons (e.g. ascending and descending icons) are lost, even the sorting functionality is still working fine. To overcome this problem, create a renderer class as follows:
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:
- For all column headers:
JTableHeader header = table.getTableHeader(); header.setDefaultRenderer(new KeepSortIconHeaderRenderer(header.getDefaultRenderer()));
Output: - For a specific column header:
TableColumn column = table.getColumnModel().getColumn(2); column.setHeaderRenderer(new KeepSortIconHeaderRenderer(table.getTableHeader().getDefaultRenderer()));
Output:
You can download demo programs in the Attachments section.
Related JTable Tutorials:
- A Simple JTable Example for Display
- Editable JTable Example
- JTable Simple Renderer Example
- 6 Techniques for Sorting JTable You Should Know
- How to scroll JTable row to visible area programmatically
- JTable popup menu example
- Setting column width and row height for JTable
- How to handle mouse clicking event on JTable column header
- How to create JComboBox cell editor for JTable
Comments
Can you please help me into this