gpt4 book ai didi

java - JMenuBar SelectionModel ChangeListener 只触发一次

转载 作者:行者123 更新时间:2023-11-30 06:23:44 25 4
gpt4 key购买 nike

我正在尝试让我的 JMenuBar 模拟 Firefox 和 iTunes 的菜单栏的行为。行为:菜单栏最初是隐藏的。但是,当您按下 Alt 时,菜单栏会出现(第一个项目被选中),而当您没有选择任何菜单项时,菜单栏就会消失。我的想法是通过 SelectionModel 上的 ChangeListener 来监听 JMenuBar 的选择更改。

但是,附加的行为 SSCCE不尽如人意。当框架加载时,JMenuBar 不可见。当您按下 Alt 时,菜单栏会出现并选中第一个菜单(感谢 WindowsLookAndFeel)。但是,随后每次按下 Alt 时都不会触发 ChangeEvents。我不明白为什么...

有人有光要散发吗?

public class MenuBarTest extends javax.swing.JFrame {

public MenuBarTest() {
initComponents();
jMenuBar1.setVisible(false);
jMenuBar1.getSelectionModel().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
System.out.println(e.toString());
jMenuBar1.setVisible(jMenuBar1.isSelected());
System.out.println(jMenuBar1.isSelected());
System.out.println(jMenuBar1.getSelectionModel().isSelected());
}
});
}

private void initComponents() {

jMenuBar1 = new javax.swing.JMenuBar();
jMenu1 = new javax.swing.JMenu();
jMenuItem1 = new javax.swing.JMenuItem();
jMenu2 = new javax.swing.JMenu();
jMenuItem2 = new javax.swing.JMenuItem();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

jMenu1.setText("File");
jMenuItem1.setText("jMenuItem1");
jMenu1.add(jMenuItem1);
jMenuBar1.add(jMenu1);
jMenu2.setText("Edit");
jMenuItem2.setText("jMenuItem2");
jMenu2.add(jMenuItem2);
jMenuBar1.add(jMenu2);
setJMenuBar(jMenuBar1);
javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 400, Short.MAX_VALUE));
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGap(0, 279, Short.MAX_VALUE));

pack();
}

public static void main(String args[]) {
try {
UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | javax.swing.UnsupportedLookAndFeelException ex) {
ex.printStackTrace();
}
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new NewClass().setVisible(true);
}
});
}
private javax.swing.JMenu jMenu1;
private javax.swing.JMenu jMenu2;
private javax.swing.JMenuBar jMenuBar1;
private javax.swing.JMenuItem jMenuItem1;
private javax.swing.JMenuItem jMenuItem2;
}

最佳答案

看起来菜单栏一旦被选中就永远不会被取消选中。不确定这是否是错误。

直接监听 MenuSelectionManager 可能是一个更好的主意,因为您会在任何地方收到有关菜单选择的所有更改的通知。需要一些逻辑来过滤掉那些与 menuBar 无关的东西,类似于:

ChangeListener listener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
MenuElement[] elements = MenuSelectionManager.defaultManager().getSelectedPath();
jMenuBar1.setVisible(elements.length > 0 && elements[0] == jMenuBar1);
}
};
MenuSelectionManager.defaultManager().addChangeListener(listener);

更新

隐藏菜单栏的一个严重缺点是其菜单项的加速器停止工作。原因是只有正在显示的组件的 componentInputMaps 被要求处理它们。这是在 swing 包的内部深处完成的,即由包私有(private)类 KeyboardManager 完成的。无法挂接自定义管理器(可以实现它来处理未显示的菜单栏)。

不过,在链条的另一端,我们可以进行干预。基本上有两个选项,都是菜单栏的子类:

  • (非常肮脏的把戏!)覆盖 isShowing 以始终返回 true。我已经看到这样做了,但不能真正推荐,因为可能有我不知道的副作用
  • 一个有点肮脏的技巧:添加一个属性 hidden 并实现 getPreferredSize 以在隐藏时返回 0 高度。肮脏之处在于它依赖于 RootPaneLayout 尊重 pref 高度 ...

修改后的 ChangeListener:

bar.setHidden(true);
ChangeListener listener = new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
MenuElement[] elements = MenuSelectionManager.defaultManager().getSelectedPath();
bar.setHidden(!(elements.length >0 && elements[0] == bar));
}
};
MenuSelectionManager.defaultManager().addChangeListener(listener);

自定义菜单栏:

public static class JHideableMenuBar extends JMenuBar {

private boolean hidden;

public void setHidden(boolean hidden) {
if (this.hidden == hidden) return;
this.hidden = hidden;
revalidate();
}

@Override
public Dimension getPreferredSize() {
Dimension pref = super.getPreferredSize();
if (hidden) {
pref.height = 0;
}
return pref;
}

}

关于java - JMenuBar SelectionModel ChangeListener 只触发一次,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18093773/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com