2012-06-29 103 views
0

我试图将jRadioButton添加到jTable中。我用给定的代码将jRadioButton添加到jTable中

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

} 

但是当我运行此我以不同的颜色越来越jTable列,当我点击单选按钮没有任何反应。我正在使用netbeans。如果我尝试自定义jTable,则jTable中不会显示任何内容。给我一个适当的指导。

+0

另请参阅此[示例](http://stackoverflow.com/a/11179669/230513)。 – trashgod

+0

@Trashgod:但在其他一些例子中,我也看到RadioButton的分组在jTable的情况下不会起作用? – Luna

+0

@ mKorbel的[示例](http://stackoverflow.com/a/11179669/230513)使用'JPanel'来包含按钮组;在第二个附录[此处](http://stackoverflow.com/a/11173600/230513)中讨论了单独的列以回应您[上一个问题](http://stackoverflow.com/q/11154378/230513)这个话题。 – trashgod

回答

6
  1. 如果要编辑表格单元格的值,则必须设置TableCellEditor
  2. 您应该在您的渲染器中创建一个单独的JRadioButton,并在任何地方重复使用它,这就是TableCellRenderer的目的。
  3. 如果您不拨打super.getTableCellRendererComponent,则无需扩展DefaultTableCellRenderer,只需执行TableCellRenderer即可。

考虑阅读JTable tutorial以更好地理解渲染器和编辑器的概念。

编辑:

下面是如何使这项工作的例子。当然,你必须去适应你的模型,但你应该得到的要点:

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

} 
+0

好吧..我试试你说的方式.. – Luna

+0

@Tickua我加了一个我正在解释的例子。 –

+0

@GuillaumePolet我知道你并不打算把它作为一个完整的解决方案,但我仍然想提一些东西。如果您没有从DefaultTableCellRenderer扩展,则需要小心地找出方法来指示单元格是否具有焦点,是否可编辑以及是否被选中。如果您不这样做,那么这些单元格将与其他表格单元格的外观不匹配。 – Enwired

4
  1. 不建议在getTableCellRendererComponent方法返回一个新的组件。相反,总是返回相同的组件,但根据该值进行修改。这是可能的,因为返回的组件仅仅被用作'stamp'而不是直接添加到Swing层次结构中。请参阅教程中的Renderers and Editors部分
  2. 我在第一点中介绍的内容解释了为什么您不能单击该按钮。它仅仅是表中存在的按钮的图像,而不是真实的按钮

另外,考虑使用JCheckbox而不是单选按钮。在这种情况下,当您的TableModel包含boolean值时,您可以简单地使用默认的渲染器/编辑器

+1

我经历了许多例子和你给出的链接。由于我是初学者,我完全困惑......每一个地方我都可以看到使用Renderer和Editors的类。但是没有人描述我们怎么称呼它..我试图以正常的方式(创建对象),然后它是一个错误..在这里我使用netbeans,在它的表模型jTable已经定义..所以你可以请解释一下,通过显示特定的代码?? – Luna

+0

如果我尝试通过使用这个新的JRadioButton(“a”)在jTable的自定义代码中添加单选按钮,那么它就是javax.swing.JRadioButton [,0,0,0x0,invalid,alignmentX = 0.0 ,..... text = a],而不是按钮 – Luna