0

I am experimenting the possibility to replace the JTable header cell (JLabel) with a JPanel. The reasoning is to have a more flexible container to place other header related stuff, i.e., multicolumn sorting indicators. Putting a panel is straight-forward however maintaining the LAF seems like the hassle.

My attempt was to override the header renderer and pack the content in a JPanel. It works but the default LAF is gone as expected.

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;

import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellRenderer;

public class JTableHeaderExperimental {

    static class XTableHeaderCellRenderer extends DefaultTableCellRenderer{
        private TableCellRenderer defaultRenderer;

        public XTableHeaderCellRenderer(TableCellRenderer defaultRenderer) {
            this.defaultRenderer = defaultRenderer;
        }

        @Override
        public Component getTableCellRendererComponent(JTable table,
                Object value, boolean isSelected, boolean hasFocus, int row,
                int column) {
            super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            // For the simplicity, skipping sorting icon related stuff
            GridBagConstraints constraints = new GridBagConstraints();
            JPanel panel = new JPanel(new GridBagLayout());
            JLabel extraLabel = new JLabel("Extra label");
            JLabel originalLabel = (JLabel) defaultRenderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);

            constraints.fill = GridBagConstraints.HORIZONTAL;
            constraints.gridx = 0;
            constraints.gridy = 0;
            panel.add(extraLabel, constraints);

            constraints.gridx = 0;
            constraints.gridy = 1;
            panel.add(this, constraints);

            System.out.println("Original Header Border: " + originalLabel.getBorder().getClass());
            System.out.println("New Header Border: " + this.getBorder().getClass());
            System.out.println("Header Panel Border: " + panel.getBorder().getClass());

            return panel;
        }
    }

    public static void main(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (ClassNotFoundException | InstantiationException
                | IllegalAccessException | UnsupportedLookAndFeelException e) {
            e.printStackTrace();
        }

        Object[][] data = {
                {"Test", "Data"},
                {"Comes", "Here"}               
        };
        String[] columnNames = {"Header 1", "Header 2"};
        JFrame frame = new JFrame();
        JTable table = new JTable();

        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        DefaultTableModel model = new DefaultTableModel(data, columnNames);
        table.setModel(model);
        table.getTableHeader().setDefaultRenderer(new XTableHeaderCellRenderer(table.getTableHeader().getDefaultRenderer()));
        frame.setSize(200, 200);

        frame.add(new JScrollPane(table));
        frame.setVisible(true);

    }
}

Running this code gives the output:

Original Header Border: class javax.swing.plaf.synth.SynthBorder
New Header Border: class javax.swing.border.EmptyBorder
Header Panel Border: class javax.swing.plaf.synth.SynthBorder

and renders:

enter image description here

as opposed to the default system LAF:

enter image description here

I was wondering if it is possible to create a panel and pass the LAF details (i.e., border, bg/fg colors) of the original label.

amertkara
  • 1,369
  • 14
  • 19
  • You may get some ideas from this [Q&A](http://stackoverflow.com/q/7137786/230513). – trashgod May 06 '15 at 15:35
  • @trashgod I know about that one, especially the accepted answer's Technical aspects/3rd bullet point makes it clear. But I was wondering if anyone had a go at it. – amertkara May 06 '15 at 15:40
  • Any luck with luca's `MouseAdapter`? – trashgod May 06 '15 at 15:45
  • @trashgod the implementation seems beyond using an adapter, I have almost got there, just some minor tweaks. I will post the full implementation once it is stable/tidy enough. It involved migrating some Swing.Synth classes to my local SwingX codebase (due to overuse of package local static methods). Also, I needed to get the JPanel use Region.Button once it gets painted (Since the original background is painted with Region.Button). – amertkara May 22 '15 at 17:19

0 Answers0