2011-02-10 25 views
14

tengo en un JFrame algunos componentes que quiero para referirse a otro JFrame y quiero conseguirlos por su nombre y no hago métodos get/set públicas para cada uno.Obtener un componente Swing por su nombre

¿Hay alguna manera desde Swing para obtener una referencia de componente por su nombre como do C#?

p. Ej. form.Controls["text"]

Gracias

+1

Window.getWindows() y luego escanea lo que necesitas – bestsss

+1

¿Por qué en el mundo te gustaría hacer eso?Al hacerlo, pierde dos comprobaciones importantes del compilador estático: - Primero, el campo existe. - En segundo lugar, es del tipo correcto. Además, la búsqueda dinámica es más lenta que tener una referencia al campo. – fortran

+0

Por ejemplo, debido a las temidas API, donde no tiene acceso directo a algunos componentes que desea modificar. –

Respuesta

27

Sé que esta es una vieja pregunta, pero me puse a hacerlo ahora. Quería una manera fácil de obtener componentes por nombre, así que no tenía que escribir un código complicado cada vez para acceder a diferentes componentes. Por ejemplo, tener un JButton accede al texto en un campo de texto o una selección en una lista.

La solución más fácil es hacer que todas las variables componentes sean variables de clase para que pueda acceder a ellas desde cualquier lugar. Sin embargo, no todos quieren hacer eso, y algunos (como yo) están usando editores de GUI que no generan los componentes como variables de clase.

Mi solución es simple, por lo que yo sé, y realmente no infringe ningún estándar de programación (haciendo referencia a lo que se estaba diciendo). Permite una forma fácil y directa de acceder a los componentes por su nombre.

  1. Crear una variable de clase de mapa. Necesitarás importar HashMap al menos al . Llamé a mi componentMap por simplicidad.

    private HashMap componentMap; 
    
  2. Agregue todos sus componentes al marco de forma normal.

    initialize() { 
        //add your components and be sure 
        //to name them. 
        ... 
        //after adding all the components, 
        //call this method we're about to create. 
        createComponentMap(); 
    } 
    
  3. Define los dos métodos siguientes en tu clase. Tendrá que importar componentes, si no lo ha hecho:

    private void createComponentMap() { 
         componentMap = new HashMap<String,Component>(); 
         Component[] components = yourForm.getContentPane().getComponents(); 
         for (int i=0; i < components.length; i++) { 
           componentMap.put(components[i].getName(), components[i]); 
         } 
    } 
    
    public Component getComponentByName(String name) { 
         if (componentMap.containsKey(name)) { 
           return (Component) componentMap.get(name); 
         } 
         else return null; 
    } 
    
  4. Ahora tiene un HashMap que mapea todos los componentes existentes en la actualidad en su marco/panel de contenido/tabla/etc a sus respectivos nombres .

  5. Para acceder ahora a estos componentes, es tan simple como una llamada a getComponentByName (String name). Si existe un componente con ese nombre, devolverá ese componente. Si no, devuelve nulo. Es su responsabilidad colocar el componente en el tipo apropiado. Sugiero usar instanceof para estar seguro.

Si planea añadir, eliminar o cambiar el nombre componentes en cualquier momento durante el tiempo de ejecución, consideraría la adición de métodos que modifican el HashMap de acuerdo con los cambios.

+0

Sí, creo que es una buena solución. Gracias por el código :) – xdevel2000

+1

Tuve problemas con JPanels encadenados en mi formulario. Por lo que una versión ligeramente modivied también camina a través de contenedores que contiene: \t privada Componente getComponentByName (String nombre) { \t \t retorno getComponentByName (. GetMainFrame() getRootPane(), nombre); \t} \t \t privada Componente getComponentByName (raíz de contenedores, String nombre) { \t \t de (componente C: root.getComponents()) { \t \t \t si (name.equals (c.getName())) { \t \t \t \t return c; \t \t \t} \t \t \t si (c instanceof Container) { \t \t \t \t resultado Componente = getComponentByName ((Container) c, nombre); \t \t \t \t si (resultado! = Null) { \t \t \t \t \t return resultado; \t \t \t \t} \t \t \t}} \t \t \t \t devuelto nulo; \t} –

+0

Simple y elegante – kazy

1

Se puede declarar una variable como una pública a continuación, obtener el texto o lo que sea la operación que desea y luego se puede acceder a ella en el otro marco (si es en el mismo paquete) porque es público.

2

puede mantener una referencia al primer JFrame en el segundo JFrame y simplemente recorrer mediante JFrame.getComponents(), verificando el nombre de cada elemento.

6

Cada Component puede tener un nombre, al que se accede a través de getName() y setName(), pero tendrá que escribir su propia función de búsqueda.

4

getComponentByName (marco, nombre)

si usted está utilizando NetBeans IDE u otra que por defecto crea variables privadas (campos) para contener todos sus componentes AWT/Swing, entonces el siguiente código puede trabajar para ti. Utilice la siguiente manera:

// get a button (or other component) by name 
JButton button = Awt1.getComponentByName(someOtherFrame, "jButton1"); 

// do something useful with it (like toggle it's enabled state) 
button.setEnabled(!button.isEnabled()); 

Aquí está el código para que lo anterior sea posible ...

import java.awt.Component; 
import java.awt.Window; 
import java.lang.reflect.Field; 

/** 
* additional utilities for working with AWT/Swing. 
* this is a single method for demo purposes. 
* recommended to be combined into a single class 
* module with other similar methods, 
* e.g. MySwingUtilities 
* 
* @author http://javajon.blogspot.com/2013/07/java-awtswing-getcomponentbynamewindow.html 
*/ 
public class Awt1 { 

    /** 
    * attempts to retrieve a component from a JFrame or JDialog using the name 
    * of the private variable that NetBeans (or other IDE) created to refer to 
    * it in code. 
    * @param <T> Generics allow easier casting from the calling side. 
    * @param window JFrame or JDialog containing component 
    * @param name name of the private field variable, case sensitive 
    * @return null if no match, otherwise a component. 
    */ 
    @SuppressWarnings("unchecked") 
    static public <T extends Component> T getComponentByName(Window window, String name) { 

     // loop through all of the class fields on that form 
     for (Field field : window.getClass().getDeclaredFields()) { 

      try { 
       // let us look at private fields, please 
       field.setAccessible(true); 

       // compare the variable name to the name passed in 
       if (name.equals(field.getName())) { 

        // get a potential match (assuming correct &lt;T&gt;ype) 
        final Object potentialMatch = field.get(window); 

        // cast and return the component 
        return (T) potentialMatch; 
       } 

      } catch (SecurityException | IllegalArgumentException 
        | IllegalAccessException ex) { 

       // ignore exceptions 
      } 

     } 

     // no match found 
     return null; 
    } 

} 

Se utiliza la reflexión para mirar a través de los campos de la clase para ver si se puede encontrar un componente que se refiere por una variable del mismo nombre.

NOTA: El código anterior utiliza genéricos para convertir los resultados al tipo que espere, por lo que en algunos casos es posible que tenga que ser explícito sobre el tipo de conversión. Por ejemplo, si myOverloadedMethod acepta tanto JButton y JTextField, puede ser necesario definir explícitamente la sobrecarga que desea llamar ...

myOverloadedMethod((JButton) Awt1.getComponentByName(someOtherFrame, "jButton1")); 

Y si no está seguro, se puede obtener una Component y comprobar que funciona con instanceof ...

// get a component and make sure it's a JButton before using it 
Component component = Awt1.getComponentByName(someOtherFrame, "jButton1"); 
if (component instanceof JButton) { 
    JButton button = (JButton) component; 
    // do more stuff here with button 
} 

Hope this helps!

1

Necesitaba acceder a elementos dentro de varios JPanel s que estaban dentro de un solo JFrame.

@Jesse Strickland publicó una gran respuesta, pero el código proporcionado no puede acceder a ningún elemento anidado (como en mi caso, dentro de JPanel).

Después de buscar en Google adicional encontré este método recursivo proporcionado por @aioobe here.

combinando y modificando ligeramente el código de @Jesse Strickland y @aioobe que tiene un código de trabajo que se puede acceder a todos los elementos anidados, no importa lo profundas que son:

private void createComponentMap() { 
    componentMap = new HashMap<String,Component>(); 
    List<Component> components = getAllComponents(this); 
    for (Component comp : components) { 
     componentMap.put(comp.getName(), comp); 
    } 
} 

private List<Component> getAllComponents(final Container c) { 
    Component[] comps = c.getComponents(); 
    List<Component> compList = new ArrayList<Component>(); 
    for (Component comp : comps) { 
     compList.add(comp); 
     if (comp instanceof Container) 
      compList.addAll(getAllComponents((Container) comp)); 
    } 
    return compList; 
} 

public Component getComponentByName(String name) { 
    if (componentMap.containsKey(name)) { 
     return (Component) componentMap.get(name); 
    } 
    else return null; 
} 

Uso del código es exactamente lo mismo que en el código @Jesse Strickland.

0

Si sus componentes están declarados dentro de la misma clase que los está manipulando, simplemente acceda a estos componentes como atributos de con el nombre de clase.

public class TheDigitalClock { 

    private static ClockLabel timeLable = new ClockLabel("timeH"); 
    private static ClockLabel timeLable2 = new ClockLabel("timeM"); 
    private static ClockLabel timeLable3 = new ClockLabel("timeAP"); 


    ... 
    ... 
    ... 


      public void actionPerformed(ActionEvent e) 
      { 
       ... 
       ... 
       ... 
        //set all components transparent 
        TheDigitalClock.timeLable.setBorder(null); 
        TheDigitalClock.timeLable.setOpaque(false); 
        TheDigitalClock.timeLable.repaint(); 

        ... 
        ... 
        ... 

       } 
    ... 
    ... 
    ... 
} 

Y, usted puede ser capaz de acceder a los componentes de clase como atributos del nombre de la clase de otras clases en el mismo espacio de nombres demasiado. Puedo acceder a los atributos protegidos (variables miembro de la clase), tal vez también se puede acceder a los componentes públicos. ¡Intentalo!

Cuestiones relacionadas