侦听组件何时首次显示

2022-09-03 00:14:40

我试图捕捉屏幕上显示组件的第一个时刻,而不使用“肮脏”的解决方案,就像使用计时器一样。基本上,我想知道什么时候我可以安全地开始在组件上使用方法。getLocationOnScreen()

我以为组件听众可以提供帮助,但在这里没有运气。我现在卡住了,不知道该用哪个听众。有什么建议吗?

下面是一些示例代码,它显示组件侦听器失败。

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;

public class CompListenerTest
{
    static ComponentListener cL = new ComponentAdapter()
    {
        @Override
        public void componentShown(ComponentEvent e)
        {
            super.componentShown(e);
            System.out.println("componentShown");
        }
    };

    static MouseListener mL = new MouseAdapter() 
    {

        @Override
        public void mousePressed(MouseEvent e)
        {
            super.mousePressed(e);
            JComponent c = (JComponent) e.getSource();
            System.out.println("mousePressed c="+c.isShowing());
        }

    };

    public static void main(String[] args)
    {
        JPanel p = new JPanel();
        p.setPreferredSize(new Dimension(300, 400));
        p.setBackground(Color.GREEN);
        p.addComponentListener(cL);
        p.addMouseListener(mL);

        System.out.println("initial test p="+p.isShowing());
        JPanel contentPane = new JPanel();
        contentPane.setBackground(Color.RED);
        contentPane.add(p);
        JFrame f = new JFrame();
        f.setContentPane(contentPane);
        f.setSize(800, 600);
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setVisible(true);
    }
}

提前致谢。


答案 1

ComponentListener 不起作用的原因是它报告对 visible 属性的更改 - 默认情况下也是如此,即使不是组件层次结构的一部分也是如此。

若要可靠地收到通知,请使用层次结构列表


编辑(思考我对这个问题/答案的知识演变,不确定网络礼仪对这样做有什么看法......如果这是错误的方式,请简单地指导我:-)

首先:主题中提出的问题不一定与实际问题有关(正如Boro在下面评论的那样 - 任何链接到评论的方法?):没有必要保留某种本地标志来决定将getLocationOnScreen发送到组件是否安全,只需询问组件本身即可。学习项目1为自己:-)

第二:提出的问题很有趣。五位专家(包括我自己,自称),五种不同的答案。这引发了我的一些挖掘。

我的假设:组件事件对于通知(首次)显示没有用。我知道 componentShown 是无用的,因为它是一种属性更改组件可见属性的通知(很少更改)。不过,对移动/调整大小的建议有用性感到困惑。

构建用例:充分准备示例中的框架,并使其为以后的演示做好准备,这是提高感知性能的典型方法。我的预测 - 基于我的假设:在准备时间调整大小/移动时解雇,在演出时间没有任何东西(注意:isShowing是我们追求的,那就是后者)。在 OP 的示例中添加一个代码段:

    final JFrame f = new JFrame();
    f.setContentPane(contentPane);
    f.setSize(800, 600);
    //        f.pack(); 

    JFrame controller = new JFrame("opener");
    controller.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    Action open = new AbstractAction("open/hide second") {

        @Override
        public void actionPerformed(ActionEvent e) {
            f.setVisible(!f.isVisible());
        }

    };
    controller.add(new JButton(open));
    controller.pack();
    controller.setVisible(true);

失望:在准备时间没有通知,在展会时间通知,只是根据需要,我的假设似乎是错误的;-)最后的机会:将套装换成一个包...瞧,在准备时间通知,在演出时间没有通知,再次让我高兴。再玩一点:如果组件是可显示的,看起来ConsentEvents就会被触发,这在某些上下文中可能有用,也可能没有用,但如果显示是我们所追求的状态,则不会。这

新的英制规则(草案):
不要使用组件列表器来通知“显示”。这是AWT时代的遗留物。
使用祖先留言者。这似乎是Swing的替代品,“已添加”的通知略有错误,这实际上意味着“显示”
只有当真正对细粒度状态更改感兴趣时才使用 HierarchyListener。


答案 2

我使用了一个祖先Listener并处理了祖先添加事件。


推荐