2009-02-18 9 views
8

Tengo problemas con el siguiente código, donde uso un JComboBox para cambiar un valor de cadena en una celda de tabla. JComboBox funciona bien, pero si hago clic en el cuadro y luego hago clic en sin seleccionar nada el menú desplegable de JComboBox permanece visible, incluso si borro la fila. Al hacer clic en otro componente de Swing como un JButton a menudo hace que desaparezca, pero no siempre.problema de enfoque utilizando un JComboBox como editor de celda en una JTable


    TableColumn col = myTable.getColumnModel().getColumn(0); 
    JComboBox eq = new JComboBox(); 
    eq.addItem("=="); 
    eq.addItem("!="); 
    DefaultCellEditor editor = new DefaultCellEditor(eq); 
    col.setCellEditor(editor);

Editar: me había olvidado mencionar que antes me puse:


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

Si comento esta línea a cabo o se establece falso, entonces al hacer clic en otros componentes Swing no hace que el cuadro de desaparecer. Al hacerlo, al hacer clic en cualquier cosa que tenga un foco, la caja se irá, haciendo que el problema sea menos molesto, pero posiblemente enmascarando la causa del comportamiento.

¿Estoy haciendo algo mal aquí o estoy olvidando un paso? Alternativamente, ¿hay alguna manera de obligarlo a cerrarse?

Gracias!

Respuesta

11

Para comprender esto, deberá comprender lo que sucede con una tabla editable. Un poco de teoría:

Cada célula tiene un procesador y un editor potenciales. El procesador solo le dice a la célula cómo dibujar y no interactúa con los eventos. Sin embargo, el editor es un componente que puede interactuar con eventos. Cuando ocurre un evento que desencadena una edición, el componente editor se agrega en la parte superior de la tabla. Cuando finaliza la edición, el componente se elimina.

Para que el componente se vaya, deberá asegurarse de que la celda no se encuentre aún en el estado de "edición". Esta es la razón por la cual terminateEditOnFocusLast hace que el JComboBox desaparezca. Si desea obtener otras cosas para que funcione la caja, probablemente deba llamar a removeEditor() en respuesta a ciertos eventos, posiblemente enfoque o selección de celda.

Para realmente entender lo que sucede, recomiendo echar un vistazo al código fuente para eliminar Editor(), editCellAt() etc., y tal vez pasar una vez en un depurador. Es posible que haya anulado algunos de los códigos de manejo de eventos o los llame cuando no debería. El editor/código de manejo de eventos en JTable es bastante frágil, y es bastante fácil por accidente que las llamadas se realicen en el orden incorrecto con efectos secundarios divertidos.

Además, Java modificó muy sutilmente el comportamiento de evento y enfoque de JTable entre versiones una vez, creo que fue entre 1.4 y 1.5, cuando cambió el manejo del enfoque para el swing. Entonces, lo primero que recomiendo probar es su código con una versión de Java diferente. El error puede haber sido causado por Sun (parte de nuestro complicado código de editor tuvo que ser cambiado) y si difiere entre versiones, es más fácil reportarlo a Sun.

+0

Gracias por el fondo y la respuesta completa. He echado un vistazo a esos métodos pero aún no he encontrado nada. Creo que básicamente tienes la respuesta correcta, solo que necesito descubrir dónde está pasando. ¡Gracias! –

+0

¡Buena respuesta completa! –

+0

Gracias por la lección sobre las diferencias entre el renderizador y el editor. Muy útil. – Boundless

1

Sé que esta pregunta es antigua, pero como referencia aquí está mi solución. Extiendo DefaultCellEditor y escucho que JComboBox se cancele, forzo al editor a cancelar.

import javax.swing.DefaultCellEditor; 
import javax.swing.JComboBox; 
import javax.swing.event.PopupMenuEvent; 
import javax.swing.event.PopupMenuListener; 

public class ComboBoxCellEditor extends DefaultCellEditor { 

    public ComboBoxCellEditor(JComboBox comboBox) { 
     super(comboBox); 
     comboBox.addPopupMenuListener(new PopupMenuListener() { 

      public void popupMenuWillBecomeVisible(PopupMenuEvent e) { 
      } 

      public void popupMenuWillBecomeInvisible(PopupMenuEvent e) { 
      } 

      public void popupMenuCanceled(PopupMenuEvent e) { 
       cancelCellEditing(); 
      } 
     }); 
    } 
} 

Entonces ...

DefaultCellEditor editor = new ComboBoxCellEditor(combobox); 
column.setCellEditor(editor); 
Cuestiones relacionadas