Setting jCheckBox invisible in jTable

一个人想着一个人 提交于 2019-12-08 05:44:50

问题


I have a jTable with two columns.First column is set as Boolean(for checkbox) and second column has String value.As I am using Netbeans,checkbox got added into all rows of first column. I tried to add it only for those rows which have value in the second column. I used the code for trying that,

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 ;
  }

 }

If I try to set value 'true' for all other checkbox in the above for loop it's working well. How can I set it invisible for rest of the rows.

EDIT:

I am adding my code in this

   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

    }

回答1:


TableCellRenderer are used in tables to paint the various cells of the table reusing the same component. The table automatically sets up the proper context, component bounds and invokes the getTableCellRendererComponent for each cell of the table that needs to be painted (the first time the table is displayed all visible cells are painted and then after, upon TableModel notification, the appropriate cells are repainted).

So in your TableCellRenderer you certainly do not need to iterate over the cells of the table trying to set values. This just does not make sense. Remember you are implementing the interface TableCellRender which has a contract you need to respect.

From the Javadoc:

Returns the component used for drawing the cell. This method is used to configure the renderer appropriately before drawing.

So all you need to do is return a component representing the value parameter properly. Possibly, you can modify the component to indicate that the cell has the focus or not, and wheter it is currently selected or not. Nothing more, nothing less.

Now, coming to your question: if you want to display a checkbox only for rows that have a value implement a TableCellRenderer returning a checkbox and modify its visibility according to the value in column 1 (second column).

This example is working:

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: I did not take isSelected/hasFocus into account, if you want we can come to that later.




回答2:


First, you must understand the renderer/editor mechanism. To achieve that, read f.i. the corresponding chapter in the online tutorial referenced in the Swing tag description.

Second, for best visual appearance, implement a custom renderer by re-using the defaults installed by the JTable itself, something like:

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); 



回答3:


As the saying goes: many ways lead to Rome.

I just had a similar problem, namely I have a table with a column containing checkboxes, and I want to hide the checkbox in the first row. After evaluating the other solutions I come up with something slightly different (adapted for the original question):

Create a specific CheckBoxRenderer class:

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;
    }
}

Step number 2: attach the renderer to te column:

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

That's it.




回答4:


I know this is an old thread, but I had a similar need and found sers answer quite helpful. One addition I found that I needed to include was to create a CheckBoxEditor. Otherwise, when I clicked on the cell, I saw the checkbox appear momentarily. So I added something like this:

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;
      }
   }
}

Then you'd do something like:

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

Worked for me, anyway.

Another note is that if your cells have a background color, you can extend sers answer by adding the lines:

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

Setting the JLabel to opaque is the key, as can be found in other Stack Exchange answers on similar topics.



来源:https://stackoverflow.com/questions/11328451/setting-jcheckbox-invisible-in-jtable

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!