Получить компонент Swing по имени - PullRequest
14 голосов
/ 10 февраля 2011

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

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

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

Спасибо

Ответы [ 7 ]

27 голосов
/ 02 сентября 2011

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

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

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

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

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

    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. Определитеследующие два метода в вашем классе.Вам нужно будет импортировать Компонент, если вы еще этого не сделали:

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

  5. Чтобы получить доступ к этим компонентам, достаточно просто вызвать getComponentByName (String name).Если компонент с таким именем существует, он вернет этот компонент.Если нет, возвращается ноль.Вы несете ответственность за приведение компонента к нужному типу.Для уверенности я предлагаю использовать instanceof.

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

6 голосов
/ 10 февраля 2011

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

4 голосов
/ 23 июля 2013

getComponentByName (frame, name)

ЕСЛИ вы используете 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's 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'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
}

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

2 голосов
/ 10 февраля 2011

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

1 голос
/ 03 марта 2015

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

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

После дополнительного поиска в Google я нашел этот рекурсивный метод, предоставленный @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.

1 голос
/ 10 февраля 2011

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

0 голосов
/ 30 ноября 2017

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

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

                     ...
                     ...
                     ...

                }
    ...
    ...
    ...
}

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...