JTable中的单选按钮无法正常工作

时间:2012-10-17 09:22:41

标签: java swing jtable renderer jradiobutton

我遇到以下代码问题。我的任务是,我必须在第一列中有单选按钮,当用户选择该单选按钮时,该行被选中并被发送以进行处理。但我的问题是,我能够选择第一列中的单选按钮,but afterwards when user clicks in any part of the table then my clicked radio button is being unchecked.我无法确定,为什么会发生这种情况。我真的很困惑这个问题。需要帮助。以下代码显示了我的问题。

import java.awt.Component;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ButtonGroup;
import javax.swing.DefaultCellEditor;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JPanel;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableCellRenderer;

public class DisplayTable extends JDialog {
public void initialize() {
    SourceTableModel stm = new SourceTableModel();
    JTable sourceTable = new JTable(stm);

    sourceTable.getColumnModel().getColumn(0).setCellRenderer(new RadioButtonRenderer());
    sourceTable.getColumnModel().getColumn(0).setCellEditor(new RadioButtonEditor(new JCheckBox ()));

    JPanel panel = new JPanel();
    panel.add(new JScrollPane(sourceTable));
    add(panel);

    setModal(true);
    pack();
    setVisible(true);
}

public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            new DisplayTable().initialize();
        }
    });
}
}


class SourceTableModel extends AbstractTableModel{

private static final long serialVersionUID = 1L;

private List<SourceModel> sourceList = new ArrayList<SourceModel>(); 
private String[] columnNamesList = {"Select", "Group", "Work"};

public SourceTableModel() {
    this.sourceList = getSourceDOList();
}

public String getColumnName(int column) {
    return columnNamesList[column];
}

public int getRowCount() {
    return sourceList.size();
}

public int getColumnCount() {
    return columnNamesList.length;
}

public Class<?> getColumnClass(int columnIndex) {
    return (columnIndex == 0 ? Boolean.class : String.class);
}

public boolean isCellEditable(int rowIndex, int columnIndex) {
    return (columnIndex == 0 ? true : false);
}

public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    SourceModel model = (SourceModel) sourceList.get(rowIndex);
    switch (columnIndex) {
    case 0: 
        model.setSelect((Boolean)aValue);
        break;
    case 1: 
        model.setFactory((String) aValue);
        break;
    case 2: 
        model.setSupplier((String) aValue);
        break;
    }
    fireTableCellUpdated(rowIndex, columnIndex);
}


public Object getValueAt(int rowIndex, int columnIndex) {
    SourceModel source = sourceList.get(rowIndex);
    switch(columnIndex){
    case 0:
        return source.isSelect();
    case 1:
        return source.getFactory();
    case 2:
        return source.getSupplier();
    default:
        return null;
    }
}

private List<SourceModel> getSourceDOList() {
    List<SourceModel> tempSourceList=new ArrayList<SourceModel>();
    for (int index = 0; index < 5; index++) {

        SourceModel source = new SourceModel();
        source.setSelect(false);
        source.setFactory("group");
        source.setSupplier("Work");

        tempSourceList.add(source);
    }
    return tempSourceList;
}
}


class SourceModel {

private boolean select;
private String factory;
private String supplier;

public SourceModel() {
    // No Code;
}

public SourceModel(boolean select, String factory, String supplier) {
    super();
    this.select = select;
    this.factory = factory;
    this.supplier = supplier;
}

public boolean isSelect() {
    return select;
}

public void setSelect(boolean select) {
    this.select = select;
}

public String getFactory() {
    return factory;
}

public void setFactory(String factory) {
    this.factory = factory;
}

public String getSupplier() {
    return supplier;
}

public void setSupplier(String supplier) {
    this.supplier = supplier;
}
}

class RadioButtonEditor extends DefaultCellEditor implements ItemListener {

public JRadioButton btn = new JRadioButton();

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

public Component getTableCellEditorComponent(JTable table, Object 
value, boolean isSelected, int row, int column) {

if (value==null) 
          return null;
btn.addItemListener(this);
if (( (Boolean) value).booleanValue())
    btn.setSelected(true);
else
    btn.setSelected(false);

    return btn;
}

public Object getCellEditorValue() {
    if(btn.isSelected() == true)
        return new Boolean(true);
    else 
        return new Boolean(false);
}

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

class RadioButtonRenderer implements TableCellRenderer {
  public JRadioButton btn = new JRadioButton();
  public Component getTableCellRendererComponent(JTable table, Object value,
      boolean isSelected, boolean hasFocus, int row, int column) {
      if (value==null) return null;

      if(((Boolean)value).booleanValue())
      btn.setSelected(true);
      else
      btn.setSelected(false);

      if (isSelected) {
      btn.setForeground(table.getSelectionForeground());
      btn.setBackground(table.getSelectionBackground());
      } else {
      btn.setForeground(table.getForeground());
      btn.setBackground(table.getBackground());
      } 
      return btn;

  }
}

修改 我已经更新了我的代码,我在第一列使用了布尔类。 The problem which I am facing is, if I remove super.fireEditingStopped(); from RadioButtonEditor class then I am able to check and then if I click at any part of the table then checked one I being unchecked.如果我保留super.fireEditingStopped();然后我甚至无法检查单选按钮。

我知道super.fireEditingStopped();将停止编辑。但我的问题是如何检查它?

P.S:抱歉,我发布了我的整个代码。我认为一个人很容易看到这个问题。

这是该程序的屏幕截图。 enter image description here

3 个答案:

答案 0 :(得分:3)

从您的插图中,您似乎希望在JTable的行中强制互斥,其中每行只有一个JRadioButton。由于ButtonGroup不合适,@ {Baillaume Polet的example使用自定义管理器。

答案 1 :(得分:2)

  

我遇到以下代码问题。我的任务是,我必须拥有   第一列中的单选按钮以及用户选择该无线电时的按钮   按钮该行被选中并发送进行处理。但我的问题   是的,我可以选择第一个单选按钮   列,但之后当用户点击表格的任何部分时   我点击的单选按钮未被选中。我无法想象,   为什么会发生这种情况。我真的很困惑这个问题。救命   需要。以下代码显示了我的问题。

  1. 不要使用JRadioButton,在JTable == JCheckBox中使用build_in支持布尔值,

  2. 然后您可以基于sorting

  3. filteringBoolean value
  4. 否则您必须覆盖String"true" / "false"


  5. JRadioButtonsRendererEditor有一些好JTable,包括使用JComboBox作为Editor RadioButtonGroup

答案 2 :(得分:1)

如果您需要动态更改外观,建议您使用CellEditor扩展Component。

//@see javax/swing/SwingUtilities.java
static void updateRendererOrEditorUI(Object rendererOrEditor) {
    if (rendererOrEditor == null) {
        return;
    }
    Component component = null;
    if (rendererOrEditor instanceof Component) {
        component = (Component)rendererOrEditor;
    }
    if (rendererOrEditor instanceof DefaultCellEditor) {
        //Ahh, AbstractCellEditor ...
        component = ((DefaultCellEditor)rendererOrEditor).getComponent();
    }
    if (component != null) {
        SwingUtilities.updateComponentTreeUI(component);
    }
}

这是“CellEditor扩展JRadioButton ......”示例:

import java.awt.*;
import java.awt.event.*;
import java.util.EventObject;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.table.*;

public class DisplayTable2 extends JDialog {
  public void initialize() {
    Object[][] data = {
      { true,  "Group1", "Work1" }, { false, "Group2", "Work2" },
      { false, "Group3", "Work3" }, { false, "Group4", "Work4" }
    };
    JTable sourceTable = new JTable(new SourceTableModel(data));
    sourceTable.getColumnModel().getColumn(0).setCellRenderer(new RadioButtonRenderer());
    sourceTable.getColumnModel().getColumn(0).setCellEditor(new RadioButtonEditor());

    JPanel panel = new JPanel();
    panel.add(new JScrollPane(sourceTable));
    add(panel);

    setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
    setModal(true);
    pack();
    setVisible(true);
  }
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      @Override public void run() {
        new DisplayTable2().initialize();
      }
    });
  }
}

class SourceTableModel extends DefaultTableModel {
  private static final String[] columnNamesList = {"Select", "Group", "Work"};
  public SourceTableModel(Object[][] data) {
    super(data, columnNamesList);
  }
  @Override public Class<?> getColumnClass(int columnIndex) {
    return (columnIndex == 0 ? Boolean.class : String.class);
  }
  @Override public boolean isCellEditable(int rowIndex, int columnIndex) {
    return (columnIndex == 0 ? true : false);
  }
  @Override public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
    if(columnIndex==0 && aValue instanceof Boolean) {
      //lazy development
      for(int i=0; i<getRowCount(); i++) {
        super.setValueAt(i==rowIndex, i, columnIndex);
      }
    } else {
      super.setValueAt(aValue, rowIndex, columnIndex);
    }
  }
}

class RadioButtonRenderer extends JRadioButton implements TableCellRenderer {
  @Override public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
    if(value instanceof Boolean) {
      setSelected((Boolean)value);
    }
    return this;
  }
}

class RadioButtonEditor extends JRadioButton implements TableCellEditor {
  public RadioButtonEditor() {
    super();
    addActionListener(new ActionListener() {
      @Override public void actionPerformed(ActionEvent e) {
        fireEditingStopped();
      }
    });
  }
  @Override public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
    if(value instanceof Boolean) {
      setSelected((Boolean)value);
    }
    return this;
  }
  @Override public Object getCellEditorValue() {
    return isSelected();
  }

  //Copid from AbstractCellEditor
  //protected EventListenerList listenerList = new EventListenerList();
  //transient protected ChangeEvent changeEvent = null;
  @Override public boolean isCellEditable(EventObject e) {
    return true;
  }
  @Override public boolean shouldSelectCell(EventObject anEvent) {
    return true;
  }
  @Override public boolean stopCellEditing() {
    fireEditingStopped();
    return true;
  }
  @Override public void  cancelCellEditing() {
    fireEditingCanceled();
  }
  @Override public void addCellEditorListener(CellEditorListener l) {
    listenerList.add(CellEditorListener.class, l);
  }
  @Override public void removeCellEditorListener(CellEditorListener l) {
    listenerList.remove(CellEditorListener.class, l);
  }
  public CellEditorListener[] getCellEditorListeners() {
    return listenerList.getListeners(CellEditorListener.class);
  }
  protected void fireEditingStopped() {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for(int i = listeners.length-2; i>=0; i-=2) {
      if(listeners[i]==CellEditorListener.class) {
        // Lazily create the event:
        if(changeEvent == null) changeEvent = new ChangeEvent(this);
        ((CellEditorListener)listeners[i+1]).editingStopped(changeEvent);
      }
    }
  }
  protected void fireEditingCanceled() {
    // Guaranteed to return a non-null array
    Object[] listeners = listenerList.getListenerList();
    // Process the listeners last to first, notifying
    // those that are interested in this event
    for(int i = listeners.length-2; i>=0; i-=2) {
      if(listeners[i]==CellEditorListener.class) {
        // Lazily create the event:
        if(changeEvent == null) changeEvent = new ChangeEvent(this);
        ((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent);
      }
    }
  }
}