2

First, JComponent instance jComponent created. Then it was added to it's parent like parent.add(jComponent);. Now I want to know in jComponent class that it was added to it's parent. Is it possible to do that?

The goal is to set jComponent parent when it was already added to it's parent, like:

Container window = getParent();
        while (!(window instanceof JWindow)) {
            window = window.getParent();
        }
JWindow parent = (JWindow) window;
Ernestas Gruodis
  • 8,567
  • 14
  • 55
  • 117

4 Answers4

8

There are multiple choices, depending on your needs.

If you want to know when any existing component is added to a parent, you can add a HierarchyListener to it and listen for an event of type PARENT_CHANGED which is sent after the component is added to the parent.

Example:

component.addHierarchyListener(new HierarchyListener() {

  @Override
  public void hierarchyChanged(HierarchyEvent e) {
    if ( (e.getChangeFlags() & HierarchyEvent.PARENT_CHANGED) != 0) {
      if (getParent() == e.getChangedParent()) {
         System.out.println("*** Added to parent " + e.getChangedParent());
      }
    }
  }
});

If you are already creating a custom component, you can override the "addNotify()" method:

@Override public void addNotify() {
  super.addNotify();
  // do something here with getParent();
}

If you want to know about the parent only after the component has been made visible, you can use an AncestorListener. The ancestorAdded(AncestorEvent) will be called every time the component is made visible. For instance, an AncestorListener on a JPanel inside a JTabbedPane will get such an event every time the user selects that tab for display.

Enwired
  • 1,563
  • 1
  • 12
  • 26
4

Use

javax.swing.SwingUtilities.getWindowAncestor(yourComponent)

it returns the window where your component was added into or null if it wasn't added to a window.

Of course if you add your component to a JPanel which in its turn is not yet added into a window the method above will return null.

In this case one of the comments is better: component.getParent() will then give you the Container that contains your component if any exists.

GerritCap
  • 1,606
  • 10
  • 9
2

You may be looking for an AncestorListener, shown here. The ancestorAdded() method will be "Called when the source or one of its ancestors is made visible either by setVisible(true) being called or by its being added to the component hierarchy."

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • The AncestorListener lets you know every time the component actually becomes visible due to something happening in the hierarchy. If it is a child of a JTabbedPane, for example, ancestorAdded() will be called every time the tab is made visible. If you only want to know when the component was added to its parent, regardless of current visibilty, the HieararchyListener is the thing to use. – Enwired Aug 29 '13 at 00:15
  • Right, but I'm not sure there's enough information in the question to choose. Why don't you expand your answer & I'll delete mine. – trashgod Aug 29 '13 at 00:51
  • 1
    I've tried also `AncestorListener`, working fine, but `AncestorEvent` happens only when parent is set visible. When overriding `addNotify()`, it is called immediately after child is added to parent, even if the parent not visible. So I prefer `addNotify()`, because I can create the dialog instance before it is made visible - it opens a little bit faster when user clicks some button. – Ernestas Gruodis Aug 29 '13 at 07:38
1

So the answer is:

public class MyComponent extends JComponent {

   private JWindow parent;

   //(...)

   @Override
   public void addNotify() {
     parent = (JWindow) SwingUtilities.getAncestorOfClass(JWindow.class, getParent());
     super.addNotify();
   }

}

Or we can do:

   @Override
   public void addNotify() {
     parent = (JWindow) SwingUtilities.getWindowAncestor(this);
     super.addNotify();
   }

Don't know which is better, looks like the second method is simpler.

Ernestas Gruodis
  • 8,567
  • 14
  • 55
  • 117
  • 1
    Overriding addNotify would work, but you have to create a sub-class, like you did above. If you want to use an existing component without making a sub-class, then just use the HierarchyListener interface. – Enwired Aug 28 '13 at 23:41
  • Yes, it also works, tested :) But the code is larger, compared to overriding `addNotify()`. – Ernestas Gruodis Aug 29 '13 at 07:56
  • 1
    Well, it depends on whether you are creating a sub-class or not. Anyway, your code for determining the owning JWindow can be made simpler. You do not need the 'while' loop: parent = (JWindow) SwingUtilities.getAncestorOfClass(JWindow.class, getParent()); – Enwired Aug 29 '13 at 18:02
  • @Enwired Thanks indeed, this method is superb, tested. I have changed my answer above. – Ernestas Gruodis Aug 29 '13 at 19:13
  • Also tested as @GerritCap suggested: `SwingUtilities.getWindowAncestor(this);` Works the same. Looks like even better? – Ernestas Gruodis Aug 29 '13 at 19:17