Получить компонент 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 <T>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();
...
...
...
}
...
...
...
}
И вы можете иметь доступ к компонентам класса в качестве атрибутов имени класса из других классов в одном и том же пространстве имен.. Я могу получить доступ к защищенным атрибутам (переменные-члены класса), возможно, вы также можете получить доступ к общедоступным компонентам. Попробуйте!