Reputation: 2314
I'm attempting to create a JTable that looks like the mockup below:
The green corner is basically buffer-space for the red column and row headers. The cells don't need to be rendered in the colours pictured; however they need to be distinguishable from the rest of the 'white' cells in the table.
This table also is not editable or selectable; it's merely viewed by a user whilst it is updated.
I know this can be achieved using a DefaultTableModel with custom renders for rows 1,2 && cols 1,2 and adding +2 when setting and getting table values (accounting for the rows and columns that are being used as headers).
Upvotes: 2
Views: 2620
Reputation: 205865
Input is limited to 20x20 so including the headers that's 22x22.
Also consider a JScrollPane
containing a JPanel
having GridLayout
and containing 22x22 instances JLabel
, or a suitable subclass. This scales easily to several thousand cells.
Addendum: If the need arises, CellRendererPane
makes a good flyweight renderer, as suggested here.
If you go with JTable
for rendering scalability,
This is no abuse; it is exactly how TableModel
is intended to be used. TableModel
models a rectangular matrix of whatever you decide. JTable
is just an (efficiently rendered) view of that model.
I prefer AbstractTableModel
, shown here, because Vector
is rarely the desired data structure. Use whatever container makes your indexing most convenient. DefaultTableModel
is handy and serves as a guide to extending AbstractTableModel
. In particular, you'll need a setValueAt()
.
@Override
public void setValueAt(Object aValue, int row, int col) {
... // update your data structure
this.fireTableCellUpdated(row, col); // notify the view
}
Upvotes: 6
Reputation: 109823
longer comment, everything depends
1) if is possible for Columns
resize
reordering
2) if is possible for Columns
filtering
sorting
a. then you have look at two JTables, first JTable only with TableHeader, simple with removed rows and second full sized JTable with TableHeader and Columns and rows,
b. for interactions betweens two JTableHeader is there
TableColumnModelListener#columnMarginChanged(ChangeEvent e) and columnMoved(TableColumnModelEvent e)
c. everyting put to one JPanel
inside JScrollPane
d. if you'll change numbers of rows or colums (or filtering / sorting) then you have to notified JPanel
for rezize JTable#getPreferredScrollableViewportSize()
+ Dimension
for ontop JTable
only with TableHeader
very similair way as there (is everything that you needed)
(endless kudos for Rob)
import java.awt.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class TableFilterRow extends JFrame implements TableColumnModelListener {
private static final long serialVersionUID = 1L;
private JTable table;
private JPanel filterRow;
public TableFilterRow() {
table = new JTable(3, 5);
table.setPreferredScrollableViewportSize(table.getPreferredSize());
JScrollPane scrollPane = new JScrollPane(table);
getContentPane().add(scrollPane);
table.getColumnModel().addColumnModelListener(this);
// Panel for text fields
filterRow = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0));
for (int i = 0; i < table.getColumnCount(); i++) {
filterRow.add(new JTextField(" Sum at - " + i));
}
columnMarginChanged(new ChangeEvent(table.getColumnModel()));
getContentPane().add(filterRow, BorderLayout.SOUTH);
}
// Implement TableColumnModelListener methods
// (Note: instead of implementing a listener you should be able to
// override the columnMarginChanged and columMoved methods of JTable)
@Override
public void columnMarginChanged(ChangeEvent e) {
TableColumnModel tcm = table.getColumnModel();
int columns = tcm.getColumnCount();
for (int i = 0; i < columns; i++) {
JTextField textField = (JTextField) filterRow.getComponent(i);
Dimension d = textField.getPreferredSize();
d.width = tcm.getColumn(i).getWidth();
textField.setPreferredSize(d);
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
filterRow.revalidate();
}
});
}
@Override
public void columnMoved(TableColumnModelEvent e) {
Component moved = filterRow.getComponent(e.getFromIndex());
filterRow.remove(e.getFromIndex());
filterRow.add(moved, e.getToIndex());
filterRow.validate();
}
@Override
public void columnAdded(TableColumnModelEvent e) {
}
@Override
public void columnRemoved(TableColumnModelEvent e) {
}
@Override
public void columnSelectionChanged(ListSelectionEvent e) {
}
public static void main(String[] args) {
JFrame frame = new TableFilterRow();
frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
3) otherwise look How to Use Raised Borders in the prepareRederer
4) this question has nothing to do with type of TableModel
Upvotes: 5