Java 检测组件的移除

Java 检测组件的移除,java,swing,Java,Swing,我使用PopupFactory.getPopup方法创建一个Popup。根据文档,当不再需要时,我需要在弹出窗口上调用hide()方法 在我的应用程序中,弹出窗口是JLabel的子对象,在许多不同的情况下,该子对象可能会从当前帧中删除。(删除JLabel本身或其父容器之一)而不是在每个位置调用hide()(并使弹出窗口对象在所有这些位置都可用),我更希望能够检测到JLabel或其父容器之一的删除 如何检测到删除?我天真地认为删除组件意味着删除/隐藏其子组件,但正如下面的代码所示,弹出窗口在删除J

我使用
PopupFactory.getPopup
方法创建一个
Popup
。根据文档,当不再需要时,我需要在弹出窗口上调用
hide()
方法

在我的应用程序中,弹出窗口是
JLabel
的子对象,在许多不同的情况下,该子对象可能会从当前帧中删除。(删除
JLabel
本身或其父容器之一)而不是在每个位置调用
hide()
(并使
弹出窗口
对象在所有这些位置都可用),我更希望能够检测到
JLabel
或其父容器之一的删除

如何检测到删除?我天真地认为删除组件意味着删除/隐藏其子组件,但正如下面的代码所示,弹出窗口在删除
JLabel
后仍然存在

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class Xyzzy extends JFrame {
    static Xyzzy frame;
    static JPanel panel;
    static JLabel text1;
    static JLabel text2;

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    frame = new Xyzzy();
                    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.PAGE_AXIS));

                    panel = new JPanel();
                    panel.setLayout(new BoxLayout(panel, BoxLayout.LINE_AXIS));
                    frame.add(panel);


                    text1 = new JLabel("text1");
                    text2 = new JLabel("text2");

                    panel.add(text1);

                    frame.add(new JButton(new AbstractAction("Add popup") {
                            public void actionPerformed(ActionEvent e) {
                                PopupFactory factory = PopupFactory.getSharedInstance();
                                Popup popup = factory.getPopup(text1, new JLabel("POPUP"),frame.getX()+300,frame.getY()+300);
                                popup.show();
                            }
                        }));

                    frame.add(new JButton(new AbstractAction("New label") {
                            public void actionPerformed(ActionEvent e) {
                                panel.remove(text1);
                                panel.add(text2);
                                panel.revalidate();
                            }
                        }));

                    frame.setSize(600, 600);
                    frame.setVisible(true);
                }
            });
    }
}
此代码创建一个显示文本“text1”和两个按钮的
JFrame
。如果按下标记为“添加弹出窗口”的按钮,窗口中将出现一个带有文本“弹出窗口”的弹出窗口。此弹出窗口是
text1
的子窗口。按下“新标签”按钮,“文本1”将从显示屏上删除,但弹出窗口仍然存在


我需要能够检测何时删除
text1
或包含
面板
,以便隐藏弹出窗口。我希望避免在调用实际的
remove()
方法时添加代码。

您可以使用HierarchyListener:

public void actionPerformed(ActionEvent e) {
  PopupFactory factory = PopupFactory.getSharedInstance();
  final Popup popup = factory.getPopup(text1, new JLabel("POPUP"),frame.getX()+300,frame.getY()+300);
  text1.addHierarchyListener(new HierarchyListener() {

    public void hierarchyChanged(HierarchyEvent e) {
      if (e.getID() == HierarchyEvent.HIERARCHY_CHANGED
          && (e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
        popup.hide();
      }
    }
  });
  popup.show();
}