简体   繁体   English

按名称获取 Swing 组件

[英]Get a Swing component by name

I have in a JFrame some components that I want to refer into another JFrame and I want to get them by name and not do public get/set methods for each.我在JFrame有一些组件,我想将它们引用到另一个JFrame ,我想按名称获取它们,而不是为每个组件执行公共 get/set 方法。

Is there a way from Swing to get a component reference by its name like do c#?有没有办法从 Swing 像 c# 一样通过名称获取组件引用?

eg form.Controls["text"]例如form.Controls["text"]

Thanks谢谢

I know this is an old question, but I found myself asking it just now.我知道这是一个老问题,但我发现自己现在才问这个问题。 I wanted an easy way to get components by name so I didn't have to write some convoluted code each time to access different components.我想要一种通过名称获取组件的简单方法,这样我就不必每次都编写一些复杂的代码来访问不同的组件。 For example, having a JButton access the text in a text field or a selection in a List.例如,让 JButton 访问文本字段中的文本或列表中的选择。

The easiest solution is to make all of the component variables be class variables so that you can access them anywhere.最简单的解决方案是将所有组件变量设为类变量,以便您可以在任何地方访问它们。 However, not everyone wants to do that, and some (like myself) are using GUI Editors that don't generate the components as class variables.然而,并不是每个人都想这样做,有些人(比如我自己)正在使用不会将组件生成为类变量的 GUI 编辑器。

My solution is simple, I'd like to think, and doesn't really violate any programming standards, as far as I know (referencing what fortran was getting at).我的解决方案很简单,我想,据我所知,并没有真正违反任何编程标准(参考 fortran 的内容)。 It allows for an easy and straightforward way to access components by name.它允许通过名称访问组件的简单直接的方法。

  1. Create a Map class variable.创建一个 Map 类变量。 You'll need to import HashMap at the very least.您至少需要导入 HashMap。 I named mine componentMap for simplicity.为简单起见,我将我的 componentMap 命名为。

     private HashMap componentMap;
  2. Add all of your components to the frame as normal.像往常一样将所有组件添加到框架中。

     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. Define the following two methods in your class.在您的类中定义以下两个方法。 You'll need to import Component if you haven't already:如果您还没有导入 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. Now you've got a HashMap that maps all the currently existing components in your frame/content pane/panel/etc to their respective names.现在您已经有了一个 HashMap,它将框架/内容窗格/面板/等中所有当前存在的组件映射到它们各自的名称。

  5. To now access these components, it is as simple as a call to getComponentByName(String name).现在要访问这些组件,就像调用 getComponentByName(String name) 一样简单。 If a component with that name exists, it will return that component.如果存在具有该名称的组件,它将返回该组件。 If not, it returns null.如果不是,则返回 null。 It is your responsibility to cast the component to the proper type.您有责任将组件转换为正确的类型。 I suggest using instanceof to be sure.我建议使用 instanceof 来确定。

If you plan on adding, removing, or renaming components at any point during runtime, I would consider adding methods that modify the HashMap according to your changes.如果您计划在运行时的任何时候添加、删除或重命名组件,我会考虑添加根据您的更改修改 HashMap 的方法。

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

getComponentByName(frame, name) getComponentByName(框架,名称)

IF you're using NetBeans or another IDE that by default creates private variables (fields) to hold all of your AWT/Swing components, then the following code may work for you.如果您使用 NetBeans 或其他默认情况下创建私有变量(字段)来保存所有 AWT/Swing 组件的 IDE,那么以下代码可能适合您。 Use as follows:使用方法如下:

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

Here's the code to make the above possible...这是使上述成为可能的代码......

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

}

It uses reflection to look through the class fields to see if it can find a component that is referred to by a variable of the same name.它使用反射来查看类字段以查看是否可以找到由同名变量引用的组件。

NOTE: The code above uses generics to cast the results to whatever type you are expecting, so in some cases you may have to be explicit about type casting.注意:上面的代码使用泛型将结果转换为您期望的任何类型,因此在某些情况下您可能必须明确类型转换。 For example if myOverloadedMethod accepts both JButton and JTextField , you may need to explicitly define the overload you wish to call ...例如,如果myOverloadedMethod接受JButtonJTextField ,您可能需要明确定义您希望调用的重载...

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

And if you're not sure, you can get an Component and check it with instanceof ...如果您不确定,您可以获取一个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
}

Hope this helps!希望这可以帮助!

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

I needed to access elements inside several JPanel s which were inside a single JFrame .我需要访问多个JPanel的元素,这些元素位于单个JFrame

@Jesse Strickland posted a great answer, but the provided code is not able to access any nested elements (like in my case, inside JPanel ). @Jesse Strickland 发布了一个很好的答案,但提供的代码无法访问任何嵌套元素(例如在我的情况下,在JPanel )。

After additional Googling I found this recursive method provided by @aioobe here .在额外的谷歌搜索之后,我发现了@aioobe here提供的这个递归方法。

By combining and slightly modifying the code of @Jesse Strickland and @aioobe I got a working code that can access all the nested elements, no matter how deep they are:通过组合并稍微修改@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;
}

Usage of the code is exactly the same as in @Jesse Strickland code.代码的用法与@Jesse Strickland 代码中的用法完全相同。

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

If your components are declared inside the same class you're manipulating them from, you simply access these components as attributes of the class name .如果您的组件是在您操作它们的同一个类中声明的,您只需将这些组件作为类名的属性来访问。

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

                     ...
                     ...
                     ...

                }
    ...
    ...
    ...
}

And, you may be able to access class components as attributes of the class name from other classes in the same namespace too .而且,您可以从同一命名空间中的其他类访问类组件作为类名的属性。 I can access protected attributes(class member variables), maybe you can access public components, too.我可以访问受保护的属性(类成员变量),也许您也可以访问公共组件。 Try it!尝试一下!

Swing does provide other ways to implement this, for the sake as exercising here is my version that implements a find in Component hierarchy context. 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM