我有一个有3列的JTable,第一列是简单文本,另外2列是JComboBox。列名和列电子邮件都有自定义TableCellEditor和TableCellRenderer。
有时,当我单击未选中的行中的组合框时,将不会使用正确的选定颜色(蓝色)绘制单元格。
为了便于说明,TableCellRenderer绘制粉红色单元格,TableCellEditor绘制橙色单元格。
JTable为isCellSelected()返回false,更具体地说,在JTable editCellAt()处为isRowSelected()返回false。但是,当渲染器调用isCellSelected()时,它返回true,因此渲染器颜色正确。
我无法弄清楚这里出了什么问题。 我的SSCCE:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractCellEditor;
import javax.swing.DefaultListCellRenderer;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.WindowConstants;
import javax.swing.plaf.basic.BasicComboBoxEditor;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableColumnModel;
import org.iii.snsi.streamcenter.main.Main;
public class EditorNotSelectedColorFrame {
public JComponent makeUI() {
JTable table = new JTable();
DefaultTableModel model = new DefaultTableModel(new String[]{"COL 1", "COL 2", "COL 3"}, 0);
table.setModel(model);
for (int i = 0; i < 5; i++) {
Object[] row = new Object[3];
row[0] = new MyListItem(new String[]{"item a", "item b", "item c"});
row[1] = new MyListItem(new String[]{"item d", "item e", "item f"});
row[2] = new MyListItem(new String[]{"item g", "item h", "item i"});
model.addRow(row);
}
MyTableCellEditor editor = new MyTableCellEditor(Color.orange, Color.BLACK);
MyTableCellRenderer renderer = new MyTableCellRenderer(Color.pink, Color.BLACK);
TableColumnModel columnModel = table.getColumnModel();
columnModel.getColumn(0).setCellEditor(editor);
columnModel.getColumn(1).setCellEditor(editor);
columnModel.getColumn(2).setCellEditor(editor);
columnModel.getColumn(0).setCellRenderer(renderer);
columnModel.getColumn(1).setCellRenderer(renderer);
columnModel.getColumn(2).setCellRenderer(renderer);
JPanel panel = new JPanel(new BorderLayout());
panel.add(new JScrollPane(table));
return panel;
}
public static void main(String... args) {
try {
for (UIManager.LookAndFeelInfo info : UIManager.getInstalledLookAndFeels()) {
if ("Windows".equals(info.getName())) {
UIManager.setLookAndFeel(info.getClassName());
break;
}
}
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
JFrame f = new JFrame();
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
f.getContentPane().add(new EditorNotSelectedColorFrame().makeUI());
f.setSize(320, 240);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
});
}
}
class MyListItem<T> {
private ArrayList<T> items = new ArrayList<>();
private Integer selectedIndex = -1;
public MyListItem(T[] items) {
selectedIndex = -1;
this.items.addAll(Arrays.asList(items));
}
public ArrayList<T> getItems() {
return items;
}
public void setSelectedIndex(Integer selectedIndex) {
this.selectedIndex = selectedIndex;
}
public Integer getSelectedIndex() {
return selectedIndex;
}
}
class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor {
private Color unselectedBackground;
private Color unselectedForeground;
private JMyComboBox comboBox;
private MyListItem myListItem;
public MyTableCellEditor(Color bg, Color fg) {
unselectedBackground = bg;
unselectedForeground = fg;
comboBox = new JMyComboBox(bg, fg);
comboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
stopCellEditing();
}
});
}
@Override
public Object getCellEditorValue() {
int idx = comboBox.getSelectedIndex();
if (idx > -1) {
myListItem.setSelectedIndex(comboBox.getSelectedIndex());
}
return myListItem;
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
comboBox.removeAllItems();
if (value instanceof MyListItem) {
myListItem = (MyListItem) value;
for (Object item : myListItem.getItems()) {
comboBox.addItem(item.toString());
}
comboBox.setSelectedIndex(myListItem.getSelectedIndex());
} else {
myListItem = null;
}
if (isSelected) {
comboBox.setForeground(table.getSelectionForeground());
comboBox.setBackground(table.getSelectionBackground());
} else {
comboBox.setForeground(unselectedForeground);
comboBox.setBackground(unselectedBackground);
}
return comboBox;
}
}
class MyTableCellRenderer extends DefaultTableCellRenderer {
private Color unselectedBackground;
private Color unselectedForeground;
private JMyComboBox comboBox;
public MyTableCellRenderer(Color bg, Color fg) {
super();
unselectedBackground = bg;
unselectedForeground = fg;
comboBox = new JMyComboBox(bg, fg);
}
@Override
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
comboBox.removeAllItems();
if (value instanceof MyListItem) {
MyListItem cellItem = (MyListItem) value;
for (Object item : cellItem.getItems()) {
comboBox.addItem(item.toString());
}
comboBox.setSelectedIndex(cellItem.getSelectedIndex());
}
if (isSelected) {
comboBox.setForeground(table.getSelectionForeground());
comboBox.setBackground(table.getSelectionBackground());
} else {
comboBox.setForeground(unselectedForeground);
comboBox.setBackground(unselectedBackground);
}
return comboBox;
}
}
class JMyComboBox extends JComboBox<String> {
private MyComboBoxEditor editor = new MyComboBoxEditor();
private MyComboBoxRenderer renderer = new MyComboBoxRenderer();
public JMyComboBox(Color bg, Color fg) {
super();
setEditable(true);
setEditor(editor);
setRenderer(renderer);
editor.setColors(bg, fg);
renderer.setColors(bg, fg);
}
@Override
public void setBackground(Color bg) {
super.setBackground(bg);
if (editor != null) {
editor.setColors(bg, getForeground());
}
}
@Override
public void setForeground(Color fg) {
super.setForeground(fg);
if (editor != null) {
editor.setColors(getBackground(), fg);
}
}
}
class MyComboBoxEditor extends BasicComboBoxEditor {
private JLabel label = new JLabel();
public MyComboBoxEditor() {
super();
label.setOpaque(true);
}
public void setColors(Color background, Color foreground) {
label.setBackground(background);
label.setForeground(foreground);
}
@Override
public void setItem(Object anObject) {
super.setItem(anObject);
label.setText(((JTextField) super.getEditorComponent()).getText());
}
@Override
public Component getEditorComponent() {
return label;
}
}
class MyComboBoxRenderer extends DefaultListCellRenderer {
private Color unselectedBackground;
private Color unselectedForeground;
public void setColors(Color background, Color foreground) {
this.unselectedBackground = background;
this.unselectedForeground = foreground;
}
@Override
public Component getListCellRendererComponent(JList<?> list, Object value,
int index, boolean isSelected, boolean cellHasFocus) {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
if (!isSelected) {
if (unselectedBackground != null) {
setBackground(unselectedBackground);
}
if (unselectedForeground != null) {
setForeground(unselectedForeground);
}
}
return this;
}
}