Adding jRadioButton into jTable
Asked Answered
L

2

0

I am trying to add jRadioButton into jTable. I used the given code

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


    return new javax.swing.JRadioButton();
  }

 }

But when I run this I am getting jTable column in a different color and when I click on radio Button nothing happens. I am using netbeans. If I try to Customize the jTable then nothing will appear in jTable. Give me a proper guidance.

Leenaleeper answered 29/6, 2012 at 9:47 Comment(3)
See also this example.Discobolus
@Trashgod: but in some other examples i had also seen that the grouping of RadioButton wont work in the case of jTable?Leenaleeper
@mKorbel's example uses a JPanel to contain the button group; separate columns are discussed in the second addendum here in response to your previous question on this topic.Discobolus
D
7
  1. If you want to edit the value of a table cell, you must set a TableCellEditor.
  2. You should create a single JRadioButton in your renderer and reuse it everywhere, that is the purpose of TableCellRenderer.
  3. If you are not calling super.getTableCellRendererComponent, it is not need to extend DefaultTableCellRenderer, simply implement TableCellRenderer.

Consider reading the JTable tutorial to understand better the concepts of renderers and editors.

EDIT:

Here is an example on how you can make this work. Of course, you'll have to adapt to your model but you should get the gist:

import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.util.ArrayList;
import java.util.List;

import javax.swing.AbstractCellEditor;
import javax.swing.JFrame;
import javax.swing.JRadioButton;
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.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;

public class TestTable {

    public class RadioButtonCellEditorRenderer extends AbstractCellEditor implements TableCellRenderer, TableCellEditor, ActionListener {

        private JRadioButton radioButton;

        public RadioButtonCellEditorRenderer() {
            this.radioButton = new JRadioButton();
            radioButton.addActionListener(this);
            radioButton.setOpaque(false);
        }

        @Override
        public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
            radioButton.setSelected(Boolean.TRUE.equals(value));
            return radioButton;
        }

        @Override
        public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
            radioButton.setSelected(Boolean.TRUE.equals(value));
            return radioButton;
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            stopCellEditing();
        }

        @Override
        public Object getCellEditorValue() {
            return radioButton.isSelected();
        }

    }

    private JFrame f;
    private JTable table;

    private class MyObjectManager {
        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);
        private List<MyObject> objects = new ArrayList<TestTable.MyObject>();

        public void addObject(MyObject object) {
            objects.add(object);
            object.setManager(this);
            propertyChangeSupport.firePropertyChange("objects", null, object);
        }

        public List<MyObject> getObjects() {
            return objects;
        }

        public void setAsSelected(MyObject myObject) {
            for (MyObject o : objects) {
                o.setSelected(myObject == o);
            }
        }
    }

    private class MyObject {
        private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

        private MyObjectManager manager;

        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 MyObjectManager getManager() {
            return manager;
        }

        public void setManager(MyObjectManager manager) {
            this.manager = manager;
            propertyChangeSupport.firePropertyChange("manager", null, manager);
        }

        public boolean isSelected() {
            return selected;
        }

        public void setSelected(boolean selected) {
            if (this.selected != selected) {
                this.selected = selected;
                if (selected) {
                    manager.setAsSelected(this);
                }
                propertyChangeSupport.firePropertyChange("selected", !selected, selected);
            }
        }

    }

    protected void initUI() {
        MyObjectManager manager = new MyObjectManager();
        for (int i = 0; i < 200; i++) {
            MyObject object = new MyObject("Row " + (i + 1));
            manager.addObject(object);
        }
        table = new JTable(new MyTableModel(manager));
        table.setRowHeight(20);
        TableColumn column = table.getColumnModel().getColumn(1);
        column.setCellEditor(new RadioButtonCellEditorRenderer());
        column.setCellRenderer(new RadioButtonCellEditorRenderer());
        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 final MyObjectManager manager;

        public MyTableModel(MyObjectManager manager) {
            super();
            this.manager = manager;
            manager.propertyChangeSupport.addPropertyChangeListener(this);
            for (MyObject object : manager.getObjects()) {
                object.getPropertyChangeSupport().addPropertyChangeListener(this);
            }
        }

        @Override
        public void propertyChange(PropertyChangeEvent evt) {
            if (evt.getSource() == manager) {
                // OK, not the cleanest thing, just to get the gist of it.
                if (evt.getPropertyName().equals("objects")) {
                    ((MyObject) evt.getNewValue()).getPropertyChangeSupport().addPropertyChangeListener(this);
                }
                fireTableDataChanged();
            } else if (evt.getSource() instanceof MyObject) {
                int index = manager.getObjects().indexOf(evt.getSource());
                fireTableRowsUpdated(index, index);
            }
        }

        @Override
        public int getColumnCount() {
            return 2;
        }

        @Override
        public int getRowCount() {
            return manager.getObjects().size();
        }

        public MyObject getValueAt(int row) {
            return manager.getObjects().get(row);
        }

        @Override
        public Object getValueAt(int rowIndex, int columnIndex) {
            switch (columnIndex) {
            case 0:
                return getValueAt(rowIndex).getValue();
            case 1:
                return getValueAt(rowIndex).isSelected();
            }
            return null;
        }

        @Override
        public void setValueAt(Object value, int rowIndex, int columnIndex) {
            if (columnIndex == 1) {
                getValueAt(rowIndex).setSelected(Boolean.TRUE.equals(value));
            }
        }

        @Override
        public boolean isCellEditable(int rowIndex, int columnIndex) {
            return columnIndex == 1;
        }

        @Override
        public Class<?> getColumnClass(int column) {
            switch (column) {
            case 0:
                return String.class;
            case 1:
                return Boolean.class;
            }
            return Object.class;
        }

        @Override
        public String getColumnName(int column) {
            switch (column) {
            case 0:
                return "Value";
            case 1:
                return "Selected";
            }
            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();
            }
        });
    }

}
Dresser answered 29/6, 2012 at 9:53 Comment(7)
@Tickua I added an example of what I was explaining.Dresser
@GuillaumePolet I know that you didn't intend this as a complete solution, but I still want to mention something. If you do not extend from DefaultTableCellRenderer, you will need to be careful to find ways to indicate whether the cell has focus or not, is editable or not, and is selected or not. If you don't, then those cells won't match the appearance of other table cells.Dormeuse
@Tickua You have said you are a beginner. This isn't the easiest task for a beginner to try, so if you are having trouble, don't feel too bad!Dormeuse
@Dormeuse As the OP mentionned, he is a beginner and I did not want to add complexity to the SSCCE. If he can already make his code work, we can then later fix background/foreground/border for selection/focus.Dresser
For all the massive amounts of code you posted, it is shocking how few comments accompany it to explain what each part does.Presto
@Presto the explanation of the code is at the top, and the focus needs to be obviously put on the renderer. The rest of the code is very trivial and simple to understand, so additional explanations seem rather superfluous. The purpose of the snippet is to demonstrate a solution in a fully working example, not to provide top-notch code with pretty doc for every line.Dresser
@GuillaumePolet Many thanks for posting a practical example that actually runs even with Java 11. (It turns out I only needed the RadioButtonCellEditorRenderer class along with fireTableRowsUpdated to make it work for my use case)Immateriality
U
5
  1. It is not recommended to return a new component in the getTableCellRendererComponent method. Instead, always return the same component, but modify it according to the value. This is possible since the returned component is merely used as a 'stamp' and not added directly to the Swing hierarchy. See the Renderers and Editors section in the tutorial
  2. What I described in the first point explains why you cannot click on the button. It is merely an image of the button that is present in the table, not a real button

Also, consider using a JCheckbox instead of a radiobutton. In that case you can simply stick to the default renderer / editor when your TableModel contains boolean values

Ury answered 29/6, 2012 at 9:53 Comment(2)
I went through many examples and the link which you have given..As I am a beginner I got totally confused..Every where I can see classes for using Renderers and Editors..But no one describes how can we call it..I tried it in normal way(creating object) then it'l be an error.. Here I am using netbeans,in it table model for jTable is already defined..So can you please explain it in a simple way by showing specific codes??Leenaleeper
If I try to add radiobutton in the customize code of jTable by using this, new JRadioButton("a") , then it'l come as, javax.swing.JRadioButton[,0,0,0x0,invalid,alignmentX=0.0,.....text=a], in the column instead of buttonLeenaleeper

© 2022 - 2024 — McMap. All rights reserved.