double row header in JTable

194 views Asked by At

im coding soft that uses table and jtable gives me hard time again.

for single row header im using:

    private class make_table extends AbstractTableModel {
        private String[] headers = headers();
                                            
        Object[][] rows = rows();
        
        public int getColumnCount() {
            return headers.length;
        }

        public int getRowCount() {
            return rows.length;
        }

        public String getColumnName(int col) {
            return headers[col];
        }

        public Object getValueAt(int row, int col) {
            return rows[row][col];
        }

        public Class getColumnClass(int c) {
            return getValueAt(0, c).getClass();
        }
    }   

then i just pass it into:

table = new JTable(new make_table());

headers(); method just returns String[] with names of columns - 1 dimensional array.

i've tried to make headers() retrun 2D array - String[][] and headers within make_table String[][] instead of String[]. my problem is how to render it/show it in JTable.

i've just copy-pasted that whole method long time ago into another project and i cant understand how it works. i guess i could somehow use way im handling rows since its 2D array but i cant get my head around it.

note: i've read some stuff but it all seems to be focusing on not same number of cells in row 1 and row 2. i want first row header to have 6 cells and second row in header 6 cells as well.

my question: how could i pass into & show two row header JTable? preferably via 2D array.

1

There are 1 answers

0
camickr On

Two different approaches:

  1. Use HTML for the column name with the <br> tag to denote each line
  2. Use a custom renderer to parse the column name into multiple lines

In both cases the height of the column header will be determined the the number of lines in the first column:

enter image description here

import java.awt.*;
import javax.swing.*;
import javax.swing.table.*;

public class TableHeaderLines extends JPanel
{
    public TableHeaderLines()
    {
        add( createHeaderUsingHTML() );
        add( createHeaderUsingCustomRenderer() );
    }

    private JComponent createHeaderUsingHTML()
    {
        // the height of the header is determined by the height of the first column

        Object[] columnNames =
        {
            "<html>Column 1<br>multi<br>line</html",
            "Column 2",
            "<html>Column 3<br>more</html",
            "<html>one<br>two<br>three<br>four</html>" // lines won't display completely
        };

        DefaultTableModel model = new DefaultTableModel(columnNames, 5);
        JTable table = new JTable(model);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());

        return new JScrollPane( table );
    }

    private JComponent createHeaderUsingCustomRenderer()
    {
        // the height of the header is determined by the height of the first column
        // the multi line renderer will only work if the first line is multi line

        Object[] columnNames =
        {
            "Column 1,multi,line",
            "Column 2",
            "Column 3,more",
            "one,two,three,four" // 4th line won't display
        };

        DefaultTableModel model = new DefaultTableModel(columnNames, 5);
        JTable table = new JTable(model);
        table.setPreferredScrollableViewportSize(table.getPreferredSize());

        table.getTableHeader().setDefaultRenderer( new LineRenderer() );

        return new JScrollPane( table );
    }

    class LineRenderer extends JPanel implements TableCellRenderer
    {
        public LineRenderer()
        {
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
            setOpaque( false );
            setBorder(UIManager.getBorder("TableHeader.cellBorder"));
        }

        public Component getTableCellRendererComponent(
            JTable table, Object value, boolean isSelected,
            boolean hasFocus, final int row, final int column)
        {
            removeAll();

            String[] result = ((String)value).split(",");

            for (int i = 0; i < result.length; i++)
            {
                JLabel label = new JLabel(result[i]);
                label.setFont( table.getTableHeader().getFont() );
                label.setAlignmentX(0.5f);
                add(label);
            }

            return this;
        }
    }

    public static void createAndShowGUI()
    {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
        frame.add(new TableHeaderLines());
        frame.pack();
        frame.setLocationRelativeTo( null );
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception
    {
        java.awt.EventQueue.invokeLater( () -> createAndShowGUI() );
    }
}