webentwicklung-frage-antwort-db.com.de

Rufen Sie eine Swing-Komponente nach Namen ab

Ich habe in einer JFrame einige Komponenten, die ich möchte, dass Auf eine andere JFrame verweist, und ich möchte , Um sie nach Namen zu erhalten, und nicht , Um öffentliche Methoden für jeden zu erhalten.

Gibt es eine Möglichkeit von Swing, eine Komponentenreferenz anhand ihres Namens zu erhalten, wie in C #?

z.B. form.Controls["text"]

Vielen Dank

14
xdevel2000

Ich weiß, das ist eine alte Frage, aber ich habe mich gerade gefragt. Ich wollte eine einfache Möglichkeit, Komponenten anhand des Namens zu erhalten, sodass ich nicht jedes Mal etwas gewundenen Code schreiben musste, um auf andere Komponenten zuzugreifen. Wenn Sie beispielsweise eine J-Taste haben, können Sie auf den Text in einem Textfeld oder auf eine Auswahl in einer Liste zugreifen.

Die einfachste Lösung besteht darin, alle Komponentenvariablen zu Klassenvariablen zu machen, sodass Sie von überall darauf zugreifen können. Das will jedoch nicht jeder, und einige (wie ich) verwenden GUI-Editoren, die die Komponenten nicht als Klassenvariablen generieren.

Meine Lösung ist einfach, würde ich gerne nachdenken und verstößt, soweit ich weiß, nicht wirklich gegen Programmierstandards (Bezug darauf, worauf sich fortran bezogen hat). Es ermöglicht einen einfachen und unkomplizierten Zugriff auf Komponenten anhand des Namens.

  1. Erstellen Sie eine Map-Klassenvariable. Sie müssen HashMap mindestens am Importieren. Ich habe meine Komponentenkarte der Einfachheit halber genannt.

    private HashMap componentMap;
    
  2. Fügen Sie alle Ihre Komponenten wie gewohnt dem Rahmen hinzu.

    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. Definieren Sie die folgenden zwei Methoden in Ihrer Klasse. Sie müssen Component importieren, wenn Sie noch nicht

    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. Jetzt haben Sie eine HashMap, die alle aktuell in Ihrem Frame-/Content-Bereich/Panel/etc vorhandenen Komponenten ihren jeweiligen Namen zuordnet.

  5. Um jetzt auf diese Komponenten zuzugreifen, müssen Sie getComponentByName (String-Name) aufrufen. Wenn eine Komponente mit diesem Namen vorhanden ist, wird diese Komponente zurückgegeben. Wenn nicht, wird null zurückgegeben. Es liegt in Ihrer Verantwortung, die Komponente auf den richtigen Typ zu gießen. Ich empfehle die Verwendung von instanceof, um sicherzugehen.

Wenn Sie planen, Komponenten zu einem beliebigen Zeitpunkt zur Laufzeit hinzuzufügen, zu entfernen oder umzubenennen, würde ich in Betracht ziehen, Methoden hinzuzufügen, die die HashMap entsprechend Ihren Änderungen ändern.

27

Jede Component kann einen Namen haben, auf den über getName() und setName() zugegriffen wird, aber Sie müssen Ihre eigene Suchfunktion schreiben.

6
trashgod

getComponentByName (Frame, Name)

Wenn Sie NetBeans oder ein anderes IDE verwenden, das standardmäßig private Variablen (Felder) erstellt, in denen alle AWT/Swing-Komponenten enthalten sind, funktioniert der folgende Code möglicherweise für Sie. Verwenden Sie wie folgt:

// 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());

Hier ist der Code, um das Obige zu ermöglichen ...

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;
    }

}

Mit Reflection wird durch die Klassenfelder gesucht, um zu sehen, ob eine Komponente gefunden werden kann, auf die eine Variable mit demselben Namen verweist. 

ANMERKUNG: Im obigen Code werden die Ergebnisse mit Generics in den von Ihnen erwarteten Typ umgewandelt. In einigen Fällen müssen Sie sich daher explizit mit der Typumwandlung befassen. Wenn zum Beispiel myOverloadedMethod sowohl JButton als auch JTextField akzeptiert, müssen Sie möglicherweise die Überladung explizit definieren, die Sie aufrufen möchten ...

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

Und wenn Sie sich nicht sicher sind, können Sie eine Component erhalten und diese mit instanceof... überprüfen.

// 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
}

Hoffe das hilft!

4
Jonathan

sie könnten einen Verweis auf den ersten JFrame im zweiten JFrame halten und einfach JFrame.getComponents () durchlaufen, um den Namen der einzelnen Elemente zu überprüfen.

2
Andy

Ich musste auf Elemente in mehreren JPanels zugreifen, die sich in einer einzigen JFrame befanden.

@Jesse Strickland hat eine großartige Antwort gepostet, aber der bereitgestellte Code kann nicht auf verschachtelte Elemente zugreifen (wie in meinem Fall in JPanel).

Nach zusätzlichem Googeln fand ich diese rekursive Methode von @aioobe hier .

Durch die Kombination und leichte Modifizierung des Codes von @Jesse Strickland und @aioobe erhielt ich einen Funktionscode, der auf alle geschachtelten Elemente zugreifen kann, unabhängig davon, wie tief sie sind:

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;
}

Die Verwendung des Codes ist genauso wie im Code von @Jesse Strickland.

1
kazy

Sie können eine Variable als öffentlich deklarieren und dann den Text oder die gewünschte Operation abrufen. Anschließend können Sie auf die Variable im anderen Frame zugreifen (sofern sie im selben Paket enthalten ist), da sie öffentlich ist.

1
Mojo_Jojo

Wenn Ihre Komponenten in derselben Klasse deklariert sind, von der Sie sie bearbeiten, greifen Sie auf diese Komponenten als Attribute von dem Klassennamen zu.

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();

                     ...
                     ...
                     ...

                }
    ...
    ...
    ...
}

Und Sie können können auf Klassenkomponenten als Attribute des Klassennamens auch von anderen Klassen im selben Namensraum zugreifen . Ich kann auf geschützte Attribute (Klassenmitgliedervariablen) zugreifen, möglicherweise können Sie auch auf öffentliche Komponenten zugreifen. Versuch es!

0