Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
354 views
in Technique[技术] by (71.8m points)

java - Iterate / recurse through Containers and Components to find objects of a given class?

I've written a MnemonicsBuilder class for JLabels and AbstractButtons. I would like to write a convenience method setMnemonics( JFrame f ) that will iterate through every child of the JFrame and select out the JLabels and AbstractButtons. How can I obtain access to everything contained in the JFrame? I've tried:

LinkedList<JLabel> harvestJLabels( Container c, LinkedList<JLabel> l ) {
    Component[] components = c.getComponents();
    for( Component com : components )
    {
        if( com instanceof JLabel )
        {
            l.add( (JLabel) com );
        } else if( com instanceof Container )
        {
            l.addAll( harvestJLabels( (Container) com, l ) );
        }
    }
    return l;
}

In some situations, this works just fine. In others, it runs out of memory. What am I not thinking of? Is there a better way to search for child components? Is my recursion flawed? Is this not a picture of how things "Contain" other things in Swing - e.g., is Swing not a Rooted Tree?

JFrame
|
|\__JMenuBar
|   |
|    \__JMenu
|       |
|        \__JMenuItem
|
|\__JPanel
|   |
|   |\__JButton 
|   |
|   |\__JLabel
|   |
|   |\__ ... JCheckBoxes, other AbstractButtons, etc.
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Agree with Tom here... Your problem is that you're already passing the List to add the JLabels down to your recursive method AND you're also returning it - thus adding the same items to your list more than once. In more politically correct terms - the List is your accumulator.

Your method should instead look like this:

public void harvestJLabels(Container c, List<JLabel> l) {
    Component[] components = c.getComponents();
    for(Component com : components) {
        if(com instanceof JLabel) {
            l.add((JLabel) com);
        } else if(com instanceof Container) {
            harvestJLabels((Container) com, l));
        }
    }
}

Then you can have a helper method to initiate this harvesting:

public List<JLabel> harvestJLabels(Container c) {
    List<JLabel> jLabels = new ArrayList<JLabel>();
    harvestJLabels(c, jLabels);
    return jLabels;
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...