按名称获取Swing组件

时间:2011-02-10 14:54:23

标签: java swing jframe

我有JFrame个我想要的组件 引用另一个JFrame,我想要 通过名字得到他们而不是 为每个人做公共获取/设置方法。

是否有一种方法可以让Swing通过其名称获取组件引用,如do C#?

e.g。 form.Controls["text"]

由于

8 个答案:

答案 0 :(得分:27)

我知道这是一个老问题,但我发现自己现在才问这个问题。我想要一种简单的方法来按名称获取组件,这样我就不必每次都要编写一些复杂的代码来访问不同的组件。例如,让JButton访问文本字段中的文本或列表中的选择。

最简单的解决方案是使所有组件变量成为类变量,以便您可以在任何地方访问它们。但是,不是每个人都想这样做,有些人(比如我自己)正在使用不会将组件生成为类变量的GUI编辑器。

我的解决方案很简单,我想,并且并没有真正违反任何编程标准,据我所知(参考fortran的内容)。它允许以简单直接的方式按名称访问组件。

  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. 在您的课程中定义以下两种方法。如果您尚未导入,则需要导入Component:

    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,它将您的框架/内容窗格/面板/等中的所有当前现有组件映射到它们各自的名称。

  5. 现在访问这些组件,就像调用getComponentByName(String name)一样简单。如果存在具有该名称的组件,则它将返回该组件。如果不是,则返回null。您有责任将组件转换为正确的类型。我建议使用instanceof来确定。

  6. 如果您计划在运行时的任何时候添加,删除或重命名组件,我会考虑添加根据您的更改修改HashMap的方法。

答案 1 :(得分:6)

每个Component都可以有一个名称,可以通过getName()setName()访问,但您必须编写自己的查找功能。

答案 2 :(得分:4)

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同时接受JButtonJTextField,您可能需要明确定义要调用的重载...

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
}

希望这有帮助!

答案 3 :(得分:2)

你可以在第二个JFrame中保存对第一个JFrame的引用,然后循环遍历JFrame.getComponents(),检查每个元素的名称。

答案 4 :(得分:1)

您可以将变量声明为公共变量,然后获取所需的文本或任何操作,然后您可以在另一个框架中访问它(如果它在同一个包中),因为它是公共的。

答案 5 :(得分:1)

我需要访问位于单个JPanel内的多个JFrame内的元素。

@Jesse Strickland发布了一个很好的答案,但提供的代码无法访问任何嵌套元素(就像我的情况一样,在JPanel内)。

经过额外的Google搜索后,我发现@aioobe here提供了这种递归方法。

通过组合并略微修改@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代码完全相同。

答案 6 :(得分:0)

如果您的组件是在同一个类中声明的,那么您只需将这些组件作为类名的属性进行访问。

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

                     ...
                     ...
                     ...

                }
    ...
    ...
    ...
}

而且,可能能够将类组件作为类名的属性从同一名称空间中的其他类访问。我可以访问受保护的属性(类成员变量),也许您也可以访问公共组件。试试吧!

答案 7 :(得分:0)

Swing 确实提供了其他方法来实现这一点,因为这里是我在组件层次结构上下文中实现查找的版本。

/**
 * Description          : Find a component having the given name in container  desccendants hierarchy
 * Assumptions          : First component with the given name is returned
 * @return java.awt.Component
 * @param component java.awt.Component
 * @param componentName java.lang.String
 */
public static Component findComponentByName(Component component, String componentName) {
  if (component == null ) {
    return null;
  }

  if (component.getName() != null && component.getName().equalsIgnoreCase(componentName)) {
    return component;
  } 

  if ( (component instanceof Container )  ) {       
    Component[] children = ((Container) component).getComponents();
    for ( int i=0; i<children.length; i++ ) {
        Component child = children[i];
        Component found = findComponentByName( child, componentName );
        if (found != null ) {
            return found;
        }
    }
  }
  return null;
}