jtbale属性编辑器 JCheckBox显示问题

     目前在用jtable做一个 属性编辑器,table就二列,一列属性名,一列属性值。 需要根据属性值动态生成编辑器(JComboBox、JCheckBox、JTextArea)。

 

基本功能已实现 现在存在如下问题:

 

1.JCheckBox显示没问题,但是点击时位置不正确(会跑到单元格最左边)。

2.JTextArea显示有问题,没有一开始就换行显示,要编辑的时候才换行显示。

 

请大家帮忙看一下,谢谢大家了!

 

 

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Vector;

import javax.swing.AbstractCellEditor;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultListSelectionModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextArea;
import javax.swing.ListSelectionModel;
import javax.swing.WindowConstants;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumnModel;

public class PropertyJtable extends JTable {

    public PropertyJtable(Vector rowData, Vector columnNames) {
        super(rowData, columnNames);
    }

    public JComboBox getJComboBox() {
        JComboBox comboBox = new JComboBox();
        comboBox.addItem("red");
        comboBox.addItem("green");
        comboBox.addItem("blue");
        return comboBox;
    }

    public static void main(String[] args) {
        JFrame frame = new JFrame("属性编辑器");
        frame.setSize(250, 200);
        frame.setPreferredSize(new Dimension(250, 200));
        frame.setLayout(new BorderLayout());
        frame.setLocationRelativeTo(null);

        Vector title = new Vector();
        title.add("Property");
        title.add("Value");
            
        JTable jtable = new PropertyJtable(new Vector(), title);
        JScrollPane scrollPane = new JScrollPane(jtable);

        DefaultTableModel model = (DefaultTableModel) jtable.getModel();
        model.addRow(new Object[] { "name", "阿呆" });
        model.addRow(new Object[] { "是否显示", new Boolean(true) });
        model.addRow(new Object[] { "颜色1", "red" });
        model.addRow(new Object[] { "颜色2", "blue" });
        model.addRow(new Object[] { "年龄", "24" });
        model.addRow(new Object[] { "备注", "山东分\n舵是否公司的\n故事啊发放" });
        jtable.getColumnModel().getColumn(0).setPreferredWidth(50);
        jtable.getColumnModel().getColumn(1).setPreferredWidth(150);

        frame.add(scrollPane, BorderLayout.CENTER);
        JButton printButton = new JButton("关闭");
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        printButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent event) {
                System.exit(0);
            }
        });

        frame.add(printButton, BorderLayout.SOUTH);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    // 根据值来设置单元格类型
    public TableCellEditor getCellEditor(int row, int col) {
        TableCellEditor editor = super.getCellEditor(row, col);
        // JCheckBox
        if ("true".equals(getValueAt(row, col).toString())
                || "false".equals(getValueAt(row, col).toString())) {
            // editor=super.getDefaultEditor(JCheckBox.class);
            editor = new DefaultCellEditor(new JCheckBox());
        }
        // JComboBox
        if ("red".equals(getValueAt(row, col).toString())
                || "green".equals(getValueAt(row, col).toString())
                || "blue".equals(getValueAt(row, col).toString())) {
            editor = new DefaultCellEditor(getJComboBox());
        }
        // 字数大于10 使用JTextArea
        if (getValueAt(row, col).toString().length() > 10) {
            editor = new JTextAreaEditor();
        }
        return editor;
    }

    // 单元格渲染
    public TableCellRenderer getCellRenderer(int row, int col) {
        TableCellRenderer renderer = super.getCellRenderer(row, col);
        if ("true".equals(getValueAt(row, col).toString())
                || "false".equals(getValueAt(row, col).toString())) {
            renderer = super.getDefaultRenderer(Boolean.class);
        }
        return renderer;
    }

    // 第一行不可编辑
    public boolean isCellEditable(int row, int col) {
        return (col != 0);
    }

    /*
     * 重写方法 单选模式 (non-Javadoc)
     * 
     * @see javax.swing.JTable#createDefaultSelectionModel()
     */
    protected ListSelectionModel createDefaultSelectionModel() {
        DefaultListSelectionModel defaultListSelectionModel = new DefaultListSelectionModel();
        defaultListSelectionModel
                .setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        return defaultListSelectionModel;
    }

    class JTextAreaEditor extends AbstractCellEditor implements TableCellEditor {

        protected JTextArea myEditor;

        public Component getTableCellEditorComponent(JTable table,
                Object value, boolean isSelected, int row, int column) {
            if (null == myEditor) {
                myEditor = new JTextArea();
            }
            myEditor.setText((String) value);
            TableColumnModel columnModel = table.getColumnModel();
            myEditor.setSize(columnModel.getColumn(column).getWidth(), 5);
            int heightWanted = (int) myEditor.getPreferredSize().getHeight();
            if (heightWanted != table.getRowHeight(row)) {
                table.setRowHeight(row, heightWanted);
            }
            return myEditor;
        }

        @Override
        public Object getCellEditorValue() {
            return myEditor.getText();
        }

    }
}

1.显示的时候你要自适应显示宽度高度,还需要对该列写个render,你写的render只是显示一个textarea组件,具体可以参考我写的
class TableCellTextAreaRenderer extends JTextArea implements TableCellRenderer {
public TableCellTextAreaRenderer() {
setLineWrap(true);
setWrapStyleWord(true);
}

public Component getTableCellRendererComponent(JTable table,Object value,boolean isSelected,boolean hasFocus,int row,int column) {
    // 计算当下行的最佳高度
    int maxPreferredHeight = 0;
    for (int i = 0; i < table.getColumnCount(); i++) {
        setText("" + table.getValueAt(row, i));
        setSize(table.getColumnModel().getColumn(column).getWidth(), 0);
        maxPreferredHeight = Math.max(maxPreferredHeight, getPreferredSize().height);
    }

    if (table.getRowHeight(row) != maxPreferredHeight)  // 少了这行则不能重绘
        table.setRowHeight(row, maxPreferredHeight);

    setText(value == null ? "" : value.toString());
    return this;
}

}

2.关于jcheckbox跳到左边的问题,我以前也遇到到,好像只要该列值为boolean型,就不需要另写个render或者editor了。。会默认用jcheckbox展示