List UI Properties in a JTable and sortable
/*
Definitive Guide to Swing for Java 2, Second Edition
By John Zukowski
ISBN: 1-893115-78-X
Publisher: APress
*/
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.InputEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JToolBar;
import javax.swing.SwingUtilities;
import javax.swing.UIDefaults;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
public class ListProperties {
static class CustomTableModel extends AbstractTableModel {
Vector keys = new Vector();
Vector values = new Vector();
private static final String columnNames[] = { "Property String",
"Value" };
public int getColumnCount() {
return columnNames.length;
}
public String getColumnName(int column) {
return columnNames[column];
}
public int getRowCount() {
return keys.size();
}
public Object getValueAt(int row, int column) {
Object returnValue = null;
if (column == 0) {
returnValue = keys.elementAt(row);
} else if (column == 1) {
returnValue = values.elementAt(row);
}
return returnValue;
}
public synchronized void uiDefaultsUpdate(UIDefaults defaults) {
Enumeration newKeys = defaults.keys();
keys.removeAllElements();
while (newKeys.hasMoreElements()) {
keys.addElement(newKeys.nextElement());
}
Enumeration newValues = defaults.elements();
values.removeAllElements();
while (newValues.hasMoreElements()) {
values.addElement(newValues.nextElement());
}
fireTableDataChanged();
}
}
public static void main(String args[]) {
final JFrame frame = new JFrame("List Properties");
final CustomTableModel model = new CustomTableModel();
model.uiDefaultsUpdate(UIManager.getDefaults());
TableSorter sorter = new TableSorter(model);
JTable table = new JTable(sorter);
TableHeaderSorter.install(sorter, table);
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
UIManager.LookAndFeelInfo looks[] = UIManager
.getInstalledLookAndFeels();
ActionListener actionListener = new ActionListener() {
public void actionPerformed(ActionEvent actionEvent) {
final String lafClassName = actionEvent.getActionCommand();
Runnable runnable = new Runnable() {
public void run() {
try {
UIManager.setLookAndFeel(lafClassName);
SwingUtilities.updateComponentTreeUI(frame);
// Added
model.uiDefaultsUpdate(UIManager.getDefaults());
} catch (Exception exception) {
JOptionPane.showMessageDialog(frame,
"Can't change look and feel",
"Invalid PLAF", JOptionPane.ERROR_MESSAGE);
}
}
};
SwingUtilities.invokeLater(runnable);
}
};
JToolBar toolbar = new JToolBar();
for (int i = 0, n = looks.length; i < n; i++) {
JButton button = new JButton(looks[i].getName());
button.setActionCommand(looks[i].getClassName());
button.addActionListener(actionListener);
toolbar.add(button);
}
Container content = frame.getContentPane();
content.add(toolbar, BorderLayout.NORTH);
JScrollPane scrollPane = new JScrollPane(table);
content.add(scrollPane, BorderLayout.CENTER);
frame.setSize(400, 400);
frame.setVisible(true);
}
}
class TableSorter extends TableMap implements TableModelListener {
int indexes[] = new int[0];
Vector sortingColumns = new Vector();
boolean ascending = true;
public TableSorter() {
}
public TableSorter(TableModel model) {
setModel(model);
}
public void setModel(TableModel model) {
super.setModel(model);
reallocateIndexes();
sortByColumn(0);
fireTableDataChanged();
}
public int compareRowsByColumn(int row1, int row2, int column) {
Class type = model.getColumnClass(column);
TableModel data = model;
// Check for nulls
Object o1 = data.getValueAt(row1, column);
Object o2 = data.getValueAt(row2, column);
// If both values are null return 0
if (o1 == null && o2 == null) {
return 0;
} else if (o1 == null) { // Define null less than everything.
return -1;
} else if (o2 == null) {
return 1;
}
if (type.getSuperclass() == Number.class) {
Number n1 = (Number) data.getValueAt(row1, column);
double d1 = n1.doubleValue();
Number n2 = (Number) data.getValueAt(row2, column);
double d2 = n2.doubleValue();
if (d1 < d2)
return -1;
else if (d1 > d2)
return 1;
else
return 0;
} else if (type == String.class) {
String s1 = (String) data.getValueAt(row1, column);
String s2 = (String) data.getValueAt(row2, column);
int result = s1.compareTo(s2);
if (result < 0)
return -1;
else if (result > 0)
return 1;
else
return 0;
} else if (type == java.util.Date.class) {
Date d1 = (Date) data.getValueAt(row1, column);
long n1 = d1.getTime();
Date d2 = (Date) data.getValueAt(row2, column);
long n2 = d2.getTime();
if (n1 < n2)
return -1;
else if (n1 > n2)
return 1;
else
return 0;
} else if (type == Boolean.class) {
Boolean bool1 = (Boolean) data.getValueAt(row1, column);
boolean b1 = bool1.booleanValue();
Boolean bool2 = (Boolean) data.getValueAt(row2, column);
boolean b2 = bool2.booleanValue();
if (b1 == b2)
return 0;
else if (b1) // Define false < true
return 1;
else
return -1;
} else {
Object v1 = data.getValueAt(row1, column);
String s1 = v1.toString();
Object v2 = data.getValueAt(row2, column);
String s2 = v2.toString();
int result = s1.compareTo(s2);
if (result < 0)
return -1;
else if (result > 0)
return 1;
else
return 0;
}
}
public int compare(int row1, int row2) {
for (int level = 0, n = sortingColumns.size(); level < n; level++) {
Integer column = (Integer) sortingColumns.elementAt(level);
int result = compareRowsByColumn(row1, row2, column.intValue());
if (result != 0) {
return (ascending ? result : -result);
}
}
return 0;
}
public void reallocateIndexes() {
int rowCount = model.getRowCount();
indexes = new int[rowCount];
for (int row = 0; row < rowCount; row++) {
indexes[row] = row;
}
}
public void tableChanged(TableModelEvent tableModelEvent) {
super.tableChanged(tableModelEvent);
reallocateIndexes();
sortByColumn(0);
fireTableStructureChanged();
}
public void checkModel() {
if (indexes.length != model.getRowCount()) {
System.err.println("Sorter not informed of a change in model.");
}
}
public void sort() {
checkModel();
shuttlesort((int[]) indexes.clone(), indexes, 0, indexes.length);
fireTableDataChanged();
}
public void shuttlesort(int from[], int to[], int low, int high) {
if (high - low < 2) {
return;
}
int middle = (low + high) / 2;
shuttlesort(to, from, low, middle);
shuttlesort(to, from, middle, high);
int p = low;
int q = middle;
for (int i = low; i < high; i++) {
if (q >= high || (p < middle && compare(from[p], from[q]) <= 0)) {
to[i] = from[p++];
} else {
to[i] = from[q++];
}
}
}
private void swap(int first, int second) {
int temp = indexes[first];
indexes[first] = indexes[second];
indexes[second] = temp;
}
public Object getValueAt(int row, int column) {
checkModel();
return model.getValueAt(indexes[row], column);
}
public void setValueAt(Object aValue, int row, int column) {
checkModel();
model.setValueAt(aValue, indexes[row], column);
}
public void sortByColumn(int column) {
sortByColumn(column, true);
}
public void sortByColumn(int column, boolean ascending) {
this.ascending = ascending;
sortingColumns.removeAllElements();
sortingColumns.addElement(new Integer(column));
sort();
super.tableChanged(new TableModelEvent(this));
}
}
class TableHeaderSorter extends MouseAdapter {
private TableSorter sorter;
private JTable table;
private TableHeaderSorter() {
}
public static void install(TableSorter sorter, JTable table) {
TableHeaderSorter tableHeaderSorter = new TableHeaderSorter();
tableHeaderSorter.sorter = sorter;
tableHeaderSorter.table = table;
JTableHeader tableHeader = table.getTableHeader();
tableHeader.addMouseListener(tableHeaderSorter);
}
public void mouseClicked(MouseEvent mouseEvent) {
TableColumnModel columnModel = table.getColumnModel();
int viewColumn = columnModel.getColumnIndexAtX(mouseEvent.getX());
int column = table.convertColumnIndexToModel(viewColumn);
if (mouseEvent.getClickCount() == 1 && column != -1) {
System.out.println("Sorting ...");
int shiftPressed = (mouseEvent.getModifiers() & InputEvent.SHIFT_MASK);
boolean ascending = (shiftPressed == 0);
sorter.sortByColumn(column, ascending);
}
}
}
class TableMap extends AbstractTableModel implements TableModelListener {
TableModel model;
public TableModel getModel() {
return model;
}
public void setModel(TableModel model) {
if (this.model != null) {
this.model.removeTableModelListener(this);
}
this.model = model;
if (this.model != null) {
this.model.addTableModelListener(this);
}
}
public Class getColumnClass(int column) {
return model.getColumnClass(column);
}
public int getColumnCount() {
return ((model == null) ? 0 : model.getColumnCount());
}
public String getColumnName(int column) {
return model.getColumnName(column);
}
public int getRowCount() {
return ((model == null) ? 0 : model.getRowCount());
}
public Object getValueAt(int row, int column) {
return model.getValueAt(row, column);
}
public void setValueAt(Object value, int row, int column) {
model.setValueAt(value, row, column);
}
public boolean isCellEditable(int row, int column) {
return model.isCellEditable(row, column);
}
public void tableChanged(TableModelEvent tableModelEvent) {
fireTableChanged(tableModelEvent);
}
}
Related examples in the same category
1. | Creating a JTable Component | | |
2. | Creates tables that allow rows and columns to be added or deleted | | |
3. | Build a table from list data and column names | | |
4. | Getting the Number of Rows and Columns in a JTable Component | | |
5. | Appending a Row to a JTable Component | | |
6. | Add columns to a table through DefaultTableModel | | |
7. | Insert a row to a table through DefaultTableModel | | |
8. | Insert a row to a table through DefaultTableModel at specified row | | |
9. | Scroll Table Sample | | |
10. | Simple demonstration of JTable | | |
11. | Create a table with two dimensional array | | |
12. | Create table with Unicode data | | |
13. | Resize Table | | |
14. | Expense Table | | |
15. | StockTable 6: Action and Dynamic Display | | |
16. | JTable selection events | | |
17. | A table with the ability to play with row and column selections | | |
18. | Table Selection mode | | |
19. | Display ResultSet in Table (JTable) | | |
20. | JTable(Table) with JDBC and ResultSet | | |
21. | Property Table: Use JTable to display and edit properties | | |
22. | Table with tool tips for both cells and column headers | | |
23. | StockTable 4: Table Sorter | | |
24. | JTable sorter:click the table header to sort a column and a table | | |
25. | Creating image out of a JTable | | |
26. | JTable.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); | | |
27. | JTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); | | |
28. | JTable.setColumnSelectionAllowed(boolean b); | | |
29. | JTable.setRowSelectionAllowed(boolean b); | | |
30. | JTable.setCellSelectionEnabled(boolean b); | | |
31. | Handle selection and model change events for a JTable. | | |
32. | ListSelectionModel rowSelMod = JTable.getSelectionModel(); | | |
33. | ListSelectionModel colSelMod = JTable.getColumnModel().getSelectionModel(); | | |
34. | JTree.getModel().addTreeModelListener(new TreeModelListener()) | | |
35. | Move the last visible column so it becomes the first visible column | | |
36. | the last column is moved to the first position | | |
37. | Allowing the User to Resize a Column in a JTable Component | | |
38. | Retrieve the value in the visible cell (1,2) in a JTable | | |
39. | Retrieve the value in cell (1,2) from the model | | |
40. | Change a cell in the 2nd visible column | | |
41. | Change a cell in the 3rd column in the model | | |
42. | Showing the Table Header in a Non-Scrollable JTable Component | | |
43. | Changing the Name of a Column in a JTable Component | | |
44. | Displaying an Icon in a Column Head of a JTable Component | | |
45. | Implementing Variable-Height Column Headers in a JTable Component | | |
46. | Removing the Column Headers from a Scrollable in a JTable Component | | |
47. | Creating a Custom Column Header Renderer in a JTable Component | | |
48. | Setting Column Header Tool Tips in a JTable Components | | |
49. | Setting Tool Tips on Cells in a JTable Component | | |
50. | Enable row selection (default) in a JTable | | |
51. | Enable column selection in a JTable | | |
52. | Enable cell selection in a JTable | | |
53. | Get default selection mode:MULTIPLE_INTERVAL_SELECTION | | |
54. | Allow only single a selection | | |
55. | Allow selection to span one contiguous set of rows, visible columns, or block of cells | | |
56. | Allow multiple selections of rows, visible columns, or cell blocks (default) | | |
57. | Select a column - column 0 in a JTable | | |
58. | Select an additional range of columns - columns 1 to 2 | | |
59. | Deselect a range of columns - columns 0 to 1 | | |
60. | Select a row - row 0 | | |
61. | Select an additional range of rows - rows 1 to 2 | | |
62. | Deselect a range of rows - rows 0 to 1 | | |
63. | Select a cell: cell (2,1) | | |
64. | Extend the selection to include all cells (5,3) | | |
65. | Deselect a cell: cell (3,2), All cells in the row and column containing (3,2) are deselected. | | |
66. | Toggles the selection state, if it were called again, it exactly reverses the first call. | | |
67. | Select all cells | | |
68. | Deselect all cells | | |
69. | Column selection is enabled, get the indices of the selected columns | | |
70. | Row selection is enabled, Get the indices of the selected rows | | |
71. | Get selected row and selected index | | |
72. | Get the min and max ranges of selected cells | | |
73. | Check each cell in the min and max ranges of selected cells | | |
74. | Disabling Selections in a JTable Component | | |
75. | Getting the Anchor Cell in a JTable Component | | |
76. | Creating a Scrollable JTable Component | | |
77. | Disable auto resizing to make the table horizontal scrollable | | |
78. | Determining If a Cell Is Visible in a JTable Component | | |
79. | Making a Cell Visible in a JTable Component | | |
80. | Scrolling a Cell to the Center of a JTable Component | | |
81. | Show both horizontal and vertical grid lines (the default) | | |
82. | Don't show any grid lines | | |
83. | Show only vertical grid lines | | |
84. | Show only horizontal grid lines | | |
85. | Set the grid color | | |
86. | Getting the Gap Size Between Cells in a JTable Component | | |
87. | Add 5 spaces to the left and right sides of a cell. | | |
88. | Increase the row height | | |
89. | Programmatically Starting Cell Editing in a JTable Component | | |
90. | Save the current value in the cell being edited and stops the editing process | | |
91. | Discard any changes made by the user and stops the editing process | | |
92. | Disabling User Edits in a JTable | | |
93. | Disabling User Edits in a JTable with DefaultTableModel | | |
94. | Sorting the Rows in a JTable Component Based on a Column | | |
95. | Sorting a Column in a JTable Component | | |
96. | Listening for Selection Events in a JTable Component | | |
97. | Listening for Changes to the Rows and Columns of a JTable Component | | |
98. | Listening for Column-Related Changes in a JTable Component | | |
99. | Listening for Clicks on a Column Header in a JTable Component | | |
100. | Sorting and Filtering Tables | | |
101. | Use a regexFilter to filter table content | | |
102. | Creating a JTable with rows of variable height | | |
103. | Scroll JTable To Center | | |