首次显示组件时监听

Bor*_*oro 13 java swing listener

我试图抓住屏幕上显示组件的第一时刻,而不使用"脏"解决方案,就像使用计时器一样.基本上,我想知道我可以安全地开始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);
    }
}
Run Code Online (Sandbox Code Playgroud)

提前致谢.

kle*_*tra 15

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

要可靠地通知,请使用HierarchyListener


编辑(关于这个问题/答案的关于我的知识演变的思考,不确定礼仪有关做什么的说法......如果这是错误的方式去指导我:-)

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

第二:问的问题非常有趣.五位专家(包括我自己,自称),五个不同的答案.这引发了我的一些挖掘.

我的假设:ComponentEvents对于(first-)显示的通知没有用.我知道componentShown是无用的,因为它是一种propertyChange通知组件的可见属性(很少改变).但是,对于移动/调整大小的建议用途感到困惑.

构建用例:在示例中完全准备框架并为以后显示做好准备,这是提高感知性能的典型方法.我的预测 - 基于我的假设:在准备时调整大小/移动,在显示时没有任何东西(注意: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);
Run Code Online (Sandbox Code Playgroud)

失望:在准备时没有通知,在展会时间通知,只是在需要时,我的假设似乎错了;-)最后一次机会:交换setSize一包......瞧,准备时通知,没有通知演出时间,再次开心我.播放更多:如果一个组件是可显示的,看起来会触发ComponentEvents,这在某些情况下可能有用,也可能没有用,但如果显示的是我们所处的状态则不会.该

新的帝国规则(草案):
不要使用ComponentListener来通知"显示".这是从AWT时代遗留下来的.
请使用AncestorListener.这似乎是Swing替换,有点误导的"添加"通知实际上意味着"显示"
只有在真正对细粒度状态变化感兴趣时才使用HierarchyListener


cam*_*ckr 6

我已经使用了AncestorListener并处理了ancestorAdded事件.