Получить компонент Swing по имени

У меня есть в JFrame некоторые компоненты, которые я хочу обратиться к другому JFrame, и я хочу получить их по имени, а не делать общедоступные методы get/set для каждого.

Есть ли способ от Swing получить ссылку на компонент по имени, например do С#?

например. form.Controls["text"]

Спасибо

Ответы

Ответ 1

Я знаю, что это старый вопрос, но я сразу же спросил его. Я хотел получить простой способ получить компоненты по имени, поэтому мне не приходилось писать какой-то изогнутый код каждый раз для доступа к различным компонентам. Например, если JButton получает доступ к тексту в текстовом поле или в списке в списке.

Самое простое решение - превратить все переменные компонента в переменные класса, чтобы вы могли получить к ним доступ в любом месте. Однако не все хотят это сделать, а некоторые (например, я) используют графические редакторы, которые не генерируют компоненты как переменные класса.

Мое решение простое, я бы хотел подумать и на самом деле не нарушать какие-либо стандарты программирования, насколько я знаю (ссылка на то, что fortran получал). Это позволяет легко и просто получить доступ к компонентам по имени.

  • Создайте переменную класса карты. Вам нужно будет импортировать HashMap на по крайней мере. Для простоты я назвал my componentMap.

    private HashMap componentMap;
    
  • Добавьте все ваши компоненты в кадр как обычно.

    initialize() {
        //add your components and be sure
        //to name them.
        ...
        //after adding all the components,
        //call this method we're about to create.
        createComponentMap();
    }
    
  • Определите следующие два метода в своем классе. Вам нужно будет импортировать компонент, если вы еще этого не сделали:

    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;
    }
    
  • Теперь у вас есть HashMap, который отображает все существующие в настоящее время компоненты в вашем фрейме/панели содержимого/панели/etc для их соответствующих имен.

  • Теперь для доступа к этим компонентам это так же просто, как вызов getComponentByName (имя строки). Если компонент с таким именем существует, он вернет этот компонент. Если нет, он возвращает null. Вы несете ответственность за включение компонента в соответствующий тип. Я предлагаю использовать instanceof, чтобы быть уверенным.

Если вы планируете добавлять, удалять или переименовывать компоненты в любой момент во время выполнения, я бы рассмотрел возможность добавления методов, которые изменяют HashMap в соответствии с вашими изменениями.

Ответ 2

Каждый Component может иметь имя, доступное через getName() и setName(), но вам придется писать свои собственные функция поиска.

Ответ 3

getComponentByName (фрейм, имя)

ЕСЛИ вы используете NetBeans или другую среду IDE, которая по умолчанию создает частные переменные (поля) для хранения всех компонентов AWT/Swing, тогда для вас может работать следующий код. Используйте следующее:

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

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

Вот код, чтобы сделать возможным...

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

}

Он использует отражение, чтобы просмотреть поля класса, чтобы увидеть, может ли он найти компонент, на который ссылается переменная с тем же именем.

ПРИМЕЧАНИЕ. В приведенном выше коде используются дженерики, чтобы отнести результаты к тому типу, который вы ожидаете, поэтому в некоторых случаях вам может потребоваться быть явным в отношении литья типов. Например, если myOverloadedMethod принимает как JButton, так и JTextField, вам может потребоваться явно определить перегрузку, которую вы хотите вызвать...

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

И если вы не уверены, вы можете получить Component и проверить его с помощью instanceof...

// get a component and make sure it 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
}

Надеюсь, это поможет!

Ответ 4

вы могли бы провести ссылку на первый JFrame во втором JFrame и просто пропустить JFrame.getComponents(), проверяя имя каждого элемента.

Ответ 5

Вы можете объявить переменную как общедоступную, затем получить текст или любую другую операцию, которую вы хотите, а затем вы можете получить к ней доступ в другом фрейме (если это в том же пакете), потому что он общедоступен.

Ответ 6

Мне нужно было получить доступ к элементам внутри нескольких JPanel, которые находились внутри одного JFrame.

@Jesse Strickland опубликовал отличный ответ, но предоставленный код не может получить доступ к каким-либо вложенным элементам (например, в моем случае, внутри JPanel).

После дополнительного Googling я нашел этот рекурсивный метод, предоставленный @aioobe здесь.

Объединив и слегка изменив код @Jesse Strickland и @aioobe, я получил рабочий код, который может получить доступ ко всем вложенным элементам, независимо от того, насколько они глубоки:

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

Использование кода в точности совпадает с кодом @Jesse Strickland.

Ответ 7

Если ваши компоненты объявлены внутри того же класса, из которого вы ими управляете, вы просто обращаетесь к этим компонентам как к атрибутам имени класса.

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

                     ...
                     ...
                     ...

                }
    ...
    ...
    ...
}

И вы можете иметь доступ к компонентам класса в качестве атрибутов имени класса из других классов в одном и том же пространстве имен.. Я могу получить доступ к защищенным атрибутам (переменные-члены класса), возможно, вы также можете получить доступ к общедоступным компонентам. Попробуйте!