下面是一个完整的编译,运行失败的例子,说明我的问题。JMenuItem扩展了JComponent。当添加到JPopupMenu并显示在上下文菜单中时.它是..。好吧..。显示,但不调用componentShown方法。我如何知道何时显示JMenuItem?我需要从JMenuItem内部知道。我正在创建这个JMenuItem并将其交给一个更大的框架。我不了解或控制JPopupMenu,容器,或任何其他组件。当显示我的JMenuItem时,我必须根据应用程序的上下文和当前状态更新它的文本。我怎么知道是什么时候展示的?
在下面的示例中,文本“显示的组件”在任何情况下都不会被打印。在JPanel中右键单击获取上下文菜单,您将看到JMenuItem文本“应答Hi",但现在输出到控制台。
我正在运行macOS 11.5.2BigSur和JDK11.0.6LTS(来自甲骨文)。
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
public class JMenuItemListeners {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.setMinimumSize(new Dimension(800, 600));
panel.setLayout(new BorderLayout());
panel.add(new JLabel("Hello World... right click me."),
BorderLayout.CENTER);
//========================================
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Reply Hi");
menuItem.addComponentListener(
new ComponentListener() {
@Override
public void componentResized(ComponentEvent e) {}
@Override
public void componentMoved(ComponentEvent e) {}
@Override
public void componentShown(ComponentEvent e) {
System.out.println("component shown");
}
@Override
public void componentHidden(ComponentEvent e) {}
}
);
popupMenu.add(menuItem);
panel.setComponentPopupMenu(popupMenu);
//========================================
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}发布于 2021-09-11 19:47:24
您可以使用AncestorListener
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;
public class JMenuItemListeners {
public static void main(String[] args) {
JFrame frame = new JFrame();
JPanel panel = new JPanel();
frame.setMinimumSize(new Dimension(800, 600));
panel.setLayout(new BorderLayout());
panel.add(new JLabel("Hello World... right click me."),
BorderLayout.CENTER);
//========================================
JPopupMenu popupMenu = new JPopupMenu();
JMenuItem menuItem = new JMenuItem("Reply Hi");
menuItem.addAncestorListener(new AncestorListener()
{
@Override
public void ancestorRemoved(AncestorEvent e) {}
@Override
public void ancestorMoved(AncestorEvent e) {}
@Override
public void ancestorAdded(AncestorEvent e) {
System.out.println("ancestor shown");
}
});
popupMenu.add(menuItem);
panel.setComponentPopupMenu(popupMenu);
//========================================
frame.setContentPane(panel);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
}发布于 2021-09-11 19:44:04
我认为您不会在显示JMenuItem时找到某种通知的侦听器。
相反,我将尝试将JMenuItem与应用程序的状态分离开来,我将使用javax.swing.AbstractAction来实现这一点。
您可以随时更新应用程序的上下文和/或状态,并在显示AbstractAction时神奇地显示它将反映应用程序的上下文和状态。
下面的代码片段替换了JPopupMenu和JMenuItem的创建。第二部分展示了如何通过将AbstractAction转换为时钟来更新JMenuItem。
//========================================
JPopupMenu popupMenu = new JPopupMenu();
AbstractAction a = new AbstractAction("Reply Hi") {
@Override
public void actionPerformed(ActionEvent e) {
System.out.println("Hi");
}
};
JMenuItem menuItem = new JMenuItem(a);
popupMenu.add(menuItem);
panel.setComponentPopupMenu(popupMenu);
//========================================
Timer t = new Timer(100, (e) -> {
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("'Its 'HH:mm:ss");
a.putValue(Action.NAME, dtf.format(LocalTime.now()));
});
t.start();
//========================================https://stackoverflow.com/questions/69144597
复制相似问题