在jTable中设置jCheckBox不可见

我有一个带有两列的jTable 。第一列设置为布尔值(用于复选框),第二列设置为字符串值。当我使用Netbeans ,复选框被添加到第一列的所有行中。 我试图仅为那些在第二列中具有值的行添加它。 我用代码试了一下,

 private class CustomCellRenderer extends DefaultTableCellRenderer { /* (non-Javadoc) * @see javax.swing.table.DefaultTableCellRenderer#getTableCellRendererComponent(javax.swing.JTable, java.lang.Object, boolean, boolean, int, int) */ @Override public Component getTableCellRendererComponent(JTable table, Object value,boolean isSelected, boolean hasFocus, int row, int column) { Component rendererComp = super.getTableCellRendererComponent(table, value, isSelected, hasFocus,row, column); for(int i=row;i<jTable1.getRowCount();i++){ if(jTable1.getValueAt(i, 1)==null){ jTable1.setValueAt(true, i, 0); //checkbox.setOpaque(false); } } return this ; } } 

如果我尝试为上面的for循环中的所有其他复选框设置值’true’,那么它运行良好。 如何将其设置为其余行不可见。

编辑:

我在这里添加我的代码

  package e2; import java.awt.Component; import javax.swing.JCheckBox; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; public class JTable_CheckBox extends javax.swing.JFrame { /** Creates new form JTable_CheckBox */ JCheckBox checkbox=new JCheckBox(); public JTable_CheckBox() { initComponents(); jTable1.setValueAt("John",0,1); jTable1.setValueAt("James",1,1); jTable1.setValueAt("Janet",2,1); jTable1.setValueAt("Tom",3,1); jTable1.getColumnModel().getColumn(0).setCellRenderer(new CheckboxCellRenderer()); } public static void main(String args[]) { java.awt.EventQueue.invokeLater(new Runnable() { public void run() { new JTable_CheckBox().setVisible(true); } }); } public class CheckboxCellRenderer extends JCheckBox implements TableCellRenderer { public CheckboxCellRenderer() { setOpaque(false); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { //here i am trying to set check box invisible,but here i am setting as selected for(int i=row;i<table.getRowCount();i++){ if(table.getValueAt(i, 1)==null){ table.setValueAt(true, i, 0); //checkbox.setOpaque(false); } } return this; } } // Variables declaration - do not modify private javax.swing.JScrollPane jScrollPane1; private javax.swing.JTable jTable1; // End of variables declaration } 

表中使用TableCellRenderer来绘制重用相同组件的表的各个单元格。 该表自动设置正确的上下文,组件边界并为需要绘制的表的每个单元getTableCellRendererComponent (第一次显示表格时,所有可见单元格都被绘制,然后在TableModel通知后显示相应的单元格重新粉刷)。

因此,在TableCellRenderer中,您当然不需要遍历表的单元格来尝试设置值。 这没有意义。 请记住,您正在实现具有您需要尊重的合同的TableCellRender接口。

来自Javadoc:

返回用于绘制单元格的组件。 此方法用于在绘制之前适当地配置渲染器。

所以你需要做的就是返回一个正确表示value参数的组件。 可能,您可以修改组件以指示单元格是否具有焦点,以及当前是否选择了单元格。 没有更多,没有更少。

现在,提出您的问题:如果您只想为具有值的行显示一个复选框,则实现TableCellRenderer返回一个复选框,并根据第1列(第二列)中的值修改其可见性。

这个例子有效:

 import java.awt.BorderLayout; import java.awt.Component; import java.awt.FlowLayout; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.util.ArrayList; import java.util.List; import javax.swing.JCheckBox; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableCellRenderer; public class TestTable { public class CheckboxCellRenderer extends JPanel implements TableCellRenderer { private JCheckBox checkBox; public CheckboxCellRenderer() { super(new FlowLayout(FlowLayout.CENTER, 0, 0)); setOpaque(false); checkBox = new JCheckBox(); checkBox.setOpaque(false); checkBox.setHorizontalAlignment(JCheckBox.CENTER); add(checkBox); } @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Object valueInColumn1 = table.getValueAt(row, 1); checkBox.setVisible(valueInColumn1 != null); checkBox.setSelected(value instanceof Boolean && (Boolean) value); return this; } } private JFrame f; private JTable table; private class MyObject { private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this); private String value; private boolean selected; public MyObject(String value) { this.value = value; } public PropertyChangeSupport getPropertyChangeSupport() { return propertyChangeSupport; } public String getValue() { return value; } public void setValue(String value) { this.value = value; propertyChangeSupport.firePropertyChange("value", null, value); } public boolean isSelected() { return selected; } public void setSelected(boolean selected) { if (this.selected != selected) { this.selected = selected; propertyChangeSupport.firePropertyChange("selected", !selected, selected); } } } protected void initUI() { List objects = new ArrayList(); for (int i = 0; i < 200; i++) { MyObject object = new MyObject(i % 3 == 1 ? null : "Row " + (i + 1)); objects.add(object); } table = new JTable(new MyTableModel(objects)); table.setRowHeight(20); table.getColumnModel().getColumn(0).setCellRenderer(new CheckboxCellRenderer()); f = new JFrame(); f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); f.add(new JScrollPane(table), BorderLayout.CENTER); f.pack(); f.setVisible(true); } public class MyTableModel extends AbstractTableModel implements PropertyChangeListener { private List objects; public MyTableModel(List objects) { super(); this.objects = objects; for (MyObject object : objects) { object.getPropertyChangeSupport().addPropertyChangeListener(this); } } @Override public void propertyChange(PropertyChangeEvent evt) { if (evt.getSource() instanceof MyObject) { int index = objects.indexOf(evt.getSource()); fireTableRowsUpdated(index, index); } } @Override public int getColumnCount() { return 2; } @Override public int getRowCount() { return objects.size(); } public MyObject getValueAt(int row) { return objects.get(row); } @Override public Object getValueAt(int rowIndex, int columnIndex) { switch (columnIndex) { case 0: return getValueAt(rowIndex).isSelected(); case 1: return getValueAt(rowIndex).getValue(); } return null; } @Override public void setValueAt(Object value, int rowIndex, int columnIndex) { if (columnIndex == 0) { getValueAt(rowIndex).setSelected(Boolean.TRUE.equals(value)); } } @Override public boolean isCellEditable(int rowIndex, int columnIndex) { return columnIndex == 0 && getValueAt(rowIndex).getValue() != null; } @Override public Class getColumnClass(int column) { switch (column) { case 0: return Boolean.class; case 1: return String.class; } return Object.class; } @Override public String getColumnName(int column) { switch (column) { case 0: return "Selected"; case 1: return "Value"; } return null; } } public static void main(String[] args) throws ClassNotFoundException, InstantiationException, IllegalAccessException, UnsupportedLookAndFeelException { UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); SwingUtilities.invokeLater(new Runnable() { @Override public void run() { new TestTable().initUI(); } }); } } 

PS:我没有考虑isSelected / hasFocus,如果你想我们可以稍后再说。

首先,您必须了解渲染器/编辑器机制。 要实现这一点,请阅读Swing标签说明中引用的在线教程中的相应章节。

其次,为了获得最佳视觉效果,请通过重新使用JTable本身安装的默认值来实现自定义渲染器,例如:

 public class CompoundRenderer implements TableCellRenderer { TableCellRenderer booleanRenderer; TableCellRenderer defaultRenderer; public CompoundRenderer(TableCellRenderer booleanRenderer, TableCellRenderer defaultRenderer) { this.booleanRenderer = booleanRenderer; this.defaultRenderer = defaultRenderer; } @Override public Component getTableCellRendererComponent(..., Object value, ....) { if (value instanceof Boolean) { return booleanRenderer.getTableCellRendererComponent(...); } return defaultRenderer.getTableCellRendererComponent(...); } } // usage JTable myTable ... TableCellRenderer compound = new CompoundRenderer( myTable.getDefaultRenderer(Boolean.class), myTable.getDefaultRenderer(Object.class)); // either register for all booleans myTable.setDefaultRenderer(Boolean.class, compound); // or register for a particular column myTable.getColumnModel().getColumn(someIndex).setCellRenderer(compound); 

俗话说:很多方式都会导致罗马。

我刚遇到类似的问题,即我有一个包含复选框的列的表,我想隐藏第一行中的复选框。 在评估了其他解决方案之后,我想出了一些略有不同的东西(适用于原始问题):

创建一个特定的CheckBoxRenderer类:

 public class CheckBoxRenderer extends JCheckBox implements TableCellRenderer { CheckBoxRenderer() { setHorizontalAlignment(JLabel.CENTER); } public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) { Object valueInColumn1 = table.getValueAt(row, 1); if (valueInColumn1 == null) { JLabel x=new JLabel(); return x; } setSelected((value != null && ((Boolean) value).booleanValue())); return this; } } 

步骤2:将渲染器附加到te列:

 paramTable.getColumnModel().getColumn(3).setCellRenderer(new CheckBoxRenderer()); 

而已。

我知道这是一个老线程,但我有类似的需求,并发现sers回答非常有帮助。 我发现我需要包含的一个补充是创建一个CheckBoxEditor。 否则,当我点击单元格时,我看到复选框暂时出现。 所以我添加了这样的东西:

 public class CheckBoxEditor extends DefaultCellEditor { private JCheckBox checkBox = new JCheckBox(); CheckBoxEditor() { super( checkBox ); } @Override public Component getTableCellEditorComponent( JTable table, Object value, boolean isSelected, int row, int column ) { if ( row != 1 ) { return super.getTableCellEditorComponent( table, value, isSelected, row, column ); } else { return null; } } } 

然后你会做类似的事情:

 paramTable.getColumnModel().getColumn(3).setCellEditor( new CheckBoxEditor() ); 

无论如何,为我工作。

另一个注意事项是,如果您的单元格具有背景颜色,则可以通过添加以下行来扩展sers答案:

 x.setOpaque( true ); x.setBackground( MYCOLOR ); 

将JLabel设置为不透明是关键,可以在类似主题的其他Stack Exchange答案中找到。