我想让我的JMenuBar
模拟Firefox和iTunes菜单栏的行为。行为:菜单栏最初是隐藏的。但是,当您按Alt
时,会出现菜单栏(选择第一项),当您没有选择菜单项时,菜单栏会消失。我的想法是通过JMenuBar
上的ChangeListener
来监听SelectionModel
的选择更改。
但是,附加的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;
}
答案 0 :(得分:3)
看起来菜鸟从未被选中,一旦被选中。不确定这是不是一个错误。
直接收听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);
<强>更新强>
隐藏菜单栏的一个巨大缺点是它的menuItems的加速器停止工作。原因是只要求显示的组件的componentInputMaps来处理它们。这是在swing包的内部深处完成的,即由包私有类KeyboardManager完成。无法挂钩自定义管理器(可能实现处理未显示的菜单栏)。
在链的另一端,我们可以干涉。基本上有两个选项,都是子菜单menubar:
修订后的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);
自定义menuBar:
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;
}
}
答案 1 :(得分:2)
然而,每次后续的Alt按下都不会触发ChangeEvents。我不能 找出原因......
来自SelectionModel,Mouse或Key事件的ChangeListener触发事件,这些事件是预期的
您可以从ChangeListener模拟事件,例如菜单上的重置选择(将其放在将焦点移动到JTextField上)
可以访问另一个侦听器,即正确触发自己的事件
见
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.swing.ButtonModel;
import javax.swing.JTextField;
import javax.swing.UIManager;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
public class MenuBarTest extends javax.swing.JFrame {
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;
private JTextField text = new JTextField("text", 10);
public MenuBarTest() {
jMenuBar1 = new javax.swing.JMenuBar();
jMenu1 = new javax.swing.JMenu();
jMenu1.addMenuListener(new MenuListener() {
@Override
public void menuSelected(MenuEvent e) {
System.out.println("MenuListener - Selected: " + e.toString());
}
@Override
public void menuDeselected(MenuEvent e) {
System.out.println("MenuListener - Deselected: " + e.toString());
}
@Override
public void menuCanceled(MenuEvent e) {
System.out.println("MenuListener - Canceled: " + e.toString());
}
});
jMenu1.getModel().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
ButtonModel model = (ButtonModel) e.getSource();
if (model.isArmed()) {
System.out.println("ButtonModel - Armed: " + e.toString());
} else if (model.isEnabled()) {
System.out.println("ButtonModel - Enabled: " + e.toString());
} else if (model.isPressed()) {
System.out.println("ButtonModel - Pressed: " + e.toString());
} else if (model.isRollover()) {
System.out.println("ButtonModel - Rollover: " + e.toString());
} else if (model.isSelected()) {
System.out.println("ButtonModel - Selected: " + e.toString());
} else {
System.out.println("ButtonModel - !!!!!????: " + e.toString());
}
}
});
jMenuItem1 = new javax.swing.JMenuItem();
jMenu2 = new javax.swing.JMenu();
jMenuItem2 = new javax.swing.JMenuItem();
jMenu1.setText("File");
jMenuItem1.setText("jMenuItem1");
jMenu1.add(jMenuItem1);
jMenuBar1.add(jMenu1);
jMenu2.setText("Edit");
jMenuItem2.setText("jMenuItem2");
jMenu2.add(jMenuItem2);
jMenuBar1.add(jMenu2);
jMenuBar1.setVisible(false);
jMenuBar1.addPropertyChangeListener(new PropertyChangeListener() {
@Override
public void propertyChange(PropertyChangeEvent evt) {
String strPropertyName = evt.getPropertyName();
System.out.println("PropertyChangeListener - NewValue: " + evt.getNewValue());
System.out.println("PropertyChangeListener - OldValue: " + evt.getOldValue());
System.out.println("PropertyChangeListener - PropagationId: " + evt.getPropagationId());
System.out.println("PropertyChangeListener - PropertyName: " + evt.getPropertyName());
if ("MENU.MP_BARBACKGROUND".equals(strPropertyName)) {
System.out.println("PropertyChangeListener - MENU.MP_BARBACKGROUND: " + evt.getNewValue());
}
}
});
jMenuBar1.getSelectionModel().addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
System.out.println("ChangeListener - " + e.toString());
jMenuBar1.setVisible(jMenuBar1.isSelected());
System.out.println("ChangeListener - " + jMenuBar1.isSelected());
System.out.println("ChangeListener - " + jMenuBar1.getSelectionModel().isSelected());
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
text.grabFocus();
text.requestFocusInWindow();
text.setText(text.getText());
text.selectAll();
}
});
}
});
setJMenuBar(jMenuBar1);
add(text, BorderLayout.NORTH);
add(new JTextField("text", 10), BorderLayout.SOUTH);
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setPreferredSize(new Dimension(400, 300));
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() {
@Override
public void run() {
new MenuBarTest().setVisible(true);
}
});
}
}