Javaを介してMySQLデータベースにクエリを実行し、結果セットからデータを取得してDefaultTableModelに配置します。DefaultTableModelはJTableに配置され、次にJScrollPaneに配置されて表示されます。
JTableで、次の方法でテーブルの並べ替えを有効にします。
table.setAutoCreateRowSorter(true);
ただし、並べ替える行のセルがStringクラスでない場合は、java.lang.ClassCastExceptionが発生します。私のテーブルのデータには、次のクラスがあります。
java.sql.Date
java.sql.Time
java.lang.Double
java.lang.Boolean
java.lang.String
以下は、クラスjava.lang.Doubleの列をソートしようとしたときに発生するエラーであり、その後に、結果セットを入力として取得するクラスがJTableを出力します。ソートの問題を解決する方法について誰かが何かアイデアを持っているなら、それは大いにありがたいです。
Exception in thread "AWT-EventQueue-0" java.lang.ClassCastException: java.lang.Double `enter code here`cannot be cast to java.lang.String
at java.text.Collator.compare(Collator.java:327)
at javax.swing.DefaultRowSorter.compare(DefaultRowSorter.java:968)
at javax.swing.DefaultRowSorter.access$100(DefaultRowSorter.java:112)
at javax.swing.DefaultRowSorter$Row.compareTo(DefaultRowSorter.java:1376)
at javax.swing.DefaultRowSorter$Row.compareTo(DefaultRowSorter.java:1366)
at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
at java.util.Arrays.sort(Arrays.java:472)
at javax.swing.DefaultRowSorter.sort(DefaultRowSorter.java:607)
at javax.swing.DefaultRowSorter.setSortKeys(DefaultRowSorter.java:319)
at javax.swing.DefaultRowSorter.toggleSortOrder(DefaultRowSorter.java:480)
at javax.swing.plaf.basic.BasicTableHeaderUI$MouseInputHandler.mouseClicked(BasicTableHeaderUI.java:112)
at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:270)
at java.awt.AWTEventMulticaster.mouseClicked(AWTEventMulticaster.java:269)
at java.awt.Component.processMouseEvent(Component.java:6508)
at javax.swing.JComponent.processMouseEvent(JComponent.java:3321)
at java.awt.Component.processEvent(Component.java:6270)
at java.awt.Container.processEvent(Container.java:2229)
at java.awt.Component.dispatchEventImpl(Component.java:4861)
at java.awt.Container.dispatchEventImpl(Container.java:2287)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.LightweightDispatcher.retargetMouseEvent(Container.java:4832)
at java.awt.LightweightDispatcher.processMouseEvent(Container.java:4501)
at java.awt.LightweightDispatcher.dispatchEvent(Container.java:4422)
at java.awt.Container.dispatchEventImpl(Container.java:2273)
at java.awt.Window.dispatchEventImpl(Window.java:2713)
at java.awt.Component.dispatchEvent(Component.java:4687)
at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:707)
at java.awt.EventQueue.access$000(EventQueue.java:101)
at java.awt.EventQueue$3.run(EventQueue.java:666)
at java.awt.EventQueue$3.run(EventQueue.java:664)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:87)
at java.awt.EventQueue$4.run(EventQueue.java:680)
at java.awt.EventQueue$4.run(EventQueue.java:678)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$1.doIntersectionPrivilege(ProtectionDomain.java:76)
at java.awt.EventQueue.dispatchEvent(EventQueue.java:677)
at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:211)
at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:128)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:117)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:113)
at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:105)
at java.awt.EventDispatchThread.run(EventDispatchThread.java:90)
クラスのソースは次のとおりです。
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFrame;
import javax.swing.JTable;
import javax.swing.JToggleButton;
import javax.swing.UIManager;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;
public class ResultSetToCheckBoxTable {
private int numberOfColumns;
private DefaultTableModel model;
private ResultSetMetaData metaData;
private JTable table;
private ResultSet rs;
private TableColumn tc;
public JTable getTable() {
return table;
}
public ResultSetToCheckBoxTable(ResultSet rs) {
try {
this.rs = rs;
//overrides getColumnClass method in DefaultTableModel to help make checkbox
model = new DefaultTableModel() {
@Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == numberOfColumns) {
return Boolean.class;
} else {
//return getValueAt(0, columnIndex).getClass();
return String.class;
}
}
};
// Get the column names
metaData = this.rs.getMetaData();
numberOfColumns = metaData.getColumnCount();
for (int column = 1; column <= numberOfColumns; column++) {
model.addColumn(metaData.getColumnLabel(column));
}
model.addColumn("");
// Get the table info
while (rs.next()) {
Vector tableRow = new Vector();
for (int i = 1; i <= numberOfColumns; i++) {
tableRow.addElement(rs.getObject(i));
}
tableRow.addElement(true);
model.addRow(tableRow);
}
//Create JTable using the model & set options
table = new JTable(model) {
@Override
public boolean isCellEditable(int row, int column) {
return false;
};
};
table.setAutoCreateRowSorter(true);
table.setPreferredScrollableViewportSize(new Dimension(320, 160));
//Rest of the stuff
tc = table.getColumnModel().getColumn(numberOfColumns);
tc.setHeaderRenderer(new SelectAllHeader(table, numberOfColumns));
}
catch (SQLException ex) {
Logger.getLogger(ResultSetToCheckBoxTable.class.getName()).log(Level.SEVERE, null, ex);
}
}
public static void main(String[] args) {
}
}
/**
* A TableCellRenderer that selects all or none of a Boolean column.
*
* @param numberOfColumns the Boolean column to manage
*/
class SelectAllHeader extends JToggleButton implements TableCellRenderer {
private static final String ALL = "✓ Select all";
private static final String NONE = "✓ Select none";
private JTable table;
private TableModel tableModel;
private JTableHeader header;
private TableColumnModel tcm;
private int targetColumn;
private int viewColumn;
public SelectAllHeader(JTable table, int targetColumn) {
super(ALL);
this.table = table;
this.tableModel = table.getModel();
if (tableModel.getColumnClass(targetColumn) != Boolean.class) {
throw new IllegalArgumentException("Boolean column required.");
}
this.targetColumn = targetColumn;
this.header = table.getTableHeader();
this.tcm = table.getColumnModel();
this.applyUI();
this.addItemListener(new ItemHandler());
header.addMouseListener(new MouseHandler());
tableModel.addTableModelListener(new ModelHandler());
}
@Override
public Component getTableCellRendererComponent(
JTable table, Object value, boolean isSelected,
boolean hasFocus, int row, int column) {
return this;
}
private class ItemHandler implements ItemListener {
@Override
public void itemStateChanged(ItemEvent e) {
boolean state = e.getStateChange() == ItemEvent.SELECTED;
setText((state) ? NONE : ALL);
for (int r = 0; r < table.getRowCount(); r++) {
table.setValueAt(state, r, viewColumn);
}
}
}
@Override
public void updateUI() {
super.updateUI();
applyUI();
}
private void applyUI() {
this.setFont(UIManager.getFont("TableHeader.font"));
this.setBorder(UIManager.getBorder("TableHeader.cellBorder"));
this.setBackground(UIManager.getColor("TableHeader.background"));
this.setForeground(UIManager.getColor("TableHeader.foreground"));
}
private class MouseHandler extends MouseAdapter {
@Override
public void mouseClicked(MouseEvent e) {
viewColumn = header.columnAtPoint(e.getPoint());
int modelColumn = tcm.getColumn(viewColumn).getModelIndex();
if (modelColumn == targetColumn) {
doClick();
}
}
}
private class ModelHandler implements TableModelListener {
@Override
public void tableChanged(TableModelEvent e) {
if (needsToggle()) {
doClick();
header.repaint();
}
}
}
// Return true if this toggle needs to match the model.
private boolean needsToggle() {
boolean allTrue = true;
boolean allFalse = true;
for (int r = 0; r < tableModel.getRowCount(); r++) {
boolean b = (Boolean) tableModel.getValueAt(r, targetColumn);
allTrue &= b;
allFalse &= !b;
}
return allTrue && !isSelected() || allFalse && isSelected();
}
}