What is the best way to put a footer row into a JTable? Does anyone have any sample code to do this?
The only approach I\'ve thought of so far is to put a special ro
You could try implementing your own TableCellRenderer that replaces the rendered content of the last visible row with your footer. However this wouldn't be fixed at the bottom of the table, it will likely shift up and down as you scroll.
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.event.*;
import javax.swing.table.*;
class Application extends JFrame
{
public Application()
{
this.setBounds(100,100,500,200);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
String data[][] = {{"a1","b1","c1"},{"a2","b2","c2"},{"a3","b3","c3"}};
String columnNames[] = {"a","b","c"};
JTable jtable = new JTable(new DefaultTableModel(data,columnNames));
JScrollPane jscrollPane = new JScrollPane(jtable,JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
jscrollPane.setBorder(new CompoundBorder(new MatteBorder(0,0,1,0,Color.gray),new EmptyBorder(0,0,0,0)));
this.add(jscrollPane,BorderLayout.CENTER);
JTable jtable_footer = new JTable(new DefaultTableModel(3,columnNames.length),jtable.getColumnModel());
SyncListener syncListener = new SyncListener(jtable,jtable_footer);
this.add(jtable_footer,BorderLayout.SOUTH);
}
public static void main(String args[])
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
Application application = new Application();
application.setVisible(true);
}
});
}
}
class SyncListener implements TableColumnModelListener
{
JTable jtable_data;
JTable jtable_footer;
public SyncListener(JTable main, JTable footer)
{
jtable_data = main;
jtable_footer = footer;
DefaultTableColumnModel dtcm = (DefaultTableColumnModel)jtable_data.getColumnModel();
dtcm.removeColumnModelListener(dtcm.getColumnModelListeners()[1]);
dtcm.addColumnModelListener(this);
}
public void columnMarginChanged(ChangeEvent changeEvent)
{
for (int column = 0; column < jtable_data.getColumnCount(); column++)
{
jtable_footer.getColumnModel().getColumn(column).setWidth(jtable_data.getColumnModel().getColumn(column).getWidth());
}
jtable_footer.repaint();
}
public void columnAdded(TableColumnModelEvent e){}
public void columnMoved(TableColumnModelEvent e){}
public void columnRemoved(TableColumnModelEvent e){}
public void columnSelectionChanged(ListSelectionEvent e){}
}
Looks like this project has a component called JideScrollPane which advertises support for a row footer. I haven't tried it myself, but it sounds like it does exactly what you want! The website also has a demo app where you can see it in action and it that looks pretty good.
Note that it seems a lot of the their stuff you have to pay for, but their JideScrollPane looks to be free and open source.
The only time I have done this I just added a row in the model like so:
@Override
public int getRowCount() {
return _tableContents.size() + 1;
}
_tableContents is of course the actual data behind my model. You'll have to be aware of the extra row in the model of course (in such calls as setValueAt(...))
Good luck.
Using 2 tables below each-other is a good approach.
If you want to be able to resize/move/remove the colums, key is NOT to reuse the same columnModel between the tables. Have a listener do the resizing. See example:
package snippet;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;
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.TableColumnModel;
public class FixedRow2Tables extends JFrame {
private static final long serialVersionUID = 4676303089799270571L;
Object[][] data;
Object[] column;
JTable footerTable, table;
public FixedRow2Tables() {
super("Fixed Row Example");
Object[][] mainData = new Object[][] { { "a", "", "", "", "", "" },
{ "", "b", "", "", "", "" }, { "", "", "c", "", "", "" },
{ "", "", "", "d", "", "" }, { "", "", "", "", "e", "" },
{ "", "", "", "", "", "f" } };
Object[][] summaryData = { { "fixed1", "", "", "", "", "" },
{ "fixed2", "", "", "", "", "" } };
column = new Object[] { "A", "B", "C", "D", "E", "F" };
table = new JTable(mainData, column);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
footerTable = new JTable(summaryData, column);
footerTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
footerTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
footerTable.setTableHeader(null);
// footerTable.setColumnModel(table.getColumnModel());
table.getColumnModel().addColumnModelListener(
new TableColumnModelListener() {
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
}
@Override
public void columnMoved(TableColumnModelEvent e) {
}
@Override
public void columnMarginChanged(ChangeEvent e) {
final TableColumnModel tableColumnModel = table
.getColumnModel();
TableColumnModel footerColumnModel = footerTable
.getColumnModel();
for (int i = 0; i < tableColumnModel.getColumnCount(); i++) {
int w = tableColumnModel.getColumn(i).getWidth();
footerColumnModel.getColumn(i).setMinWidth(w);
footerColumnModel.getColumn(i).setMaxWidth(w);
// footerColumnModel.getColumn(i).setPreferredWidth(w);
}
footerTable.doLayout();
footerTable.repaint();
repaint();
}
@Override
public void columnAdded(TableColumnModelEvent e) {
}
});
JScrollPane scroll = new JScrollPane(table);
scroll.setHorizontalScrollBarPolicy(JScrollPane.HORIZONTAL_SCROLLBAR_NEVER);
scroll.setPreferredSize(new Dimension(400, 100));
getContentPane().add(scroll, BorderLayout.CENTER);
getContentPane().add(footerTable, 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);
}
});
}
}
Try using a second JTable that uses the same column model as your data table and add your footer data to that table. Add the second (footer) table under your original table.
JTable footer = new JTable(model, table.getColumnModel());
panel.add(BorderLayout.CENTER, table);
panel.add(BorderLayout.SOUTH, footer);