感谢@mKorbel 推动我在此过程中尝试编写 SSCCE cos,我找到了解决方案。无论如何,这是我的 SSCCE,它可能对其他人有用。谁知道?只需复制并运行即可查看其工作原理。
(注意:代码不是很短,因为我打算在此之后提出次要问题)
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import java.util.ArrayList;
import java.util.Arrays;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.event.PopupMenuEvent;
import javax.swing.event.PopupMenuListener;
public class CustomPopup extends JPopupMenu
{
private JMenuItem menuItem1 = new JMenuItem("One");
private JMenuItem menuItem2 = new JMenuItem("Two");
private JMenuItem menuItem3 = new JMenuItem("Three");
private JMenuItem menuItem4 = new JMenuItem("Four");
private JMenuItem menuItem5 = new JMenuItem("Five");
public CustomPopup()
{
this.add(menuItem1);
this.add(menuItem2);
this.add(menuItem3);
this.add(menuItem4);
this.add(menuItem5);
addListeners(this);
}
private void addListeners(final JPopupMenu popup /*, final String someLetter*/)
{
popup.addPopupMenuListener(new PopupMenuListener(){
@Override
public void popupMenuWillBecomeVisible(PopupMenuEvent evt)
{
JMenuItem menuItem = (JMenuItem)popup.getComponent(3);
String[] letters = {"A", "B", "C", "D"};
ArrayList<String> lettersList = new ArrayList<String>();
lettersList.addAll(Arrays.asList(letters));
String someLetter = getRandomAlphabet();
if(lettersList.contains(someLetter)){
menuItem.setEnabled(true);
}
else{
menuItem.setEnabled(false);
}
}
@Override
public void popupMenuWillBecomeInvisible(PopupMenuEvent evt){
// No Override
}
@Override
public void popupMenuCanceled(PopupMenuEvent evt){
// No Override
}
});
}
private String getRandomAlphabet()
{
String alpha = "";
String Alphas[] = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J"};
double bigNum = Math.random() * 1000000;
String str = String.valueOf(bigNum);
int idx = Integer.valueOf(String.valueOf(str.charAt(str.length() - 1)));
if(idx < 6)
{
alpha = Alphas[idx];
}
else
{
alpha = Alphas[idx - 5];
}
return alpha;
}
public static void main(String[] args)
{
/*try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InstantiationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedLookAndFeelException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
JPanel panel = new JPanel();
JPopupMenu popupMenu = new CustomPopup();
panel.setComponentPopupMenu(popupMenu);
panel.setLayout(new GridBagLayout());
/*JButton button = new JButton("Action");
button.setSize(new Dimension(60, 20));
button.addActionListener(new ActionListener(){
@Override
public void actionPerformed(ActionEvent e)
{
JOptionPane.showMessageDialog(null, "Button was clicked");
}
});
panel.add(button);*/
JFrame frame = new JFrame("popupTest");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(new Dimension(200, 200));
frame.add(panel);
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
}
问题:现在这可以满足我的要求(即menuItem4
根据某些指定计算的随机结果动态启用和禁用getRandomAlphabet()
),我查看了@Guillaume Polet 的 Lovely 实现并对其进行了测试。UIManager
非常好......所以我决定添加一个按钮并测试我在使用不是本机 Java 默认值时遇到的最烦人的问题之一......同样的事情发生了!
我是什么意思?当 LnF 不是默认值Metal
时,在显示 popupMenu 后在任何其他 Actionable 组件上单击 popupMenu 外部在第一次单击时不起作用(这只会将弹出窗口设置为不可见)。然后您必须再次(第二次)单击该组件,然后才能触发其 Action... 很烦人不是吗?
要了解这种情况,只需取消注释UIManager
上面的代码部分(我从@Guillaume Polet 的漂亮解决方案中获取)并取消注释Button
我添加的部分,然后运行程序并查看当您尝试单击时会发生什么显示后立即按钮popupMenu
。有趣的是,在使用 Java 的默认 Metal LnF 时不会出现这个问题
我已经在 Windows 7 上使用系统默认外观解决了这个问题,但无济于事,所以我决定让睡狗撒谎......但老实说,我认为有一个解决这个问题......我知道一定有人对这个东西有破解......代码块,方向,链接,任何解决这个问题的任何地方都会让我感到非常高兴。谢谢好心人!