Question

I have been thinking a lot to solve this mistake. But unfortunately I came to final cnclusion that I need help of professionals.

Please, copy,paste this code to see issue:

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

Now please click twice on that big button called 'Update Table'. As you see column that should display checkbox as it holds boolean values do not do that but instead displays String true or false.

This code emulates my real workflow. So, how to update tablemodel to have boolean columns with checkbozes.

Thanks!

Was it helpful?

Solution

take this as simple start point

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

OTHER TIPS

Your problem in getColumnClass method as you see you also return Object because of that you also get String columns.

You can determine that method in next way:

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

Or return Classes for your columns in another way. But you must to determine this Classes while cunstruct your model.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top