2012-06-29 134 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