2014-03-02 42 views
3

我有一個3列JTable。第2列是一個複選框,我想爲該行啓用/禁用JSpinner。JTable與JSpinner啓用/禁用

我一直在努力,除了一件事情--JSpinner看起來並不像它的殘疾人(文本和微調按鈕變灰)。我不太清楚如何實現這一點。我試着在JSpinner上強制調用setEnabled(false),但表似乎沒有正確重畫。

下面是一些代碼,我已經得到了通過其他StackOverflow的實例工作:

import java.awt.Component; 
import java.awt.Dimension; 
import java.awt.EventQueue; 
import java.awt.event.MouseAdapter; 
import java.awt.event.MouseEvent; 
import java.util.EventObject; 

import javax.swing.JComponent; 
import javax.swing.JFrame; 
import javax.swing.JPanel; 
import javax.swing.JScrollPane; 
import javax.swing.JSpinner; 
import javax.swing.JTable; 
import javax.swing.WindowConstants; 
import javax.swing.event.CellEditorListener; 
import javax.swing.event.ChangeEvent; 
import javax.swing.event.ChangeListener; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellEditor; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableColumn; 

public class SpinnerTable { 
    public JComponent makeUI() { 
     String[] columnNames = { "Name", "Spinner Enable", "Spinner" }; 
     final Object[][] data = { { "aaa", true, 1 }, { "bbb", true, 10 }, 
       { "ccc", true, 10 } }; 

     final DefaultTableModel model = new DefaultTableModel(data, columnNames) { 
      @Override 
      public Class<?> getColumnClass(int column) { 
       return getValueAt(0, column).getClass(); 
      } 
     }; 
     JTable table = new JTable(model) { 

      @Override 
      public void setValueAt(Object aValue, int row, int column) { 
       super.setValueAt(aValue, row, column); 

      } 

      @Override 
      public boolean isCellEditable(int row, int column) { 

       if (column == 2) 
        return (Boolean) model.getValueAt(row, 1); 

       return super.isCellEditable(row, column); 
      } 

     }; 

     table.setRowHeight(36); 
     table.setAutoCreateRowSorter(true); 
     TableColumn column = table.getColumnModel().getColumn(2); 
     column.setCellRenderer(new ComboBoxCellRenderer()); 
     column.setCellEditor(new ComboBoxCellEditor()); 

     return new JScrollPane(table); 
    } 

    public static void main(String[] args) { 
     EventQueue.invokeLater(new Runnable() { 
      @Override 
      public void run() { 
       createAndShowGUI(); 
      } 
     }); 
    } 

    public static void createAndShowGUI() { 
     JFrame f = new JFrame(); 
     f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     f.getContentPane().add(new SpinnerTable().makeUI()); 
     f.setSize(320, 240); 
     f.setLocationRelativeTo(null); 
     f.setVisible(true); 
    } 
} 

class SpinnerPanel extends JPanel { 
    protected JSpinner spinner = new JSpinner() { 
     @Override 
     public Dimension getPreferredSize() { 
      Dimension d = super.getPreferredSize(); 
      return new Dimension(40, d.height); 
     } 
    }; 

    public SpinnerPanel() { 
     super(); 
     setOpaque(true); 
     add(spinner); 
    } 
} 

class ComboBoxCellRenderer extends SpinnerPanel implements TableCellRenderer { 
    public ComboBoxCellRenderer() { 
     super(); 
     setName("Table.cellRenderer"); 
    } 

    @Override 
    public Component getTableCellRendererComponent(JTable table, Object value, 
      boolean isSelected, boolean hasFocus, int row, int column) { 
     setBackground(isSelected ? table.getSelectionBackground() : table 
       .getBackground()); 
     if (value != null) { 
      spinner.setValue(value); 
     } 
     return this; 
    } 
} 

class ComboBoxCellEditor extends SpinnerPanel implements TableCellEditor { 
    public ComboBoxCellEditor() { 
     super(); 
     spinner.addChangeListener(new ChangeListener() { 

      @Override 
      public void stateChanged(ChangeEvent e) { 
       fireEditingStopped(); 

      } 
     }); 
     addMouseListener(new MouseAdapter() { 
      @Override 
      public void mousePressed(MouseEvent e) { 
       fireEditingStopped(); 
      } 
     }); 
    } 

    @Override 
    public Component getTableCellEditorComponent(JTable table, Object value, 
      boolean isSelected, int row, int column) { 
     this.setBackground(table.getSelectionBackground()); 
     spinner.setValue(value); 
     return this; 
    } 

    // Copid from DefaultCellEditor.EditorDelegate 
    @Override 
    public Object getCellEditorValue() { 
     return spinner.getValue(); 
    } 

    @Override 
    public boolean shouldSelectCell(EventObject anEvent) { 
     if (anEvent instanceof MouseEvent) { 
      MouseEvent e = (MouseEvent) anEvent; 
      return e.getID() != MouseEvent.MOUSE_DRAGGED; 
     } 
     return true; 
    } 

    @Override 
    public boolean stopCellEditing() { 
     fireEditingStopped(); 
     return true; 
    }; 

    transient protected ChangeEvent changeEvent = null; 

    @Override 
    public boolean isCellEditable(EventObject e) { 
     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); 
      } 
     } 
    } 
} 

回答

4

該表不知道它應該重新繪製細胞在列2時,第1欄被修改。您可以通過手動啓動更新來通知表格。例如,擴展模型的setValueAt()

@Override 
public void setValueAt(Object aValue, int row, int column) { 
    super.setValueAt(aValue, row, column); 
    if (column == 1) 
     fireTableRowsUpdated(row, row); 
} 

這將禁用編輯和微調將成爲不可編輯。如果你需要真正的視覺禁用微調的話,您可以啓用渲染器內/禁用基於isCellEditable微調,即:

spinner.setEnabled(table.isCellEditable(row, column)); 

注意,在當前的實現,則延長JTable實現isCellEditablesetValueAt。這些應該真的是模型的一部分。

+0

fireTableRowsUpdated(row,row);不需要關注DefaultTableModel,那麼這個通知器被調用兩次 – mKorbel

+0

@dubdubdubdot移動所有東西,從JTable到DefaultTableModel – mKorbel

+0

的每條代碼行都將簡單的微調器放到了渲染器上,而JPanel是無用的,或者還有另一個選項所有的JComponents到JPanel,[那麼將有一列的JTable](http://stackoverflow.com/a/15090127/714968) – mKorbel