Search code examples
javaswingjtabletablecelleditorjradiobutton

Clicking on radiobutton gives old value?


I am quite new to java, so please don't be too harsh :)

I have a JTable with a column with 3 JRadioButtons in each cell.

The JRadioButtons display correctly, and the correct JRadioButtons are selected.

To put the JRadioButtons in the JTable I use setCellRenderer() and setCellEditor() :

private void addRadio(int intCol)
{
  mgrdData.getColumnModel().getColumn(intCol).setCellRenderer(new RadioButtonRenderer());
  RadioButtonEditor butEdit = new RadioButtonEditor(new JCheckBox());
  butEdit.UseTcp(mtcpGrid);
  mgrdData.getColumnModel().getColumn(intCol).setCellEditor(butEdit);
}

Below is the code of the RadioButtonEditor class :

public class RadioButtonEditor extends DefaultCellEditor implements ItemListener
{
  public JPanel pnl = new JPanel();
  public ButtonGroup group1 = new ButtonGroup();
  public JRadioButton btnVA = new JRadioButton("VA");
  public JRadioButton btnUIT = new JRadioButton("UIT");
  public JRadioButton btnAAN = new JRadioButton("AAN");

  public tcp mtcpCon;

  public RadioButtonEditor(JCheckBox checkBox)
  {
    super(checkBox);
  }

  public void UseTcp(tcp tcpCon)
  {
    mtcpCon = tcpCon;
  }

  public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column)
  {
    if (value==null) return null;
    group1.add(btnVA );
    group1.add(btnUIT );
    group1.add(btnAAN );
    pnl.add(btnVA );
    pnl.add(btnUIT );
    pnl.add(btnAAN );
    btnVA.setSelected(false);
    btnUIT .setSelected(false);
    btnAAN .setSelected(false);
    String strVal1 = (String)value;
    switch(Integer.parseInt(strVal1))
    {
      Case 0:
        btnVA.setSelected(true);
        break;
      Case 1:
        btnUIT.setSelected(true);
        break;
      Case 2:
        btnAAN.setSelected(true);
        break;
    }
    System.out.println("gettablecelleditorcomponent strVal1 : " + strVal1);
    return pnl;
  }

  public Object getCellEditorValue()
  {
    String strVal2="";
    if(btnVA.isSelected()  == true) strVal2="0";
    if(btnUIT.isSelected() == true) strVal2="1";
    if(btnAAN.isSelected() == true) strVal2="2";
    System.out.println("getcelleditorvalue strVal2 : " + strVal2);
    return strVal2;
  }

  public void itemStateChanged(ItemEvent e)
  {
    super.fireEditingStopped();
  }
}

Below is the code of the RadioButtonRenderer class :

public class RadioButtonRenderer implements TableCellRenderer
{
  public JPanel pnl = new JPanel();
  public ButtonGroup group1 = new ButtonGroup();
  public JRadioButton btnVA = new JRadioButton("VA");
  public JRadioButton btnUIT = new JRadioButton("UIT");
  public JRadioButton btnAAN = new JRadioButton("AAN");

  public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column)
  {
    if (value==null) value="0";
    btnVA.putClientProperty("JComponent.sizeVariant","small");
    btnAAN.putClientProperty("JComponent.sizeVariant","small");
    btnUIT.putClientProperty("JComponent.sizeVariant","small");
    group1.add(btnVA );
    group1.add(btnUIT );
    group1.add(btnAAN );
    pnl.add(btnVA );
    pnl.add(btnUIT );
    pnl.add(btnAAN );
    btnVA.setSelected(false);
    btnUIT .setSelected(false);
    btnAAN .setSelected(false);
    switch(Integer.parseInt((String)value))
    {
      Case 0:
        btnVA.setSelected(true);
        break;
      Case 1:
        btnUIT.setSelected(true);
        break;
      Case 2:
        btnAAN.setSelected(true);
        break;
    }
    return pnl;
  }
}

I want to detect which JRadioButton is clicked, and process that new value. I assume the fired event should be in the RadioButtonEditor class, but I don't know event.

I added println() to both the getTableCellEditor() as well as the getCellEditorValue() events, but both print an old value.

For example :

Start with row0=0, row1=1, row2=2

Click on 2 on row1 gives :

gettablecelleditorcomponent : 1

Now row0=0, row1=2, row2=2 Click on 1 on row0 gives :

getcelleditorvalue : 2
gettablecelleditorcomponent : 0

Now row0=1, row1=2, row2=2 Then click on 0 on row1 gives :

getcelleditorvalue : 1
gettablecelleditorcomponent : 2

Now row0=1, row1=0, row2=2 Then click on 1 on row2 gives :

getcelleditorvalue : 0
gettablecelleditorcomponent : 2

Now row0=1, row1=0, row2=1

From this can be seen :

getTableCellEditor() has the previous value of that row
getCellEditorValue() has the global previous value 

Which event can I use to obtain the new value of the JRadioButton, after it has been clicked?

[EDIT]

I added a TableModelListener to the table, but getFirstRow() still show the last selected row, and not the row in which the user clicked on the radiobutton.

So for example, when they last clicked on a radiobutton in row 5, and now click on a radiobuttion on row 7, then getFirstRow() in tabelChanged() still shows 5

Below is the code of my TableModelListener :

mgrdData.getModel().addTableModelListener(new TableModelListener()
{
  public void tableChanged(TableModelEvent e)
  {
    System.out.println("column : " + e.getColumn());
    System.out.println("firstrow : " + e.getFirstRow());
  }
});

Solution

  • Try adding a TableModelListener to your JTable.

    Editing is just a process for updating the model data inside the JTable. The values stored in the Editor are usually temporary and unpredictable.

    At the end of editing, the end result is that your table's underlying model is updated. Then all TableModelListeners will be informed.

    Updated

    Ah ok. The problem now might be that the "editing finished" event isn't getting fired until the radio buttons in the editor lose focus. So, clicking onto row 7 actually fires you the event from row 5 which just lost focus. Clicking on 7 just gives it focus and BEGINS the editing process for 7. But, you can tell the editor when editing is finished. In the editor, try something like this:

    public RadioButtonEditor(JCheckBox checkBox)
    {
      super(checkBox);
      ActionListener editingListener = new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          // editing is now complete - don't wait for focus to be lost
          // this will switch back to showing renderer
          //    and fire the event to tablemodellisteners
          stopCellEditing();
        }
      };
      btnVA.addActionListener(editingListener);
      btnUIT.addActionListener(editingListener);
      btnAAN.addActionListener(editingListener);
    }
    

    I think you were going down that route with your ItemListener, but you haven't called btnVA.addItemListener(this), etc.. But an ActionListener is normally better for radiobuttons anyway.