JTable渲染含多复选框JPanel的单元格时出现重复JCheckBox问题
问题根源
你的JCheckBox重复是因为渲染器和编辑器的JPanel是类级别的成员变量,每次getTableCellRendererComponent/getTableCellEditorComponent被调用(窗口拖拽、缩放、滚动、单元格重绘都会触发这些方法调用)时,你只往面板里新增复选框,没有先清空面板上已有的旧组件,多次调用后就会堆叠大量重复复选框。
调整后的渲染器代码
public class CheckBoxCellRenderer extends JPanel implements TableCellRenderer { private static final long serialVersionUID = -6142180432465856711L; private final JPanel panel = new JPanel(new FlowLayout()); public CheckBoxCellRenderer() { setOpaque(true); // 把内容面板加到当前渲染器容器中 add(panel); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { // 核心修复:先清空所有旧组件 panel.removeAll(); // 同步表格选中状态的背景色,避免样式割裂 if (isSelected) { setBackground(table.getSelectionBackground()); panel.setBackground(table.getSelectionBackground()); } else { setBackground(table.getBackground()); panel.setBackground(table.getBackground()); } if(value!=null){ Set<Integer> intValues = (Set<Integer>) value; for(Integer intvalue : intValues){ JCheckBox checkBox = new JCheckBox(intvalue.toString()); checkBox.setBackground(panel.getBackground()); panel.add(checkBox); } } // 自适应行高 table.setRowHeight(row, this.getPreferredSize().height); panel.revalidate(); panel.repaint(); return this; } }
调整后的单元格编辑器代码
class CheckBoxCellEditor extends AbstractCellEditor implements TableCellEditor{ private static final long serialVersionUID = 7910769369831526953L; private final JPanel panel = new JPanel(new FlowLayout()); // 缓存当前单元格的复选框实例,用于后续获取编辑结果 private final List<JCheckBox> currentCheckBoxes = new ArrayList<>(); @Override public Object getCellEditorValue() { // 补充编辑值返回逻辑,返回用户选中的Integer集合 Set<Integer> selectedValues = new HashSet<>(); for (JCheckBox cb : currentCheckBoxes) { if (cb.isSelected()) { selectedValues.add(Integer.valueOf(cb.getText())); } } return selectedValues; } @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) { // 核心修复:清空旧组件和缓存 panel.removeAll(); currentCheckBoxes.clear(); panel.setBackground(isSelected ? table.getSelectionBackground() : table.getBackground()); if(value!=null){ Set<Integer> intValues = (Set<Integer>) value; for(Integer intvalue : intValues){ JCheckBox checkBox = new JCheckBox(intvalue.toString()); checkBox.setBackground(panel.getBackground()); panel.add(checkBox); currentCheckBoxes.add(checkBox); } } table.setRowHeight(row, panel.getPreferredSize().height); return panel; } }
额外注意点
- 不要复用渲染器/编辑器里的旧组件,每次重绘都先清空再新增是Swing单元格渲染的标准写法
- 如果需要复选框默认选中对应值,可以在新增复选框时判断值集合,调用
setSelected(true)设置状态
内容的提问来源于stack exchange,提问作者Akilesh Balireddi
相关产品推荐
相关产品推荐

