2011-04-05 22 views
16

Tengo una JTable con un procesador de celdas personalizado. La celda es un JPanel que contiene un JTextField y un JButton. JTextField contiene un número entero, y cuando el usuario hace clic en JButton, se debe aumentar el número entero.¿Cómo hacer que un JButton en una celda JTable pueda hacer clic?

El problema es que no se puede hacer clic en JButton cuando lo tengo en una celda JTable. ¿Cómo puedo hacer que se pueda hacer clic?

enter image description here

Aquí está mi código de prueba:

public class ActiveTable extends JFrame { 

    public ActiveTable() { 
     RecordModel model = new RecordModel(); 
     model.addRecord(new Record()); 
     JTable table = new JTable(model); 
     EditorAndRenderer editorAndRenderer = new EditorAndRenderer(); 
     table.setDefaultRenderer(Object.class, editorAndRenderer); 
     table.setDefaultEditor(Object.class, editorAndRenderer); 
     table.setRowHeight(38); 

     add(new JScrollPane(table)); 
     setPreferredSize(new Dimension(600, 400)); 
     pack(); 
     setDefaultCloseOperation(EXIT_ON_CLOSE); 
     setTitle("Active Table"); 
     setVisible(true); 
    } 

    public static void main(String[] args) { 
     SwingUtilities.invokeLater(new Runnable() { 

      @Override 
      public void run() { 
       new ActiveTable(); 
      } 
     }); 
    } 

    class RecordModel extends AbstractTableModel { 

     private final List<Record> records = new ArrayList<Record>(); 

     @Override 
     public int getColumnCount() { 
      return 1; 
     } 

     @Override 
     public int getRowCount() { 
      return records.size(); 
     } 

     @Override 
     public Object getValueAt(int rowIndex, int columnIndex) { 
      return records.get(rowIndex); 
     } 

     public void addRecord(Record r) { 
      records.add(r); 
      fireTableRowsInserted(records.size()-1, records.size()-1); 
     } 

    } 

    class Record { 
     private int count = 1; 
     public int getCount() { return count; } 
     public void increase() { count = count + 1; } 
    } 

    class CellPanel extends JPanel { 
     private Record record; 
     private final JTextField field = new JTextField(8); 
     private final Action increaseAction = new AbstractAction("+") { 
      public void actionPerformed(ActionEvent e) { 
       record.increase(); 
       field.setText(record.getCount()+""); 
       JTable table = (JTable) SwingUtilities.getAncestorOfClass(JTable.class, (Component) e.getSource()); 
       table.getCellEditor().stopCellEditing(); 
      } 
     }; 
     private final JButton button = new JButton(increaseAction); 

     public CellPanel() { 
      add(field); 
      add(button); 
     } 

     public void setRecord(Record r) { 
      record = r; 
      field.setText(record.getCount()+""); 
     } 

     public Record getRecord() { 
      return record; 
     } 
    } 

    class EditorAndRenderer extends AbstractCellEditor implements TableCellEditor, TableCellRenderer { 

     private final CellPanel renderer = new CellPanel(); 
     private final CellPanel editor = new CellPanel(); 

     @Override 
     public Component getTableCellRendererComponent(JTable table, Object value, 
       boolean isSelected, boolean hasFocus, int row, int column) { 
      renderer.setRecord((Record) value); 
      return renderer; 
     } 

     @Override 
     public Component getTableCellEditorComponent(JTable table, Object value, 
       boolean isSelected, int row, int column) { 
      editor.setRecord((Record) value); 
      return editor; 
     } 

     @Override 
     public Object getCellEditorValue() { 
      return editor.getRecord(); 
     } 

     @Override 
     public boolean isCellEditable(EventObject ev) { 
      return true; 
     } 

     @Override 
     public boolean shouldSelectCell(EventObject ev) { 
      return false; 
     } 
    } 
} 
+0

puede que todavía sea necesario JPanel (anidado Cualquiera que sea JComponents) en el interior de la celda del JTable ?? , – mKorbel

+0

@mKorbel: Sí, necesito que la celda sea un JPanel multilínea con múltiples botones. – Jonas

+0

espera sec. Publiqué este código aquí tal vez dos veces o más (en algún lugar de la JList se refirió q & a), si no puedo encontrarlo, entonces comenzaré a buscarlo en la PC local ... – mKorbel

Respuesta

6

basé mi último ejemplo en el código proporcionado por mKrobels responder a How to implement dynamic GUI in swing

La principal diferencia entre su y mi ejemplo, en la cuestión es que se utilice DefaultTableModel y lo uso AbstractTableModel. Su ejemplo funciona, pero no el mío.

La solución que encontré fue que tenía que poner en práctica isCellEditable() en el TableModel, así que con este método añadió, mi ejemplo funciona:

@Override 
public boolean isCellEditable(int rowIndex, int columnIndex) { 
    return true; 
} 
3

El procesador es sólo una pantalla para la pintura de las células. Necesita un componente de editor que le permita realizar cambios.

Tome un vistazo a:

http://download.oracle.com/javase/6/docs/api/javax/swing/table/TableCellEditor.html

+0

I don No entiendo cómo puedo usar 'TableCellEditor' ya que mi celda contiene múltiples componentes y solo uno de ellos, el' JButton' debe poder hacer clic. ¿Algunas ideas? – Jonas

+1

@Jonas, getTableCellRendererComponent() puede devolver un panel que tenga botones, texto, etc. – jzd

9

Ésta es una forma de usar ButtonColumn.

public class TableTest extends JFrame { 

    public TableTest() { 
     this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
     JTable table = new JTable(new TestModel()); 
     table.getColumnModel().getColumn(1).setPreferredWidth(3); 
     table.getColumnModel().getColumn(2).setPreferredWidth(3); 
     this.add(new JScrollPane(table)); 
     Action increase = new AbstractAction("+") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JTable table = (JTable) e.getSource(); 
       int row = Integer.valueOf(e.getActionCommand()); 
       TestModel model = (TestModel) table.getModel(); 
       model.increment(row, 0); 
      } 
     }; 
     ButtonColumn inc = new ButtonColumn(table, increase, 1); 
     Action decrease = new AbstractAction("-") { 

      @Override 
      public void actionPerformed(ActionEvent e) { 
       JTable table = (JTable) e.getSource(); 
       int row = Integer.valueOf(e.getActionCommand()); 
       TestModel model = (TestModel) table.getModel(); 
       model.decrement(row, 0); 
      } 
     }; 
     ButtonColumn dec = new ButtonColumn(table, decrease, 2); 
     pack(); 
    } 

    public static void main(String[] args) { 
     new TableTest().setVisible(true); 
    } 
} 

class TestModel extends AbstractTableModel { 

    List<TestRecord> records = new LinkedList<TestRecord>(); 

    private static class TestRecord { 

     private int val = 0; 
    } 

    public void increment(int row, int col) { 
     records.get(row).val++; 
     fireTableCellUpdated(row, 0); 
    } 

    public void decrement(int row, int col) { 
     records.get(row).val--; 
     fireTableCellUpdated(row, 0); 
    } 

    public TestModel() { 
     records.add(new TestRecord()); 
     records.add(new TestRecord()); 
    } 

    @Override 
    public Class<?> getColumnClass(int col) { 
     if (col == 0) { 
      return Integer.class; 
     } else { 
      return ButtonColumn.class; 
     } 
    } 

    @Override 
    public boolean isCellEditable(int row, int col) { 
     return true; 
    } 

    @Override 
    public int getColumnCount() { 
     return 3; 
    } 

    @Override 
    public int getRowCount() { 
     return records.size(); 
    } 

    @Override 
    public Object getValueAt(int row, int col) { 
     if (col == 0) { 
      return records.get(row).val; 
     } else if (col == 1) { 
      return "+"; 
     } else { 
      return "-"; 
     } 
    } 
} 
Cuestiones relacionadas