如何正确更新jtable模型?

时间:2013-11-06 11:59:24

标签: java swing jtable tablemodel

我一直在考虑解决这个错误。但不幸的是,我得到了最后的结论,我需要专业人士的帮助。

请复制,粘贴此代码以查看问题:

public class DateFormatDemo extends JFrame
{
    private JTable dataSearchResultTable;

    public DateFormatDemo()
    {
        JButton updateTable = new JButton("Update table");
        updateTable.setMaximumSize(updateTable.getPreferredSize());
        updateTable.addActionListener(new ActionListener()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                updateMyTableModel();
            }
        });
        JPanel panel = new JPanel(new GridLayout(2, 1, 5, 10));
        panel.setPreferredSize(new Dimension(500, 300));
        panel.add(new JScrollPane(initDataSearchResultTable()));
        panel.add(updateTable);
        super.getContentPane().add(panel);
        super.pack();
        super.setDefaultCloseOperation(EXIT_ON_CLOSE);
        super.setVisible(true);
    }

    private JTable initDataSearchResultTable()
    {
        dataSearchResultTable = new JTable();
        // dataSearchResultTable.setAutoCreateColumnsFromModel(false);
        dataSearchResultTable.setSelectionBackground(new Color(0xaaaaff));
        dataSearchResultTable.setFillsViewportHeight(true);
        dataSearchResultTable.setRowSelectionAllowed(true);
        dataSearchResultTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        dataSearchResultTable.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);

        return dataSearchResultTable;
    }

    void updateMyTableModel()
    {
        TableModel tableModel = dataSearchResultTable.getModel();
        TableColumnModel columnModel = dataSearchResultTable.getColumnModel();
        if (tableModel instanceof MyTableModel) {
            ((MyTableModel) tableModel).updateModel();
            this.initColumnWidths(tableModel, columnModel);
        } else {
            tableModel = new MyTableModel();
            dataSearchResultTable.setModel(tableModel);
            this.makeColumnsNotResizable(columnModel);
            this.initColumnWidths(tableModel, columnModel);
        }
    }

    private void makeColumnsNotResizable(TableColumnModel columnModel)
    {
        for (int i = 0; i < columnModel.getColumnCount(); i++) {
            if (i == 0 || i == 1) {
                columnModel.getColumn(i).setResizable(false);
            }
        }
    }

    private void initColumnWidths(TableModel tableModel, TableColumnModel columnModel)
    {
        TableColumn column = null;
        Component comp = null;
        int cellWidth = 0;
        int headerWidth = 0;
        TableCellRenderer headerRenderer = dataSearchResultTable.getTableHeader().getDefaultRenderer();

        for (int i = 0; i < columnModel.getColumnCount(); i++) {
            column = columnModel.getColumn(i);
            comp = headerRenderer.getTableCellRendererComponent(null, column.getHeaderValue(), false, false, -1, 0);
            headerWidth = comp.getPreferredSize().width;
            Class<?> columnClass = tableModel.getColumnClass(i);
            for (int j = 0; j < tableModel.getRowCount(); j++) {
                comp = dataSearchResultTable.getDefaultRenderer(columnClass).getTableCellRendererComponent(
                        dataSearchResultTable, tableModel.getValueAt(j, i), false, false, j, i);
                int width = comp.getPreferredSize().width;
                // we cache width of first row. And compare widths of next
                // rows with width of first.
                // If some row has greater width it becomes width of whole
                // row(unless header has greater width)
                if (cellWidth < width || j == 0) {
                    cellWidth = width;
                }
            }
            System.out
                    .println("columnClass=" + columnClass + ",headerWidth=" + headerWidth + ",cellWidth=" + cellWidth);

            if (headerWidth > cellWidth) {
                TableCellRenderer centeredRenderer = dataSearchResultTable.getDefaultRenderer(columnClass);
                if (centeredRenderer instanceof DefaultTableCellRenderer) {
                    ((DefaultTableCellRenderer) centeredRenderer).setHorizontalAlignment(SwingConstants.CENTER);
                    column.setCellRenderer(centeredRenderer);
                    column.setPreferredWidth(headerWidth);
                }
            } else {
                column.setPreferredWidth(cellWidth + 5);
            }
        }
    }

    class MyTableModel extends AbstractTableModel
    {
        private String[] columnNames = { "First Name", "Last Name", "Timestamp", "Number", "Vegetarian" };
        private Object[][] data = new Object[5][];

        void updateModel()
        {
            data = new Object[][] {
                    { "Vova", "KipokKipokKipokKipok", "2013-04-12 11:20:41", new Integer(5), new Boolean(true) },
                    { "Olia", "Duo", "2010-01-11 11:11:41", new Integer(3), new Boolean(false) },
                    { "Oksana", "Stack", "2012-04-12 11:20:41", new Integer(2), new Boolean(false) },
                    { "Petro", "White", "2010-04-12 11:20:21", new Integer(20), new Boolean(true) },
                    { "Ivan", "Brown", "2011-04-11 11:20:41", new Integer(10), new Boolean(true) } };
            fireTableDataChanged();
        }

        public int getColumnCount()
        {
            return columnNames.length;
        }

        public int getRowCount()
        {
            return data.length;
        }

        public String getColumnName(int col)
        {
            return columnNames[col];
        }

        public Object getValueAt(int row, int col)
        {
            if (data.length > 0 && data[0] != null) {
                return data[row][col];
            }
            return null;
        }

        /*
         * JTable uses this method to determine the default renderer/ editor for
         * each cell. If we didn't implement this method, then the last column
         * would contain text ("true"/"false"), rather than a check box.
         */
        public Class getColumnClass(int c)
        {
            Object valueAt = getValueAt(0, c);
            return valueAt == null ? Object.class : valueAt.getClass();
        }

        /*
         * Don't need to implement this method unless your table's editable.
         */
        public boolean isCellEditable(int row, int col)
        {
            // Note that the data/cell address is constant,
            // no matter where the cell appears onscreen.
            if (col < 2) {
                return false;
            } else {
                return true;
            }
        }

        /*
         * Don't need to implement this method unless your table's data can
         * change.
         */
        public void setValueAt(Object value, int row, int col)
        {
            if (data.length > 0 && data[0] != null) {
                data[row][col] = value;
                fireTableCellUpdated(row, col);
            }
        }

    }

    public static void main(String[] args) throws ParseException
    {
        new DateFormatDemo();
    }
}

现在请在名为“更新表”的大按钮上单击两次。如您所见,列应该显示复选框,因为它保持布尔值不会这样做,而是显示字符串true或false。

此代码模拟我的真实工作流程。 那么,如何更新tablemodel以使用带有checkbozes的布尔列。

谢谢!

2 个答案:

答案 0 :(得分:3)

将此视为简单的起点

import java.awt.*;
import java.util.Random;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class Forum implements ListSelectionListener {

    private JFrame frame = new JFrame("Frame");
    private JPanel fatherCenter = new JPanel();
    private JScrollPane tableScroll = new JScrollPane();
    private MyTableModel tableModel;
    private JTable dialogTable;
    private ListSelectionModel lsDialog;
    private Color clr;
    private Color clr1;

    private void addData() {
        Runnable doRun1 = new Runnable() {
            @Override
            public void run() {
                tableModel.resetTable();
                Vector<String> tbl = new Vector<String>();
                Vector<Object> tbl1 = new Vector<Object>();
                Random rnd = new Random();
                tbl.add("Integer");
                tbl.add("Double");
                tbl.add("Boolean");
                tbl.add("Boolean");
                tbl.add("String");
                tableModel.setColumnNames(tbl);
                for (int row = 0; row < 30; row++) {
                    tbl1 = null;
                    tbl1 = new Vector<Object>();
                    tbl1.addElement(row + 1);
                    tbl1.addElement(rnd.nextInt(25) + 3.14);
                    tbl1.addElement((row % 3 == 0) ? false : true);
                    tbl1.addElement((row % 5 == 0) ? false : true);
                    if (row % 7 == 0) {
                        tbl1.add(("Canc"));
                    } else if (row % 6 == 0) {
                        tbl1.add(("Del"));
                    } else {
                        tbl1.add(("New"));
                    }
                    tableModel.addRow(tbl1);
                }
                addTableListener();
            }
        };
        SwingUtilities.invokeLater(doRun1);
    }

    private void addTableListener() {
        tableModel.addTableModelListener(new TableModelListener() {
            @Override
            public void tableChanged(TableModelEvent tme) {
                if (tme.getType() == TableModelEvent.UPDATE) {
                    System.out.println("");
                    System.out.println("Cell " + tme.getFirstRow() + ", "
                            + tme.getColumn() + " changed. The new value: "
                            + tableModel.getValueAt(tme.getFirstRow(),
                            tme.getColumn()));
                }
            }
        });
    }

    @Override
    public void valueChanged(ListSelectionEvent le) {
        int row = dialogTable.getSelectedRow();
        int col = dialogTable.getSelectedColumn();
        String str = "Selected Row(s): ";
        int[] rows = dialogTable.getSelectedRows();
        for (int i = 0; i < rows.length; i++) {
            str += rows[i] + " ";
        }
        str += "Selected Column(s): ";
        int[] cols = dialogTable.getSelectedColumns();
        for (int i = 0; i < cols.length; i++) {
            str += cols[i] + " ";
        }
        str += "Selected Cell: " + dialogTable.getSelectedRow() + ", " + dialogTable.getSelectedColumn();
        System.out.println(str);
        Object value = dialogTable.getValueAt(row, col);
        System.out.println(String.valueOf(value));
    }

    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                Forum osFrame = new Forum();
            }
        });
    }

    public Forum() {
        tableModel = new MyTableModel();
        dialogTable = new JTable(tableModel) {
            private static final long serialVersionUID = 1L;

            @Override
            public Component prepareRenderer(TableCellRenderer renderer, int row, int column) {
                Component comp = super.prepareRenderer(renderer, row, column);
                JComponent jc = (JComponent) comp;//for Custom JComponent
                if (!isRowSelected(row)) {
                    int modelRow = convertRowIndexToModel(row);
                    boolean type = (Boolean) getModel().getValueAt(modelRow, 2);
                    boolean type1 = (Boolean) getModel().getValueAt(modelRow, 3);
                    comp.setForeground(Color.black);
                    if ((type) && (!type1)) {
                        comp.setBackground(clr1);
                    } else if ((!type) && (type1)) {
                        comp.setBackground(Color.orange);
                    } else if ((!type) || (!type1)) {
                        comp.setBackground(Color.red);
                    } else {
                        comp.setBackground(row % 2 == 0 ? getBackground() : getBackground().darker());
                    }
                    dialogTable.convertRowIndexToView(0);
                } else {
                    comp.setForeground(Color.blue);
                }
                if (!isCellEditable(row, column)) {
                    comp.setForeground(Color.red);
                    comp.setBackground(Color.magenta);
                }
                return comp;
            }
        };
        tableScroll = new JScrollPane(dialogTable, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
                ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        tableScroll.setBorder(null);
        dialogTable.getTableHeader().setReorderingAllowed(false);
        dialogTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        lsDialog = dialogTable.getSelectionModel();
        dialogTable.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
        dialogTable.setRowHeight(20);
        dialogTable.setRowMargin(2);
        dialogTable.setPreferredScrollableViewportSize(dialogTable.getPreferredSize());
        ListSelectionModel rowSelMod = dialogTable.getSelectionModel();
        //ListSelectionModel colSelMod = dialogTable.getColumnModel().getSelectionModel();
        rowSelMod.addListSelectionListener(this);
        //colSelMod.addListSelectionListener(this);        
        fatherCenter = new JPanel();
        fatherCenter.setLayout(new BorderLayout(10, 10));
        fatherCenter.add(tableScroll, BorderLayout.CENTER);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setLayout(new BorderLayout(10, 10));
        frame.add(fatherCenter);
        frame.setPreferredSize(new Dimension(400, 660));
        frame.pack();
        frame.setLocation(150, 150);
        frame.setVisible(true);
        addData();
    }

    private class MyTableModel extends AbstractTableModel {

        private static final long serialVersionUID = 1L;
        private Vector<Vector<Object>> _data;
        private Vector<String> _colNames;
        private boolean[] _columnsVisible = {true, true, true, true, true};

        public MyTableModel() {
            _colNames = new Vector<String>();
            _data = new Vector<Vector<Object>>();
        }

        public MyTableModel(Vector<String> colnames) {
            _colNames = colnames;
            _data = new Vector<Vector<Object>>();
        }

        public void resetTable() {
            _colNames.removeAllElements();
            _data.removeAllElements();
        }

        public void setColumnNames(Vector<String> colNames) {
            _colNames = colNames;
            fireTableStructureChanged();
        }

        public void addRow(Vector<Object> data) {
            _data.add(data);
            fireTableRowsInserted(_data.size() - 1, _data.size() - 1);
        }

        public void removeRowAt(int row) {
            _data.removeElementAt(row);
            fireTableRowsDeleted(row - 1, _data.size() - 1);
        }

        @Override
        public int getColumnCount() {
            return _colNames.size();
        }

        @Override
        public Class<?> getColumnClass(int colNum) {
            switch (colNum) {
                case 0:
                    return Integer.class;
                case 1:
                    return Double.class;
                case 2:
                    return Boolean.class;
                case 3:
                    return Boolean.class;
                default:
                    return String.class;
            }
        }

        @Override
        public boolean isCellEditable(int row, int colNum) {
            switch (colNum) {
                case 2:
                    return false;
                default:
                    return true;
            }
        }

        @Override
        public String getColumnName(int colNum) {
            return _colNames.get(colNum);
        }

        @Override
        public int getRowCount() {
            return _data.size();
        }

        @Override
        public Object getValueAt(int row, int col) {
            Vector<Object> value = _data.get(row);
            return value.get(col);
        }

        @Override
        public void setValueAt(Object newVal, int row, int col) {
            Vector<Object> aRow = _data.elementAt(row);
            aRow.remove(col);
            aRow.insertElementAt(newVal, col);
            fireTableCellUpdated(row, col);
        }

        public void setColumnVisible(int index, boolean visible) {
            _columnsVisible[index] = visible;
            fireTableStructureChanged();
        }
    }
}

答案 1 :(得分:1)

您在getColumnClass方法中遇到的问题也会返回Object,因为您还会获得String列。

您可以通过下一种方式确定该方法:

   @Override
    public Class<?> getColumnClass(int arg0) {
         return longValues[arg0].getClass();
    }

或以其他方式返回列的类。但是你必须在修改你的模型的同时确定这个类。