You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

JMenuItem的componentShown事件不触发,如何判断其已被显示?

问题原因

componentShown 事件触发的前提是组件自身的visible属性从false变为true,而JPopupMenu中的JMenuItem默认visible属性始终为true,只是所属的JPopupMenu父容器的可见性变化,因此不会触发ComponentListener的对应回调。

解决方案

你可以直接在自定义JMenuItem内部注册以下两种监听器实现需求,不需要感知上层父容器、所属JPopupMenu的任何逻辑,符合交付给上层框架使用的场景:

方案1:使用AncestorListener监听祖先组件可见性变化

这是Swing专门针对该类场景提供的轻量监听器,实现成本最低:

import javax.swing.event.AncestorEvent;
import javax.swing.event.AncestorListener;

// 替换你原来的ComponentListener注册逻辑
menuItem.addAncestorListener(new AncestorListener() {
    @Override
    public void ancestorAdded(AncestorEvent event) {
        // 菜单项随所属弹窗显示时触发
        System.out.println("component shown");
        // 这里写你更新菜单项文本的逻辑即可
        menuItem.setText("动态更新文本:" + System.currentTimeMillis());
    }

    @Override
    public void ancestorRemoved(AncestorEvent event) {
        // 菜单项随所属弹窗隐藏时触发,不需要监听隐藏状态可留空
        System.out.println("component hidden");
    }

    @Override
    public void ancestorMoved(AncestorEvent event) {}
});

方案2:使用HierarchyListener监听层级显示状态变化

如果需要更底层的监听能力,也可以用层级事件监听实现:

import java.awt.event.HierarchyEvent;

menuItem.addHierarchyListener(e -> {
    if ((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) {
        if (menuItem.isShowing()) {
            System.out.println("component shown");
            // 更新文本逻辑
        } else {
            System.out.println("component hidden");
        }
    }
});

以上两种方案在你描述的macOS 11.5.2 + JDK 11.0.6环境下均可以正常触发,右键唤起弹窗时会输出对应日志,可直接集成到自定义JMenuItem的内部逻辑中。

内容的提问来源于stack exchange,提问作者Jason

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 08:09:02