简体   繁体   English

在 JTable 中使用 setAutoCreateRowSorter 对不同数据类型进行排序

[英]Sorting different data types using setAutoCreateRowSorter in JTable

I am querying a MySQL database via Java, pulling data out of the result set and placing it in a DefaultTableModel, which gets put in a JTable, then into a JScrollPane to get displayed.我正在通过 Java 查询 MySQL 数据库,从结果集中提取数据并将其放入 DefaultTableModel,然后放入 JTable,然后放入 JScrollPane 以显示。

In the JTable, I enable sorting in the table via在 JTable 中,我通过在表中启用排序

table.setAutoCreateRowSorter(true);

However, if the cells in the row I want to sort are not of class String, then I get a java.lang.ClassCastException.但是,如果我要排序的行中的单元格不是 String 类,那么我会收到 java.lang.ClassCastException。 The data in my table has the following classes:我的表中的数据具有以下类:

java.sql.Date
java.sql.Time
java.lang.Double
java.lang.Boolean
java.lang.String

Below is the error I get when I try to sort a column of class java.lang.Double, followed by the class that takes the result set as input out outputs the JTable.下面是当我尝试对 java.lang.Double 类的列进行排序时遇到的错误,然后是将结果集作为输入输出 JTable 的类。 If anyone has any ideas on how I can fix my sorting problem it would be greatly appreciated.如果有人对我如何解决排序问题有任何想法,将不胜感激。

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)

Here is the source for the class:这是该类的来源:

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();
    }
}

The problem is that you told the JTable that all your columns contain Strings (escpt the last one), which is not true:问题是你告诉 JTable 你的所有列都包含字符串(escpt 最后一个),这是不正确的:

public Class<?> getColumnClass(int columnIndex) {
    if (columnIndex == numberOfColumns) {
        return Boolean.class;
    } else {
        //return getValueAt(0, columnIndex).getClass();
        return String.class;
    }
}

Tell the truth to the JTable, and it will be happy.对JTable 说实话,它会高兴的。

this is because some data inside one column are two class Type as String and Integer OR Double and Date .... etc this code can resolve your problem :这是因为一列中的一些数据是两个类 Type 作为 String 和 Integer OR Double 和 Date .... 等此代码可以解决您的问题:

private void Change_Table_Data_Class (ArrayList<ArrayList<Object>> table) {
    for (int rowIndex = 0; rowIndex < table.size(); rowIndex++) {
        for (int columnIndex = 0; columnIndex < table.get(rowIndex).size(); columnIndex++) {
            Object cellDataType = table.get(0).get(columnIndex);
            Object cellData = table.get(rowIndex ).get(columnIndex);
                if (!(cellDataType instanceof Double)) {
                    DecimalFormat df = new DecimalFormat("#.##");                                
                        String formattedMerging = df.format(cellData);
                            table.get(rowIndex).set(columnIndex, Double.valueOf(formattedMerging));
                } else if (!(cellDataType instanceof String)) {
                         table.get(rowIndex).set(columnIndex, String.valueOf(cellData));
                }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM