我有一个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
}
答案 0 :(得分:4)
首先,必须了解渲染器/编辑器机制。要实现这一点,请阅读f.i. Swing tag description中引用的在线教程中的相应章节。
其次,为获得最佳视觉效果,请通过重复使用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);
答案 1 :(得分:2)
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<MyObject> objects = new ArrayList<TestTable.MyObject>();
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<MyObject> objects;
public MyTableModel(List<MyObject> 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,如果你想我们可以稍后再说。
答案 2 :(得分:1)
俗话说:很多方式都会导致罗马。
我遇到了类似的问题,即我有一个包含复选框的列的表,我想隐藏第一行中的复选框。在评估了其他解决方案后,我提出了一些略有不同的内容(适用于原始问题):
创建一个特定的CheckBoxRenderer类:
paramTable.getColumnModel().getColumn(3).setCellRenderer(new CheckBoxRenderer());
步骤2:将渲染器附加到te列:
<owl:NamedIndividual rdf:about="http://www.test123.com/test123-ontology.owl#cap_123">
<rdf:type rdf:resource="http://www.test123.com/test123-ontology.owl#HealthBeauty"/>
<description>Test test test</description>
<hasPrice rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">49</hasPrice>
<id rdf:datatype="http://www.w3.org/2001/XMLSchema#integer">123</id>
</owl:NamedIndividual>
那就是它。
答案 3 :(得分:0)
我知道这是一个老线程,但我有类似的需求,并发现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设置为opaque是关键,可以在类似主题的其他Stack Exchange答案中找到。