I want to recreate a table header looks using JLabel
. The look and feel of the JLabel
needs to be exactly like the JTableHeader
would
There are more issues involved then just getting the color and border of the table header. Each cell/column is rendered by a TableCellRenderer
meaning that the values return by the UIManager
may be ignored...
For example, the following renders the JTableHeader
and applies border/background to a JLabel
based on values returned by the UIManager
under the Window's Look and Feel...
As you can see, there's quite a difference between them
How ever, if all you're interested in is display a "group header" of some kind over the top of another component on a scroll pane, you could simply add a JTableHeader
to the scroll panes column view directly...
public class TestHeader {
public static void main(String[] args) {
new TestHeader();
}
public TestHeader() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
TableColumnModel model = new DefaultTableColumnModel();
final TableColumn column = new TableColumn(0, 250);
column.setHeaderValue("Test");
model.addColumn(column);
JTableHeader header = new JTableHeader();
header.setColumnModel(model);
final JTextArea textArea = new JTextArea();
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setColumnHeaderView(header);
textArea.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
column.setWidth(textArea.getWidth());
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
UPDATED
public class TestHeader {
public static void main(String[] args) {
new TestHeader();
}
public TestHeader() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException ex) {
} catch (InstantiationException ex) {
} catch (IllegalAccessException ex) {
} catch (UnsupportedLookAndFeelException ex) {
}
TableColumnModel model = new DefaultTableColumnModel();
final TableColumn column = new TableColumn(0, 250);
column.setHeaderValue("I don't see the problem");
model.addColumn(column);
final JTableHeader header = new JTableHeader();
header.setColumnModel(model);
DefaultTableModel tm = new DefaultTableModel(new Object[]{"A", "B", "C"}, 0);
tm.addRow(new Object[]{"1", "2", "3", "4"});
tm.addRow(new Object[]{"5", "6", "7", "8"});
tm.addRow(new Object[]{"9", "10", "11", "12"});
tm.addRow(new Object[]{"13", "14", "15", "16"});
final JTable table = new JTable(tm);
final JScrollPane scrollPane = new JScrollPane(table);
/**
* For some reason, the header isn't being applied as soon as the
* table is added to the scroll pane, so we need to jump our next
* request to the end of the of event queue so that it will
* occur some time in the future
*/
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
scrollPane.setColumnHeaderView(header);
}
});
table.addComponentListener(new ComponentAdapter() {
@Override
public void componentResized(ComponentEvent e) {
column.setWidth(table.getWidth());
}
});
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(scrollPane);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
}
Try taking the defaults from UIManager
:
Color color = UIManager.getColor("TableHeader.background");
Border border = UIManager.getBorder("TableHeader.CellBorder");
I figured I'll create a JTable
without any rows and place a JTextPane
right underneath.
And it works like charm.
JTextPane textPane = new JTextPane();
JPanel panel = new JPanel(new BorderLayout());
JTable table = new JTable(0, 1);
table.setPreferredScrollableViewportSize(new Dimension(600, 0));
JScrollPane js = new JScrollPane(table)
panel.add(js, BorderLayout.NORTH);
panel.add(new JScrollPane(textPane),BorderLayout.CENTER);
You need to set a look and feel for the application before trying:
header.setBackground(UIManager.getColor(new JTableHeader().getBackground()));
header.setBorder(UIManager.getBorder(new JTableHeader().getBorder()));
you should set a look and feel first like so:
try {
for (LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (Exception e) {
// If Nimbus is not available, you can set the GUI to another look and feel.
}
Here is an example:
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.table.JTableHeader;
public class Test {
public Test() {
initComponents();
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
//set nimbus look and feel
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Nimbus".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException e) {
e.printStackTrace();
}
new Test();
}
});
}
private void initComponents() {
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JLabel header = new JLabel("Title");
header.setBackground(UIManager.getColor(new JTableHeader().getBackground()));
header.setBorder(UIManager.getBorder(new JTableHeader().getBorder()));
frame.add(header);
frame.pack();
frame.setVisible(true);
}
}