JTable Row Header Look And Feel

I am trying to create row headers for my JTable. Here I spent here and here , but there is almost nothing there. What I found did not make the system look like this.

This is what I have found so far:

enter image description here

The first column (the one with no name) is the best I could achieve. I took a table header handler and applied it in a row cell. This partly worked. As you can see, the small arrow icon for descending / ascending sorting appears in each cell of the column, and the cell is now gray. In addition, this is a complete failure. In addition, I do not want the arrow icon in the row headers.

Col 1 is what happened when I tried to apply the UIManager look. Obviously, this did not work.

Col 2 is photoshop , this is what I'm trying to do.

I did nothing for the second column, so its default setting.

Question: How can I give the appearance of the system (and not just the window) title of the default table table for a row cell to create a row heading and, of course, a small arrow icon.

Here is the code

import java.awt.Component; import java.awt.Dimension; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.UIManager; import javax.swing.table.DefaultTableColumnModel; import javax.swing.table.DefaultTableModel; import javax.swing.table.JTableHeader; import javax.swing.table.TableCellRenderer; import javax.swing.table.TableColumnModel; import sun.swing.table.DefaultTableCellHeaderRenderer; public class RowHeaderTest extends JFrame { public RowHeaderTest() { initComponents(); } private void initComponents() { setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE); JScrollPane scrollPane = new JScrollPane(); JTable table = new JTable(); table.setAutoCreateRowSorter(true); table.getTableHeader().setReorderingAllowed(false); table.setModel(new DefaultTableModel( new Object[][] { { "Row 1", "Data 2", "Data 3", "Data 4", "Data 5" }, { "Row 2", "Data 6", "Data 7", "Data 8", "Data 9" }, { "Row 3", "Data 10", "Data 11", "Data 12", "Data 13" } }, new String[] { "", "Col 1", "Col 2", "Col 3", "Col 4" })); table.getColumnModel().getColumn(0).setHeaderRenderer(HeaderRenderer.THIS); table.getColumnModel().getColumn(0).setCellRenderer(HeaderRenderer.THIS); table.getColumnModel().getColumn(1).setHeaderRenderer(HeaderRendererUI.THIS); table.getColumnModel().getColumn(1).setCellRenderer(HeaderRendererUI.THIS); table.getColumnModel().getColumn(3).setHeaderRenderer(RowTableHeaderRendere.THIS); table.getColumnModel().getColumn(3).setCellRenderer(RowTableHeaderRendere.THIS); scrollPane.setViewportView(table); setSize(new Dimension(400, 200)); setLocationRelativeTo(null); add(scrollPane); } public static void main(String args[]) { try { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) { java.util.logging.Logger.getLogger(RowHeaderTest.class.getName()).log(java.util.logging.Level.SEVERE, null, ex); } java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new RowHeaderTest().setVisible(true); } }); } } final class HeaderRenderer extends DefaultTableCellHeaderRenderer { public static final HeaderRenderer THIS = new HeaderRenderer(); @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { TableCellRenderer renderer = table.getTableHeader().getDefaultRenderer(); return renderer.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column); } } final class HeaderRendererUI extends DefaultTableCellHeaderRenderer { public static final HeaderRendererUI THIS = new HeaderRendererUI(); @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { setText(value.toString()); //TableHeader.ancestorInputMap setBackground(isSelected ? UIManager.getColor("TableHeader.focusCellBackground") : UIManager.getColor("TableHeader.background")); setBorder(UIManager.getBorder("TableHeader.cellBorder")); setFont(UIManager.getFont("TableHeader.font")); setForeground(UIManager.getColor("TableHeader.foreground")); return this; } } final class RowTableHeaderRendere extends DefaultTableCellHeaderRenderer { public static final RowTableHeaderRendere THIS = new RowTableHeaderRendere(); @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { JTable t = new JTable(new DefaultTableModel( null, new String[] { value.toString() })); return t.getTableHeader(); } } 

EDIT

I just added a partial solution for the code. Col 3 now looks good, but still lacks the feel (it doesn't have a mouse), and I'm not quite sure that creating a new table just to get the title is the best way to do this.

+4
source share
1 answer

To save System LookAndFeel, you need to slightly change the rendering.

First extends your rendering with a UIRessource. This token interface is required to receive user interface changes:

 class HeaderRenderer extends DefaultTableCellHeaderRenderer implements javax.swing.plaf.UIResource { 

Then grab and hold the original renderer from your JTableHeader (for example, like the defRenderer field passed by the constructor). In your getTableCellRendererComponent call defRenderer.getTableCellRendererComponent, modify and return this JLabel.

 private final TableCellRenderer defRenderer; HeaderRenderer (TableCellRenderer defRenderer) { this.defRenderer = defRenderer; } @Override public Component getTableCellRendererComponent( JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Component c = defRenderer.getTableCellRendererComponent (...); if ( c instanceof JLabel ) { JLabel lbl = (JLabel)c; // do anything you want... } return c; } 

At the very least, override the updateUI () method in your Renderer and cancel the updateUI call to defRenderer:

 @Override public void updateUI() { TableCellRenderer locDefRenderer = defRenderer; if (locDefRenderer instanceof JComponent) { ((JComponent) locDefRenderer).updateUI(); } else { super.updateUI(); } } 

You can change a lot with this receipt. Regular paintComponent rendering is a bit more complicated ;-) - JLayer (introduced in Java 7) is used for native paints

+3
source

Source: https://habr.com/ru/post/1494181/


All Articles