上文实现了renderer复用editor的功能,那么反过来editor是否也可以复用renderer的功能呢?而且第一篇提到“通过Java2D来绘制各种天花乱坠的效果”如何实现?这俩个疑问在以下代码中都有了很好的解答,里面有不少技术细节,我就不多说了大家自己仔细看看。
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import java.awt.*;
import java.awt.geom.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
import javax.swing.border.*;
import javax.swing.table.*;
public class TableTest3 extends JFrame
{
JTable table;
Double[] values = new Double[]{new Double(0.1), new Double(0.3), new Double(0.8)};
// model
class TableModel extends AbstractTableModel{
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return values.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return values[rowIndex];
}
public void setValueAt(Object value, int rowIndex, int columnIndex) {
values[rowIndex] = (Double)value;
this.fireTableCellUpdated(rowIndex, 0);
}
public String getColumnName(int columnIndex) {
if(columnIndex == 0){
return "plain";
}else{
return "beauty";
}
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if(columnIndex == 0){
return false;
}else{
return true;
}
}
}
// cell editor
class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
TableCellRenderer renderer;
JButton actionButton;
Object value;
JTable table;
int row;
int column;
JPanel panel = new JPanel(new BorderLayout());
public Editor(TableCellRenderer renderer){
this.renderer = renderer;
actionButton = new JButton(new ImageIcon(TableTest3.class.getResource("dotdotdot.gif")));
actionButton.addActionListener(this);
actionButton.setFocusable(false);
actionButton.setFocusPainted(false);
actionButton.setMargin(new Insets(0, 0, 0, 0));
panel.add(actionButton, BorderLayout.EAST);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column){
this.value = value;
this.table = table;
this.row = row;
this.column = column;
panel.add(renderer.getTableCellRendererComponent(table, value, true, isSelected, row, column));
return panel;
}
public Object getCellEditorValue(){
return value;
}
Double[] values = new Double[]{new Double(0.1), new Double(0.3), new Double(0.8)};
// model
class TableModel extends AbstractTableModel{
public int getColumnCount() {
return 2;
}
public int getRowCount() {
return values.length;
}
public Object getValueAt(int rowIndex, int columnIndex) {
return values[rowIndex];
}
public void setValueAt(Object value, int rowIndex, int columnIndex) {
values[rowIndex] = (Double)value;
this.fireTableCellUpdated(rowIndex, 0);
}
public String getColumnName(int columnIndex) {
if(columnIndex == 0){
return "plain";
}else{
return "beauty";
}
}
public boolean isCellEditable(int rowIndex, int columnIndex) {
if(columnIndex == 0){
return false;
}else{
return true;
}
}
}
// cell editor
class Editor extends AbstractCellEditor implements TableCellEditor, ActionListener {
JSlider slider = new JSlider(JSlider.HORIZONTAL, 0, 100, 50);
TableCellRenderer renderer;
JButton actionButton;
Object value;
JTable table;
int row;
int column;
JPanel panel = new JPanel(new BorderLayout());
public Editor(TableCellRenderer renderer){
this.renderer = renderer;
actionButton = new JButton(new ImageIcon(TableTest3.class.getResource("dotdotdot.gif")));
actionButton.addActionListener(this);
actionButton.setFocusable(false);
actionButton.setFocusPainted(false);
actionButton.setMargin(new Insets(0, 0, 0, 0));
panel.add(actionButton, BorderLayout.EAST);
}
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column){
this.value = value;
this.table = table;
this.row = row;
this.column = column;
panel.add(renderer.getTableCellRendererComponent(table, value, true, isSelected, row, column));
return panel;
}
public Object getCellEditorValue(){
return value;
}
public void
actionPerformed(ActionEvent e) {
int intValue = (int)(((Number)value).doubleValue() * 100);
slider.setValue(intValue);
int result = JOptionPane.showOptionDialog(TableTest3.this,
slider, "change value",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if(result==JOptionPane.OK_OPTION) {
this.value = new Double(slider.getValue()/100.0);
this.fireEditingStopped();
}else{
this.fireEditingCanceled();
}
}
int intValue = (int)(((Number)value).doubleValue() * 100);
slider.setValue(intValue);
int result = JOptionPane.showOptionDialog(TableTest3.this,
slider, "change value",
JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE, null, null, null);
if(result==JOptionPane.OK_OPTION) {
this.value = new Double(slider.getValue()/100.0);
this.fireEditingStopped();
}else{
this.fireEditingCanceled();
}
}
}
// cell render
class Renderer extends JComponent implements TableCellRenderer{
Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
Border focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
private boolean hasFocus;
private Double value;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(hasFocus){
this.setBorder(focusBorder);
}else{
this.setBorder(noFocusBorder);
}
Dimension size = this.getSize();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0, Color.BLUE, size.width, 0, Color.YELLOW, true);
g2.setPaint(gp);
g2.fillRect(0, 0, size.width, size.height);
g2.setColor(Color.GREEN);
double r = (size.height - 8) / 2.0;
int centerX = (int)(size.width * value.doubleValue());
int centerY = (int)r;
g2.fill(new Ellipse2D.Double(centerX-r, centerY-r+4, r * 2, r * 2));
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
this.hasFocus = hasFocus;
this.value = (Double)value;
this.setToolTipText(value + "");
return this;
}
}
// cell render
class Renderer extends JComponent implements TableCellRenderer{
Border noFocusBorder = new EmptyBorder(1, 1, 1, 1);
Border focusBorder = UIManager.getBorder("Table.focusCellHighlightBorder");
private boolean hasFocus;
private Double value;
public void paintComponent(Graphics g) {
super.paintComponent(g);
if(hasFocus){
this.setBorder(focusBorder);
}else{
this.setBorder(noFocusBorder);
}
Dimension size = this.getSize();
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
GradientPaint gp = new GradientPaint(0, 0, Color.BLUE, size.width, 0, Color.YELLOW, true);
g2.setPaint(gp);
g2.fillRect(0, 0, size.width, size.height);
g2.setColor(Color.GREEN);
double r = (size.height - 8) / 2.0;
int centerX = (int)(size.width * value.doubleValue());
int centerY = (int)r;
g2.fill(new Ellipse2D.Double(centerX-r, centerY-r+4, r * 2, r * 2));
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
this.hasFocus = hasFocus;
this.value = (Double)value;
this.setToolTipText(value + "");
return this;
}
}
public TableTest3(){
super("renderer used by editor");
table = new JTable(new TableModel());
TableColumn tableColumn = table.getColumnModel().getColumn(1);
tableColumn.setCellRenderer(new Renderer());
tableColumn.setCellEditor(new Editor(new Renderer()));
this.getContentPane().setLayout(new BorderLayout());
this.getContentPane().add(new JScrollPane(table), BorderLayout.CENTER);
this.setSize(500, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public static void main(String[]
args) {
new TableTest3().show();
new TableTest3().show();
}
}