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
相关产品推荐
相关产品推荐

