我在JTable Header中有Checkbox,我正在使用Nimbus L& F并自定义标题背景,但是复选框的背景采用默认的灰色背景,而不是自定义的灰色背景。
以下是CheckboxRenderer类
public class CheckBoxHeader extends JCheckBox implements TableCellRenderer{
public CheckBoxHeader(ItemListener itemListener) {
addItemListener(itemListener);
setHorizontalAlignment(SwingConstants.CENTER);
setOpaque(true);
}
public Component getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
JTableHeader header = table.getTableHeader();
Color bg = header.getBackground();
setBackground(new Color(bg.getRed(), bg.getGreen(), bg.getBlue()));
return this;
}
并在表格中
TableColumn tc = getColumnModel().getColumn(0);
tc.setCellEditor(getDefaultEditor(Boolean.class));
tc.setCellRenderer(getDefaultRenderer(Boolean.class));
((JComponent)getDefaultRenderer(Boolean.class)).setOpaque(true);
tc.setHeaderRenderer(new CheckBoxHeader());
AFAIK能够正确呈现它应该使用DefaultTableCellRenderer渲染的标题,但我没有为它做好准备。有什么建议吗?
答案 0 :(得分:4)
我不确定它是否适用于所有LnF(仅测试Windows 7,Java 1.7.0_03):
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;
public class NimbusHeaderCheckBox {
public JComponent makeUI() {
Object[] columnNames = {Status.INDETERMINATE, "Integer", "String"};
Object[][] data = {{true, 1, "b"}, {false, 9, "a"}, {true, 5, "c"}};
DefaultTableModel model = new DefaultTableModel(data, columnNames) {
@Override public Class<?> getColumnClass(int column) {
return getValueAt(0, column).getClass();
}
};
JTable table = new JTable(model);
model.addTableModelListener(new HeaderCheckBoxHandler(table));
TableCellRenderer r = new HeaderRenderer(table.getTableHeader(), 0);
table.getColumnModel().getColumn(0).setHeaderRenderer(r);
//<ins>
TableCellRenderer leftAlign = new LeftAlignHeaderRenderer();
table.getColumnModel().getColumn(1).setHeaderRenderer(leftAlign);
table.getColumnModel().getColumn(2).setHeaderRenderer(leftAlign);
//</ins>
table.getTableHeader().setReorderingAllowed(false);
return new JScrollPane(table);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override public void run() { createAndShowGUI(); }
});
}
public static void createAndShowGUI() {
try {
//UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels())
if ("Nimbus".equals(laf.getName())) UIManager.setLookAndFeel(laf.getClassName());
} catch(Exception e) {
e.printStackTrace();
}
JFrame frame = new JFrame();
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
frame.getContentPane().add(new NimbusHeaderCheckBox().makeUI());
frame.setSize(320, 240);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
class HeaderRenderer extends JCheckBox implements TableCellRenderer {
public HeaderRenderer(JTableHeader header, final int targetColumnIndex) {
super((String)null);
setOpaque(false);
setFont(header.getFont());
header.addMouseListener(new MouseAdapter() {
@Override public void mouseClicked(MouseEvent e) {
JTableHeader header = (JTableHeader)e.getSource();
JTable table = header.getTable();
TableColumnModel columnModel = table.getColumnModel();
int vci = columnModel.getColumnIndexAtX(e.getX());
int mci = table.convertColumnIndexToModel(vci);
if(mci == targetColumnIndex) {
TableColumn column = columnModel.getColumn(vci);
Object v = column.getHeaderValue();
boolean b = Status.DESELECTED.equals(v)?true:false;
TableModel m = table.getModel();
for(int i=0; i<m.getRowCount(); i++) m.setValueAt(b, i, mci);
column.setHeaderValue(b?Status.SELECTED:Status.DESELECTED);
}
}
});
}
@Override public Component getTableCellRendererComponent(
JTable tbl, Object val, boolean isS, boolean hasF, int row, int col) {
if(val instanceof Status) {
switch((Status)val) {
case SELECTED:
setSelected(true); setEnabled(true); break;
case DESELECTED:
setSelected(false); setEnabled(true); break;
case INDETERMINATE:
setSelected(true); setEnabled(false); break;
}
} else {
setSelected(true); setEnabled(false);
}
TableCellRenderer r = tbl.getTableHeader().getDefaultRenderer();
JLabel l=(JLabel)r.getTableCellRendererComponent(tbl, null, isS, hasF, row, col);
l.setIcon(new CheckBoxIcon(this));
l.setText(null); //XXX Nimbus LnF ???
////This block has no effect at all as all the columns are center aligned
////(pointed out by rcnpl)
//if(tbl.convertColumnIndexToModel(col)==0) {
// l.setHorizontalAlignment(SwingConstants.CENTER);
//} else {
// l.setHorizontalAlignment(SwingConstants.LEFT);
//}
//<ins>
l.setHorizontalAlignment(SwingConstants.CENTER);
//</ins>
return l;
}
}
//<ins>
class LeftAlignHeaderRenderer implements TableCellRenderer {
@Override public Component getTableCellRendererComponent(
JTable t, Object v, boolean isS, boolean hasF, int row, int col) {
TableCellRenderer r = t.getTableHeader().getDefaultRenderer();
JLabel l=(JLabel)r.getTableCellRendererComponent(t, v, isS, hasF, row, col);
l.setHorizontalAlignment(SwingConstants.LEFT);
return l;
}
}
//</ins>
enum Status { SELECTED, DESELECTED, INDETERMINATE }
class CheckBoxIcon implements Icon {
private final JCheckBox check;
public CheckBoxIcon(JCheckBox check) {
this.check = check;
}
@Override public int getIconWidth() {
return check.getPreferredSize().width;
}
@Override public int getIconHeight() {
return check.getPreferredSize().height;
}
@Override public void paintIcon(Component c, Graphics g, int x, int y) {
SwingUtilities.paintComponent(
g, check, (Container)c, x, y, getIconWidth(), getIconHeight());
}
}
class HeaderCheckBoxHandler implements TableModelListener {
private final JTable table;
public HeaderCheckBoxHandler(JTable table) {
this.table = table;
}
@Override public void tableChanged(TableModelEvent e) {
if(e.getType()==TableModelEvent.UPDATE && e.getColumn()==0) {
int mci = 0;
int vci = table.convertColumnIndexToView(mci);
TableColumn column = table.getColumnModel().getColumn(vci);
Object title = column.getHeaderValue();
if(!Status.INDETERMINATE.equals(title)) {
column.setHeaderValue(Status.INDETERMINATE);
} else {
int selected = 0, deselected = 0;
TableModel m = table.getModel();
for(int i=0; i<m.getRowCount(); i++) {
if(Boolean.TRUE.equals(m.getValueAt(i, mci))) {
selected++;
} else {
deselected++;
}
}
if(selected==0) {
column.setHeaderValue(Status.DESELECTED);
} else if(deselected==0) {
column.setHeaderValue(Status.SELECTED);
} else {
return;
}
}
table.getTableHeader().repaint();
}
}
}