0

My question is how to access the Swing GUI element tree (main window, JPanels, JFrames, JButtons, JTextFields ect) and create a reference to that tree. I need this to be kept in a data structure (ex. hash map) and NOT in a memory file (eg. using serialization). I need this for using it later to map these UI elements to the corresponding objects inside the code.

EDIT:

   JFrame f = new JFrame("Basic GUI"); 
   JPanel pnl1 = new JPanel(); 
   JPanel pnl2 = new JPanel(); 
   JPanel pnl3 = new JPanel(); 

   JLabel lblText = new JLabel("Test Label");
   JButton btn1 = new JButton("Button");
   JTextField txtField = new JTextField(20);

   public GUISample(){

   pnl1.add(lblText);
   pnl2.add(btn1);
   pnl3.add(txtField);

   f.getContentPane().setLayout(new BorderLayout());
   f.getContentPane().add(pnl2, BorderLayout.EAST);
   f.getContentPane().add(pnl3, BorderLayout.WEST);
   f.getContentPane().add(pnl1, BorderLayout.NORTH);
   visitComponent(f);

   }

   private Map<String, Component> hashMap = new HashMap<String,Component>();

   public Map<String, Component> getComponentsTree(){
      return hashMap;
   }
   public void visitComponent(Component cmp){
      // Add this component
      if(cmp != null) hashMap.put(cmp.getName(), cmp);
      Container container = (Container) cmp;
      if(container == null ) {
          // Not a container, return
          return;
      }
      // Go visit and add all children
      for(Component subComponent : container.getComponents()){
          visitComponent(subComponent);
      }
     System.out.println(hashMap); 

    }
100798
  • 231
  • 6
  • 15
  • Just to make sure it is clear: in a given Swing application, you want to create a data structure in memory of the entire component tree, with all their parent -> children relationship? – Rafael Steil Nov 28 '11 at 21:00
  • Yes, the entire HIERARCHY of the GUI element tree, to be saved in a data structure. – 100798 Nov 28 '11 at 21:01
  • You can use java.awt.Component.getComponents() to get the child components. Can we see an example of how you are going to use it though? Maybe there are alternatives? – jeff Nov 28 '11 at 21:02
  • 4
    @100798: "I need an exact and full example ..." Come on now that's not how it's done here. You've already been given good suggestions on how to implement this, both here and in your previous similar question, and I assume that you understand recursion. Surely you can show us your attempt to solve this yourself first, and then we can help you with that, but don't ask for a full code solution from volunteers. The main effort to solve this problem should come from you not us. Revise this and show us your attempt and most will bend over backwards to try to help you get your code to work. – Hovercraft Full Of Eels Nov 28 '11 at 21:08
  • @HovercraftFullOfEels When I asked for full I stated simple, since I have tried the suggestions but I couldn't get what I wanted - the whole GUI tree. I can post here parts of how that is done, but I don't get what I require. So, if anybody can help, I thank you for it! – 100798 Nov 28 '11 at 21:12
  • 2
    Then please, show us what you've done, and again, most of us will be glad to help, myself included, but please don't beg for code. – Hovercraft Full Of Eels Nov 28 '11 at 21:13
  • don't quite understand: the tree of components _is_ the dataStructure - simply walk it (as suggested here and in your duplicate question) and you'r done :-) – kleopatra Nov 29 '11 at 08:44

3 Answers3

4

Check out Darryl's Component Tree Model.

camickr
  • 321,443
  • 19
  • 166
  • 288
3

Start your program from the command line and type control+shift+F1 to see a dump of the active Swing container hierarchy, as shown here. It's not terribly readable, but the indents are a reliable reflection of the hierarchy.

Addendum: The result obtained in this manner is useful as a standard against which to evaluate a programatic implementation. For reference, I ran Darryl's ComponentTree against itself and compared the keyboard result to a cut & paste copy of the JTree. Only minor differences emerged:

  1. The dump starts with the enclosing JFrame, while the tree starts with the frame's root pane.

  2. The dump is lexically indented, while the tree models the hierarchy directly.

  3. The dump includes instances of CellRendererPane, marked hidden, which are used by the JTable rendering implementation; the tree does not.

Ignoring these, the component order is identical in both.

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • I think PO wants to get this programaticaly – GETah Nov 29 '11 at 07:42
  • You're probably right; if the OP can't use this, I'll make it a comment. – trashgod Nov 29 '11 at 12:12
  • Yes, I need this programaticaly. This with CTRL+SHIFT+F1 is good since actually gives the whole tree hierarchy. The @GETah solution gives some of the components but not all and not the hierarchy. Any idea how to manage the code to work to give the whole hierarchy? – 100798 Nov 29 '11 at 12:32
  • Following @camickr's suggestion, _Component Tree Model_ compares favorably to the keyboard generated dump; more above. – trashgod Nov 29 '11 at 20:01
2

I have been thinking about this problem. Here is my suggestion:

public class ComponentTreeBuilder{
   private Map<String, Component> hashMap = new HashMap<String,Component>();
   public Map<String, Component> getComponentsTree(){
      return hashMap;
   }
   public void visitComponent(Component cmp){
      // Add this component
      if(cmp != null) hashMap.put(cmp.getName(), cmp);
      Container container = (Container) cmp;
      if(container == null ) {
          // Not a container, return
          return;
      }
      // Go visit and add all children
      for(Component subComponent : container.getComponents()){
          visitComponent(subComponent);
      }
   }
}

And use this like this:

Frame myFrame = new JFrame();
// Make sure you add your elements into the frame's content pane by
myFrame.getContentPane(component);
ComponentTreeBuilder cmpBuilder = new ComponentTreeBuilder();
cmpBuilder.visitComponent(myFrame);
Map<String, Component> components = cmpBuilder.getComponentsTree(); 
// All components should now be in components hashmap

Please note that ComponentTreeBuilder is using recursion, this might throw a stack overflow exception if you have too many components in your GUI.

EDIT Just tested this code on real example and.... it works :)

Here is the code:

JFrame frame = new JFrame();
frame.getContentPane().add(new JButton());
frame.getContentPane().add(new JButton());
frame.getContentPane().add(new JButton());
frame.getContentPane().add(new JButton());
visitComponent(frame);

And here is the output:

enter image description here

GETah
  • 20,922
  • 7
  • 61
  • 103
  • Small correction needed: In the loop "for (Component subComponent : cmp.getComponents()) It does not recognize the method cmp.getComponents. – 100798 Nov 28 '11 at 21:34
  • I tried you solution and it works almost. The only problem is that it does not show the whole tree hierarchy, and this I checked with the CTRL+SHIFT+F1. Do you have any idea why it does not capture the whole tree? – 100798 Nov 29 '11 at 12:30
  • @100798 The hashmap does extract all components and save them by their names. It does however **not** save the relationship between these components. – GETah Nov 29 '11 at 12:32
  • I run the code and I am comparing to the other non-programatical solution. The code does not give the whole elements, it does not capture the elements inside panels (buttons, textfields ect), but only the main frame and part of the panels. Something is missing in the function? – 100798 Nov 29 '11 at 12:41
  • The code does not get the JPanels, that is, it does not goes one level down to JPanels and after in its components. If there is a method for getting the Panels from the JFrame, that would solve it. – 100798 Nov 29 '11 at 14:59
  • @100798 Just run the code on my side, it works like a charm! Please post the code creating your frame. Also make sure all your components' names are set – GETah Nov 29 '11 at 15:10
  • @100798 Please see my edit. Just added my tests on my side, the algorithm works fine. – GETah Nov 29 '11 at 15:21
  • I can not get the required tree as you get, so please can you post the sample so I can fix my case. Thank you! – 100798 Nov 29 '11 at 20:05
  • @100798 Please see my edit, that is all what I did. Create a sample form and fill it with some objects and then run the visitComponent method on it. Please post your code so that we can figure out what is wrong with it. – GETah Nov 29 '11 at 20:11
  • This works but I think there are redundant (doubled) UI elements showed. – 100798 Nov 29 '11 at 20:36
  • Ah great. Glad it worked. Please mark this as an answer if it fixed your problems :) – GETah Nov 29 '11 at 20:38
  • @100798 You are right, components are added twice. Please see my edit, it should be fixed now – GETah Nov 29 '11 at 20:44
  • No difference. What did you change? So if you can fix this, let close this by marking as an answer, because it became to long. Thank you! – 100798 Nov 29 '11 at 20:54
  • I removed hashmap.add inside the for loop. Agree, please post another question regarding the new issue with the corresponding code. – GETah Nov 29 '11 at 21:22
  • Thank you for you continous support. Just a little remark. Even removing that line of code inside the FOR LOOP, does not solve the redundancy issue. If you can fix that, that would complete your answer. – 100798 Nov 29 '11 at 22:10
  • Ok I will have a look at it tomorrow :) and will keep you posted – GETah Nov 29 '11 at 22:14
  • @100798 Just did a test with the changes, it works fine! Please post your code in another question I am sure we will get your problems fixed – GETah Nov 30 '11 at 09:12
  • I think it's not good to post the same question again. It remains small fixing about the redundancy. If you try my example above, you will face the redundancy problem. Let me know if there is something wrong with the example provided. – 100798 Nov 30 '11 at 14:30