简体   繁体   中英

JTable cell editor bug

I write a cell editor of JTable. Now it has a bug. I want it to show default value when first time loading. After editing, it will show user input. Run the application, you will understand the bug.

How to fix it ?

Thanks.

package com.swing;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

public class PropPageTest extends JPanel {

    private static final long serialVersionUID = 1555593265606867986L;

    public JTableX table;
    public DefaultTableModel model;
    private String[] col_names = { "Name", "Value" };
    private String[] anchor_values = { "CENTER", "NORTH" };
    public String[] default_value = {"John", "NORTH"};

    public boolean isFirstTimeLoad = true;

    private void createGUI() {
        setLayout(new BorderLayout());

        model = new DefaultTableModel(col_names, 2) {
            private static final long serialVersionUID = 478700329843848400L;
            public String[] prop_names = { "Name", "Anchor" };

            public Object getValueAt(int row, int col) {
                if (col == 0) return prop_names[row];
                if(isFirstTimeLoad){
                    isFirstTimeLoad = false;
                    return default_value[row];
                }
                else {
                    return super.getValueAt(row, col);
                }               
            }

            public boolean isCellEditable(int row, int col) {
                if (col == 0) return false;
                return true;
            }
        };

        table = new JTableX(model);

        JTextField txtFld = new JTextField();
        table.registerCellEditor(0, new DefaultCellEditor(txtFld));

        JComboBox cb = new JComboBox(anchor_values);        
        table.registerCellEditor(1, new DefaultCellEditor(cb));         

        add(table, BorderLayout.CENTER);
    }

    public static void main(String[] args) {
        JFrame f = new JFrame("test");
        f.setSize(300, 350);
        final PropPageTest test = new PropPageTest();
        f.getContentPane().add(test, BorderLayout.CENTER);

        JPanel buttonPanel = new JPanel();
        JButton saveBtn = new JButton("Save");
        buttonPanel.add(saveBtn);
        f.getContentPane().add(buttonPanel, BorderLayout.SOUTH);

        saveBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent arg0) {
                test.table.stopCellEditing();
                String[] newArr = new String[2];
                newArr[0] = test.model.getValueAt(0, 1)+"";
                newArr[1] = test.model.getValueAt(1, 1)+"";
                boolean isTrue = Arrays.equals(test.default_value, newArr);

                System.out.println("new value --" + test.model.getValueAt(0, 1));
                System.out.println("new value --" + test.model.getValueAt(1, 1));
                System.out.println("is true --" + isTrue);
            }
        });

        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
        f.setLocationRelativeTo(null);
    }

    public PropPageTest() {
        createGUI();
    }
}

-- another file

package com.swing;


import java.util.HashMap;
import java.util.Set;

import javax.swing.JTable;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableModel;

public class JTableX extends JTable {
    private static final long serialVersionUID = -7180009397735740833L;
    private final HashMap<Integer, TableCellEditor> rowEditorMap;

    public JTableX(TableModel tm) {
        super(tm);
        rowEditorMap = new HashMap<Integer, TableCellEditor>();
        this.setRowSelectionAllowed(false);
        this.setColumnSelectionAllowed(false);
    }

    public void registerCellEditor(int row, TableCellEditor editor){
        rowEditorMap.put(row, editor);
    }

    public TableCellEditor getCellEditor(int row, int col) {
        TableCellEditor tmpEditor = null;
        if (rowEditorMap != null) tmpEditor = rowEditorMap.get(row);

        if (tmpEditor != null) return tmpEditor;
        return super.getCellEditor(row, col);
    }

    public void stopCellEditing() {
        if (rowEditorMap != null) {
            Set<Integer> keySet = rowEditorMap.keySet();
            for (Integer i : keySet) {
                TableCellEditor tmpEditor = rowEditorMap.get(i);
                if (tmpEditor != null) {                    
                    tmpEditor.stopCellEditing();
                }
            }
        }
    }
}

You can't do that. The JTable (or any other part of the code) is allowed to call getValueAt when it wants to. The method should return what the table actually contains. If you want default values in the table initially, then store these default values in the model.

When the data changes in the model, it must fire a TableModelEvent. This is done automatically by DefaultTableModel when setValueAt is called.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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