With some of the examples described above, I added some things with a horizontal scrollbar and column order:
package test; import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.event.AdjustmentEvent; import java.awt.event.AdjustmentListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Enumeration; import javax.swing.JFrame; import javax.swing.JScrollBar; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.ListSelectionModel; import javax.swing.SwingUtilities; import javax.swing.event.ChangeEvent; import javax.swing.event.ListSelectionEvent; import javax.swing.event.TableColumnModelEvent; import javax.swing.event.TableColumnModelListener; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; public class FixedRow2Tables extends JFrame { class FixedFooterTable extends JTable { private TableColumnModelListener tableColumnModelListener; private JTable bindedTable; FixedFooterTable(Object[][] data, String[] columnNames) { super(data, columnNames); setAutoResizeMode(JTable.AUTO_RESIZE_OFF); setSelectionMode(ListSelectionModel.SINGLE_SELECTION); setCellSelectionEnabled(true); } public void bindTableModels(final JTable table) { this.bindedTable = table; if (tableColumnModelListener == null) tableColumnModelListener = new TableColumnModelListener() { @Override public void columnSelectionChanged(ListSelectionEvent e) { } @Override public void columnRemoved(TableColumnModelEvent e) { if (e.getFromIndex() < getColumnCount()) { TableColumn c = getColumnModel().getColumn(e.getFromIndex()); getColumnModel().removeColumn(c); } } @Override public void columnMoved(TableColumnModelEvent e) { if (e.getFromIndex() < getColumnCount() && e.getToIndex() < getColumnCount()) { TableColumn c = getColumnModel().getColumn(e.getFromIndex()); getColumnModel().moveColumn(e.getFromIndex(), e.getToIndex()); } } @Override public void columnMarginChanged(ChangeEvent e) { bindColumnWidths(table.getColumnModel()); } @Override public void columnAdded(TableColumnModelEvent e) { } }; table.getColumnModel().addColumnModelListener(tableColumnModelListener); } private void bindColumnWidths(final TableColumnModel columnModel) { TableColumnModel fixedColumnModel = getColumnModel(); Enumeration<TableColumn> enumerator = columnModel.getColumns(); while (enumerator.hasMoreElements()) { TableColumn c = enumerator.nextElement(); if (c.getModelIndex() >= fixedColumnModel.getColumnCount()) break; TableColumn destColumn = fixedColumnModel.getColumn(c.getModelIndex()); System.out.println("columnMarginChanged c" + c.getModelIndex() + " : " + c.getWidth() + " - " + destColumn.getWidth() + " : " + (destColumn.getWidth() - c.getWidth())); destColumn.setPreferredWidth(c.getWidth()); System.out.println("columnMarginChanged c" + c.getModelIndex() + " : " + c.getWidth() + " - " + destColumn.getWidth()); } revalidate(); } @Override public boolean isCellEditable(int row, int column) { return false; } public void bindViews(final JScrollPane scrollPane, final JScrollPane fixedScrollPane) { final JScrollBar fixedHorScrollBar = fixedScrollPane.getHorizontalScrollBar(); final JScrollBar horScrollBar = scrollPane.getHorizontalScrollBar(); final JScrollBar verScrollBar = scrollPane.getVerticalScrollBar(); fixedScrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_NEVER); fixedScrollPane.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); horScrollBar.addAdjustmentListener(new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent e) { fixedHorScrollBar.setValue(e.getValue()); } }); verScrollBar.addAdjustmentListener(new AdjustmentListener() { @Override public void adjustmentValueChanged(AdjustmentEvent e) { Dimension d = fixedScrollPane.getSize(); Dimension d1 = scrollPane.getSize(); } }); } public JTable getBindedTable() { return bindedTable; } } private static final long serialVersionUID = 4676303089799270571L; Object[][] data; String[] columnNames; FixedFooterTable fixedTable; JTable table; public FixedRow2Tables() { super("Fixed Row Example"); Object[][] mainData = new Object[][] { { "a", "", "", "", "", "" }, { "", "b", "", "", "", "" }, { "", "", "c", "", "", "" }, { "", "", "", "d", "", "" }, { "", "", "", "", "e", "" }, { "", "", "", "", "", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" }, { "a", "b", "c", "d", "e", "f" } }; Object[][] summaryData = { { "fixed1", "", "", "", "", "" }, { "fixed2", "b", "c", "d", "e", "f" } }; columnNames = new String[] { "Ala", "Bardzo", "Chciala", "Dostac", "Eskimoska", "Franciszki Genowefy Pigwy" }; table = new JTable(mainData, columnNames); table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF); table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); fixedTable = new FixedFooterTable(summaryData, columnNames); fixedTable.setTableHeader(null); final JScrollPane scroll = new JScrollPane(table); final JScrollPane fixedscroll = new JScrollPane(fixedTable); Dimension preferredSize = fixedTable.getPreferredSize(); fixedscroll.setPreferredSize(preferredSize); fixedTable.bindTableModels(table); fixedTable.bindViews(scroll, fixedscroll); getContentPane().add(scroll, BorderLayout.CENTER); getContentPane().add(fixedscroll, BorderLayout.SOUTH); } public static void main(String[] args) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { FixedRow2Tables frame = new FixedRow2Tables(); frame.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent e) { System.exit(0); } }); frame.pack(); frame.setVisible(true); } }); } }