0

I'm have a custom table header renderer that will have the standard label and a button inside a JComponent.

The issue I'm having is with the label returned by the default renderer. The call to the default renderer provides the standard label. If I return that as is, it looks as expected. If I try to modify the background or border nothing changes. Modifying the foreground does have the intended effect, however. I do not want to view the sort icons, so I'm attempting to construct a JLabel that looks the same, minus the icons. That is not working correctly either. My JLabel is opaque.

JLabel l = (JLabel)table.getTableHeader().getDefaultRenderer().getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
this.lbl.setBackground(l.getBackground());
return this.lbl;

I looked at the source for DefaultTableHeaderRenderer and I can't find anything special that the default class is doing.

I've also tried the following with no effect.

this.lbl.setOpaque(true);
this.lbl.setFont(UIManager.getFont("TableHeader.font"));
this.lbl.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
this.lbl.setBackground(UIManager.getColor("TableHeader.background"));
this.lbl.setForeground(UIManager.getColor("TableHeader.foreground"));
return this.lbl;

EDIT: Clarification. Both code snippets above are inside getTableCellRenderComponent() of my custom renderer. I've tried both ways and neither has worked.

mKorbel
  • 109,525
  • 20
  • 134
  • 319
Dodd10x
  • 3,344
  • 1
  • 18
  • 27
  • 1
    You shouldn't be trying yo modify the header outside of its rendering process. Instead you should providing your own implementation of the `TableCellRenderer` that provides the functionality you require and setting it the `JTableHeader` – MadProgrammer Apr 12 '13 at 04:05
  • Edited for clarification. I am doing this inside a custom TableCellEditor implementation. – Dodd10x Apr 12 '13 at 04:13
  • Then why are you doing `table.getTableHeader().getDefaultRenderer()`? – MadProgrammer Apr 12 '13 at 04:18
  • I was attempting to get the default label for the current look and feel in order to get it's properties such as background and border to use in my own component. It's not working as I would expect. – Dodd10x Apr 12 '13 at 04:25

1 Answers1

1

Try using the UIManagers values directly.

TableHeader.background = DerivedColor(color=214,217,223 parent=control offsets=0.0,0.0,0.0,0 pColor=214,217,223
TableHeader.font = javax.swing.plaf.FontUIResource[family=SansSerif,name=sansserif,style=plain,size=12]
TableHeader.foreground = DerivedColor(color=0,0,0 parent=text offsets=0.0,0.0,0.0,0 pColor=0,0,0
TableHeader.opaque = true

Something like UIManager.getColor("TableHeader.background") for example

The border I think you'll find is actually painted by the UI delegate directly.

Updated with example

enter image description here

From the included image, it's obvious that using UIManager does provide some of the basic information need to get the values used by the header, but it does highlight that the renderer is doing some special painting to get the shading.

The second column is the default renderer and the third is cheeky. It is basically stealing the cell renderer directly from the table header...

package testcellrenderer;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Font;
import javax.swing.JFrame;
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;

public class TestCellRenderer {

    public static void main(String[] args) {
        new TestCellRenderer();
    }

    public TestCellRenderer() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel("com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel");
                } catch (ClassNotFoundException ex) {
                } catch (InstantiationException ex) {
                } catch (IllegalAccessException ex) {
                } catch (UnsupportedLookAndFeelException ex) {
                }

                JFrame frame = new JFrame("Test");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new TestPane());
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);
            }
        });
    }

    public class TestPane extends JPanel {

        public TestPane() {
            DefaultTableModel model = new DefaultTableModel(
                            new Object[][]{{"Testing", "Testing", "Testing"}},
                            new Object[]{"Test A", "Test B", "Test C"}
                            );
            JTable table = new JTable(model);
            table.getColumn("Test A").setCellRenderer(new TestTableCellRenderer());
            table.getColumn("Test C").setCellRenderer(table.getTableHeader().getDefaultRenderer());

            setLayout(new BorderLayout());
            add(new JScrollPane(table));
        }

    }

    protected class TestTableCellRenderer 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); 

            Color background = UIManager.getColor("TableHeader.background");
            Color foreground = UIManager.getColor("TableHeader.foreground");
            Font font = UIManager.getFont("TableHeader.font");
            boolean opaque = UIManager.getBoolean("TableHeader.opaque");

            setBackground(background);
            setForeground(foreground);
            setFont(font);
            setOpaque(opaque);

            return this;
        }       
    }   
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • Renderers concept works for Nimbus without restriction, but not for JTableHeader, personally never tried, one of code by @kleopatra (again in power_save_mode) – mKorbel Apr 12 '13 at 07:23
  • @MadProgrammer For what its worth (coming in late to this conversation), but I'm unable to get the background of the header cells to paint via a gradient colors scheme. I have a custom renderer which is using the DefaultTableCellHeaderRenderer class' code (copy/pasted to test), and I add that renderer as the default header renderer to my table, and what happens is that the border does not paint (unless I had my own setBorder call in my renderer), and the background of the column header cells is painted flat, not with a gradient. – Adrian Romanelli Mar 08 '16 at 20:47
  • @MadProgrammer --laf com.sun.java.swing.plaf.nimbus.NimbusLookAndFeel – Adrian Romanelli Mar 08 '16 at 22:54
  • @AdrianRomanelli Are you trying to modify the renderer for the cell or the header? As I stated in the answer, the border seems to be painted by the l&f delegate itself – MadProgrammer Mar 08 '16 at 23:42
  • @MadProgrammer The only modification I do in my renderer is to change the icon for sorting for each column header cell, not table body cells (we allow filtering, and show a separate icon for a filtered column). As far as the border goes, as I mentioned previously, no border is painted at all, unless I explicitly paint one myself. Also, the background color is not a gradient color, but a plain/flat color, unlike other tables that do not use my table header. – Adrian Romanelli Mar 09 '16 at 16:01