Hay una manera fácil de cambiar el comportamiento de un Java/Swing de control cuando se obtiene el foco?

StackOverflow https://stackoverflow.com/questions/66455

  •  09-06-2019
  •  | 
  •  

Pregunta

Para la mayoría de la interfaz gráfica de usuario que yo he utilizado, cuando un control que contiene el texto recibe el foco, todo el contenido del control seleccionado.Esto significa que si usted acaba de empezar a escribir, reemplazar completamente el antiguo contenido.

Ejemplo:Usted tiene el control de giro que se inicializa con el valor cero.La ficha a ella y escriba "1" El valor en la actualidad, el control 1.

Con Swing, esto no sucede.El texto en el control no está seleccionado y el quilate aparece en un extremo u otro del texto existente.Continuando con el ejemplo anterior:

Con un Swing JSpinner, cuando la ficha para el control de giro, el quilate está a la izquierda.Escribe "1" y el valor en la actualidad, el control de 10.

Esto me motiva, (y mis usuarios) encima de una pared, y me gustaría cambiar.Aún más importante, me gustaría cambiar a nivel mundial por lo que el nuevo comportamiento se aplica a JTextField, JPasswordField, JFormattedTextField, JTextArea, Jtree, JSpinner, y así sucesivamente.La única manera que he encontrado para hacer esto para agregar un FocusAdapter para cada control y anular el focusGained() método para Hacer lo Correcto[tm].

Hay que ser más fácil, y menos frágil.Por favor?

EDITAR:Una pieza adicional de información para este caso particular.La forma con la que estoy trabajando se había generado con la Idea del diseñador de formularios.Eso significa que yo, normalmente, en realidad no se que escribir el código para crear los componentes.Es posible decir Idea de que quieres crear tú mismo, pero eso es una molestia me gustaría evitar.

Lema:Todos los buenos programadores son básicamente perezoso.

¿Fue útil?

Solución 4

Después de leer las respuestas hasta ahora (¡Gracias!) He pasado la parte más externa de JPanel para el siguiente método:

void addTextFocusSelect(JComponent component){
    if(component instanceof JTextComponent){
        component.addFocusListener(new FocusAdapter() {
                @Override
                public void focusGained(FocusEvent event) {
                    super.focusGained(event);
                    JTextComponent component = (JTextComponent)event.getComponent();
                    // a trick I found on JavaRanch.com
                    // Without this, some components don't honor selectAll
                    component.setText(component.getText());
                    component.selectAll();
                }
            });

    }
    else
    {
        for(Component child: component.getComponents()){
            if(child instanceof JComponent){
                addTextFocusSelect((JComponent) child);
            }
        }
    }
}

Funciona!

Otros consejos

Cuando lo he necesitado esto en el pasado, he creado subclases de los componentes quería añadir "auto-limpieza" funcionalidad también.por ejemplo:

public class AutoClearingTextField extends JTextField {
   final FocusListener AUTO_CLEARING_LISTENER = new FocusListener(){
      @Override
      public void focusLost(FocusEvent e) {
         //onFocusLost(e);
      }

      @Override
      public void focusGained(FocusEvent e) {
         selectAll();
      }
   };

   public AutoClearingTextField(String string) {
      super(string);
      addListener();
   }

   private void addListener() {
      addFocusListener(AUTO_CLEARING_LISTENER);      
   }
}

El mayor problema es que no he encontrado una "buena" manera de obtener los constructores sin escribir anula.La adición de ellos, y obligando a una llamada a método addListener es el caso más general, el enfoque que he encontrado.

Otra opción es mirar para ContainerEvents en un contenedor de nivel superior con un ContainerListeer para detectar la presencia de nuevos widgets y añadir un interés correspondientes detector basado en los widgets que se han añadido.(por ejemplo:si el contenedor evento es causado por la adición de un campo de texto, a continuación, agregue un enfoque de escucha que sabe cómo seleccionar todo el texto en un campo de texto, y así sucesivamente.) Si un Recipiente se agrega, entonces usted necesita para recursivamente agregar el ContainerListener a la nueva sub-contenedor así.

De cualquier manera, usted no tendrá que muck con enfoque a los oyentes en su interfaz de usuario real de código -- todo va a ser atendida en un nivel superior.

No he probado a mí mismo (sólo incursionó en la que hace un tiempo), pero usted puede conseguir probablemente el actual componente enfocado mediante el uso de:KeyboardFocusManager (no es un método estático getCurrentKeyboardFocusManager()) una adición de un PropertyChangeListener a ella.Desde allí, usted puede averiguar si el componente es un JTextComponent y seleccionar todo el texto.

Una clase independiente que se conecta un FocusListener a la deseada campo de texto puede ser escrito.Todo el enfoque de escucha haría es llamar a selectAll() en el widget de texto cuando recibe el foco.

public class SelectAllListener implements FocusListener {
  private static INSTANCE = new SelectAllListener();

  public void focusLost(FocusEvent e) { }

  public void focusGained(FocusEvent e) {
    if (e.getSource() instanceof JTextComponent) {  
      ((JTextComponent)e.getSource()).selectAll();
    }
  };

  public static void addSelectAllListener(JTextComponent tc) {
    tc.addFocusListener(INSTANCE);
  }

  public static void removeSelectAllListener(JTextComponent tc) {
    tc.removeFocusListener(INSTANCE);
  }
}

Mediante la aceptación de un JTextComponent como un argumento de este comportamiento puede ser añadido a JTextArea, JPasswordField, y todos los demás de edición de texto de los componentes directamente.Esto también permite a la clase para agregar seleccione todos los editable cuadros combinados y JSpinners, donde su control sobre el editor de texto del componente puede ser más limitada.Métodos de conveniencia se pueden añadir:

public static void addSelectAllListener(JSpinner spin) {
  if (spin.getEditor() instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)spin.getEditor());
  }
}

public static void addSelectAllListener(JComboBox combo) {
  JComponent editor = combo.getEditor().getEditorComponent();
  if (editor instanceof JTextComponent) {
    addSelectAllListener((JTextComponent)editor);
  }
}

También, la eliminación métodos de detector es probable innecesarios, ya que el oyente no contiene exterior de las referencias a otras instancias, pero se pueden agregar para hacer revisiones de código más sencillo.

La única forma que conozco es crear un FocusListener y adjuntarlo a su componente.Si desea que este FocusListener a ser global para todos los componentes en su solicitud, usted podría considerar el uso de Programación Orientada a Aspectos (AOP).Con AOP es posible escribir el código una vez y aplicar su enfoque escucha a todos los componentes de una instancia en la aplicación sin tener que copiar y pegar la componente.addFocusListener(el que escucha) el código en la aplicación..

Su aspecto tendría para interceptar la creación de un JComponent (o el sub-clases a las que desea agregar este comportamiento a) y añadir el foco de escucha a la nueva instancia.La AOP enfoque es mejor que copiar y pegar el FocusListener a toda su código porque guarda todo en una sola pieza de código, y no crear una pesadilla de mantenimiento una vez que usted decide cambiar su comportamiento global como la eliminación de la escucha para JSpinners.

Hay muchos AOP marcos que hay para elegir.Me gusta JBossAOP ya que es 100% puro de Java, pero que le gustaría echar un vistazo a AspectJ.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top