2011-10-31 56 views
8

En mi aplicación utilizo una tabla java que es similar al ejemplo this. Mi problema es que cuando cambio el valor de una celda (incluso en el ejemplo anterior), el modelo de datos no se actualiza hasta que hago clic en una celda diferente. Incluso si hago clic en el área gris debajo de la tabla después de cambiar el valor de la celda, el modelo no cambiará. Creo que la razón es que las células se mantienen enfocadas hasta que haga clic en una celda diferente. ¿Cómo puedo evitar esto y actualizar el modelo sin hacer clic en la celda de la tabla? Gracias de antemanoLa actualización de JTable Cell no funciona

tengo editar el código de ejemplo anterior para reflejar el problema

public class JTableDemo extends JApplet { 
    private JTextArea txt = new JTextArea(4, 20); 

    // The TableModel controls all the data: 
    class DataModel extends AbstractTableModel { 
    Object[][] data = { { "one", "two", "three", "four" }, 
     { "five", "six", "seven", "eight" }, 
     { "nine", "ten", "eleven", "twelve" }, }; 

    // Prints data when table changes: 
    class TML implements TableModelListener { 
     public void tableChanged(TableModelEvent e) { 
     txt.setText(""); // Clear it 
     for (int i = 0; i < data.length; i++) { 
      for (int j = 0; j < data[0].length; j++) 
      txt.append(data[i][j] + " "); 
      txt.append("\n"); 
     } 
     } 
    } 

    public DataModel() { 
     addTableModelListener(new TML()); 
     fireTableDataChanged(); 
    } 

    public int getColumnCount() { 
     return data[0].length; 
    } 

    public int getRowCount() { 
     return data.length; 
    } 

    public Object getValueAt(int row, int col) { 
     return data[row][col]; 
    } 

    public void setValueAt(Object val, int row, int col) { 
     data[row][col] = val; 
     System.out.println(val); 
     // Indicate the change has happened: 
     fireTableDataChanged(); 
    } 

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

    public void init() { 
    Container cp = getContentPane(); 
    JTable table = new JTable(new DataModel()); 
    cp.add(new JScrollPane(table)); 
    cp.add(BorderLayout.SOUTH, txt); 
    } 

    public static void main(String[] args) { 
    run(new JTableDemo(), 350, 200); 
    } 

    public static void run(JApplet applet, int width, int height) { 
    JFrame frame = new JFrame(); 
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 
    frame.getContentPane().add(applet); 
    frame.setSize(width, height); 
    applet.init(); 
    applet.start(); 
    frame.setVisible(true); 
    } 
} 

Al ejecutar el ejemplo se puede ver el contenido de la tabla en el área de texto debajo de la mesa. Después de actualizar una celda, debería aparecer en el cuadro de texto a continuación. Pero el método 'setValueAt' no llamará hasta que haga clic en una celda diferente.

+1

¿Puedes editar tu pregunta y agregar un [SSCCE] (http://sscce.org) que muestre el problema? –

+0

parecida a SSCCE +1 – mKorbel

Respuesta

8

El mecanismo de actualización predeterminado solo cambia el modelo cuando el editor de celda pierde el foco. Si selecciona tabular fuera de la celda o hacer clic en una celda diferente, se producirá el evento vital de "pérdida de foco" que activará el cambio del modelo.

Al hacer clic en el área gris no tiene ningún efecto porque no hay elementos activos allí que podrían procesar el evento - la tabla ignora el clic.

Si desea cambiar esto, necesita encontrar un evento que le indique a la computadora que el usuario está "hecho con la edición". ¿Como sabes eso?

[EDIT] Tenga en cuenta que la adición de un botón "Guardar" puede interrumpir la edición de "flujo" de los usuarios (haga clic en celda de tabla, editar, ratón de agarre, la finalidad, haga clic en Guardar, haga clic en la celda siguiente, volver a teclado, editar, ...)

+0

¿Cómo puedo usar el botón Guardar para eso? Siento que puede funcionar para mí ... – nath

+0

Simplemente agregue un botón que no hace nada con la etiqueta "Guardar".Junto con la propiedad del cliente de la respuesta de Kleopatra, eso debería ser el truco. Tenga en cuenta que molestará en gran medida a sus usuarios, ya que significa un clic adicional del mouse. Intente agregar un mnemónico para que la gente pueda dejar de editar con "Alt + S" (sin salir del teclado). –

+1

no: a focusLost de forma predeterminada _does not_ trigger a commit (que era un problema de larga data desde hace años, hasta ELLOS podrían convencerse de al menos soporte para establecer opcionalmente ese comportamiento). De hecho, el compromiso de tabular o hacer clic en otra celda se desencadena explícitamente mediante el código de tablaUI – kleopatra

12

Comportamiento esperado: el valor editado no se confirma con el modelo de respaldo hasta que se realiza un gesto de usuario explícito, como f.i. pulsando enter o tabbing out o haciendo clic en algún otro lugar de la tabla ...

Una rareza (algunos lo llaman error :-) de JTable es que la edición no termina de forma predeterminada al transferir el foco al "exterior" de la tabla . Para forzar que hacerlo, es necesario configurarlo gustaría:

table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE); 

BTW (sin relación, simplemente por la cordura): siempre se disparó el tipo de evento más de grano fino, aquí que sería un cellUpdated en lugar del martillo DataChanged .

+0

Me encantan tus lunes, gran y valiosa respuesta +1 – mKorbel

Cuestiones relacionadas