CellRendererとCellEditor

ここまでに作ったレンダラーとエディタを統合し、少し汎用的なレンダラーとエディタを実装してみる。

 ■ソースコード
 DefaultTableCellRendererとDefaultCellEditorを継承し、セルのオブジェクトに応じて、レンダラーとエディタを切り替えている。
 なお、Dateオブジェクトのエディタは、以前作ったDateTimePickerをJDialogで囲ったCalendarDialogを作って使用している。

・MyTableCellRenderer.java

package test;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.util.Date;

import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.table.DefaultTableCellRenderer;

public class MyTableCellRenderer extends DefaultTableCellRenderer{
	private static final long serialVersionUID = 1L;
	private TableColorRenderer color;
	private TableFontRenderer font;
	private DateCellRenderer date;
	
	public MyTableCellRenderer(){
		color=new TableColorRenderer(true);
		font=new TableFontRenderer(true);
		date=new DateCellRenderer(true);
	}
	
	@Override
	public Component getTableCellRendererComponent(JTable arg0, Object arg1, boolean arg2, boolean arg3, int arg4, int arg5) {
		if(arg1 instanceof Color){
			return color.getTableCellRendererComponent(arg0, arg1, arg2, arg3, arg4, arg5);
		}else if(arg1 instanceof Boolean){
			JCheckBox b=new JCheckBox();
			b.setBackground(Color.WHITE);
			b.setSelected(((Boolean)arg1).booleanValue());
			return b;
		}else if(arg1 instanceof Date){
			return date.getTableCellRendererComponent(arg0, arg1, arg2, arg3, arg4, arg5);
		}else if(arg1 instanceof Font){
			font.setBackground(Color.WHITE);
			return font.getTableCellRendererComponent(arg0, arg1, arg2, arg3, arg4, arg5);
		}else if(arg1 instanceof JComboBox){
			JComboBox c=(JComboBox)arg1;
			return super.getTableCellRendererComponent(arg0, c.getSelectedItem(), arg2, arg3, arg4, arg5);
		}else if(arg1 instanceof JComponent){
			return (JComponent)arg1;
		}else{
			return super.getTableCellRendererComponent(arg0, arg1, arg2, arg3, arg4, arg5);
		}
	}

}

・MyTableCellEditor.java

package test;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Date;

import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableModel;

public class MyTableCellEditor extends DefaultCellEditor {
	private static final long serialVersionUID = 1L;
	private Component comp;
	private TableColorEditor color;
	private TableFontEditor font;
	private CalendarDialog cal;
	private Object val;
	
	public MyTableCellEditor(){
		super(new JTextField());
		color=new TableColorEditor();
		font=new TableFontEditor();
		cal=new CalendarDialog(JOptionPane.getRootFrame());
	}
	
	@Override
	public Object getCellEditorValue() {
		if(val instanceof Color){
			return color.getCellEditorValue();
		}else if(val instanceof Font){
			return font.getCellEditorValue();
		}else if(val instanceof Date){
			return val;
		}else if(val instanceof Number){
			try{
				if(val instanceof Integer){
					return Integer.parseInt(super.getCellEditorValue().toString());
				}else if(val instanceof Float){
					return Float.parseFloat(super.getCellEditorValue().toString());
				}else if(val instanceof Double){
					return Double.parseDouble(super.getCellEditorValue().toString());
				}else if(val instanceof Long){
					return Long.parseLong(super.getCellEditorValue().toString());
				}else{
					return Double.parseDouble(super.getCellEditorValue().toString());
				}
			}catch(NumberFormatException ne){
				JOptionPane.showMessageDialog(comp,"NumberFormatException","",JOptionPane.ERROR_MESSAGE);
				return val;
			}
		}else{
			if(comp instanceof JCheckBox){
				if(((JCheckBox)comp).isSelected()){
					return Boolean.TRUE;
				}else{
					return Boolean.FALSE;
				}
			}else if(comp instanceof JTextField){
				return ((JTextField)comp).getText();
			}else if(comp instanceof JComboBox){
				return (JComboBox)comp;
			}else if(comp instanceof JButton){
				return (JButton)comp;
			}else if(comp instanceof JLabel){
				return (JLabel)comp;
			}else{
				return super.getCellEditorValue();
			}
		}
	}

	@Override
	public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
		if(value instanceof Boolean){
			JCheckBox b=new JCheckBox();
			b.setBackground(Color.WHITE);
			b.setSelected(((Boolean)value).booleanValue());
			comp=b;
			val=value;
			return comp;
		}else if(value instanceof Font){
			val=value;
			return font.getTableCellEditorComponent(table, value, isSelected, row, column);
		}else if(value instanceof Date){
			final JTable tt=table;
			final int rr=row;
			final int cc=column;
			final Object xx=value;
			JButton tmp=new JButton(((Date)value).toString());
			tmp.addActionListener(new ActionListener(){
				@Override
				public void actionPerformed(ActionEvent arg0) {
					Date dd=(Date)tt.getModel().getValueAt(rr, cc);
					cal.setDate(dd);
					cal.setLocationRelativeTo(tt);
					cal.setVisible(true);
					Date d=cal.getDate();
					if(d!=null){
						val=d;
					}else{
						val=xx;
					}
				}
			});
			return tmp;
		}else if(value instanceof Color){
			val=value;
			return color.getTableCellEditorComponent(table, value, isSelected, row, column);
		}else if(value instanceof JButton){
			JButton tmp=new JButton(((JButton)value).getText());
			ActionListener[] ac=((JButton)value).getActionListeners();
			for(int i=0;i<ac.length;i++){
				tmp.addActionListener(ac[i]);
			}
			comp=tmp;
			val=value;
			return comp;
		}else if(value instanceof JComboBox){
			JComboBox tmp=new JComboBox(((JComboBox)value).getModel());
			ActionListener[] ac=((JComboBox)value).getActionListeners();
			for(int i=0;i<ac.length;i++){
				tmp.addActionListener(ac[i]);
			}
			comp=tmp;
			val=value;
			return comp;
		}else if(value instanceof JLabel){
			JLabel tmp=(JLabel)value;
			comp=tmp;
			val=tmp;
			return comp;
		}else{
			val=value;
			comp=super.getTableCellEditorComponent(table,value,isSelected,row,column);
			return comp;
		}
	}
	
	public static void main(String[] args){
		JFrame f=new JFrame();
		f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		JTable tb=new JTable();
		final DefaultTableModel model=new DefaultTableModel(){
			private static final long serialVersionUID = 1L;
			@Override
			public boolean isCellEditable(int arg0, int arg1) {
				return (arg1==1);
			}
		};
		model.setColumnCount(2);
		model.setRowCount(7);
		model.setColumnIdentifiers(new String[]{"Name","Value"});
		tb.setDefaultEditor(Object.class, new MyTableCellEditor());
		tb.setDefaultRenderer(Object.class, new MyTableCellRenderer());
		model.setValueAt("Color", 0, 0);
		model.setValueAt(Color.RED, 0, 1);
		model.setValueAt("Font", 1, 0);
		model.setValueAt(tb.getFont(), 1, 1);
		model.setValueAt("Date", 2, 0);
		model.setValueAt(new Date(System.currentTimeMillis()), 2, 1);
		model.setValueAt("Button", 3, 0);
		model.setValueAt(new JButton("OK"), 3, 1);
		model.setValueAt("Number", 4, 0);
		model.setValueAt(123, 4, 1);
		model.setValueAt("String", 5, 0);
		model.setValueAt("晴れ", 5, 1);
		model.setValueAt("Boolean", 6, 0);
		model.setValueAt(true, 6, 1);
		
		tb.setModel(model);
		f.getContentPane().setLayout(new BorderLayout());
		f.getContentPane().add(new JScrollPane(tb),BorderLayout.CENTER);
		f.setTitle("Test");
		f.setSize(300,200);
		f.setLocationRelativeTo(null);
		f.setVisible(true);
	}
}

 ■結果
 実行結果は以下のとおり。
 2列目のセルをクリックすると、オブジェクトに適合したエディタが呼び出されます。