Reputation: 347
I'm disabling a JMenuBar
before displaying a FileDialog
(as the menu items are still active when the FileDialog
is visible) using getJMenuBar().setEnabled(false)
and then calling getJMenuBar().setEnabled(true)
after the FileDialog
closes, but the menu items do not become active after being enabled - they will if I change to another application and back to mine. I've tried calling getJMenuBar().revalidate()
and/or getJMenuBar().repaint()
to no avail.
Of note, I'm using a screen menu bar as I'm on OS X. Sample code that shows the problem:
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MenuTest extends JFrame implements ActionListener {
private JMenuItem menuItemNew = new JMenuItem("New");
private JMenuItem menuItemOpen = new JMenuItem("Open");
private JMenuItem menuItemSave = new JMenuItem("Save");
private JMenu menuFile = new JMenu("File");
private JMenuBar menuBar = new JMenuBar();
public MenuTest() {
super("JMenu Test");
setSize(300, 300);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menuItemOpen.addActionListener(this);
menuFile.add(menuItemNew);
menuFile.add(menuItemOpen);
menuFile.add(menuItemSave);
menuBar.add(menuFile);
setJMenuBar(menuBar);
setVisible(true);
}
public void openFile() {
getJMenuBar().setEnabled(false);
FileDialog fd = new FileDialog(this, "Choose a file", FileDialog.LOAD);
fd.setVisible(true);
getJMenuBar().setEnabled(true);
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == menuItemOpen) {
openFile();
}
}
public static void main(String[] arguements) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
new MenuTest();
}
}
Thanks in advance for comments / suggestions!
Upvotes: 5
Views: 718
Reputation: 12347
For me, I could resolve the issue by enabling/disabling each JMenuItem
and not the menu bar or menu itself.
I also did everything on the EDT, just in case that was the problem, but it didn't help.
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class MenuTest implements ActionListener {
private JMenuItem menuItemNew = new JMenuItem("New");
private JMenuItem menuItemOpen = new JMenuItem("Open");
private JMenuItem menuItemSave = new JMenuItem("Save");
private JMenu menuFile = new JMenu("File");
private JMenuBar menuBar = new JMenuBar();
JFrame frame;
public MenuTest() {
}
public void buildGui(){
frame = new JFrame("JMenu Test");
frame.setSize(300, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
menuItemOpen.addActionListener(this);
menuFile.add(menuItemNew);
menuFile.add(menuItemOpen);
menuFile.add(menuItemSave);
menuBar.add(menuFile);
frame.setJMenuBar(menuBar);
frame.setVisible(true);
}
public void openFile() {
menuItemNew.setEnabled(false);
menuItemOpen.setEnabled(false);
menuItemSave.setEnabled(false);
FileDialog fd = new FileDialog(frame, "Choose a file", FileDialog.LOAD);
fd.setVisible(true);
menuItemNew.setEnabled(true);
menuItemOpen.setEnabled(true);
menuItemSave.setEnabled(true);
}
@Override
public void actionPerformed(ActionEvent e) {
openFile();
}
public static void main(String[] arguments) {
System.setProperty("apple.laf.useScreenMenuBar", "true");
EventQueue.invokeLater(()->{
new MenuTest().buildGui();
});
}
}
Upvotes: 2
Reputation: 3190
I can confirm Matt's answer worked for me on macOS. But there are some things he didn't mention that I will, in the hope that it saves someone some time.
I tried disabling only the JMenu
components in the JMenuBar
so that I would have to write only one for
loop. I got the same behavior that I got when I tried to temporarily disable the JMenuBar
.
JMenuBar b = getJMenuBar();
for (int i=0; i<b.getMenuCount(); i++)
b.getMenu(i).setEnabled(false); // then true later
By only temporarily disabling the JMenuBar
, if I do one of the following, the menu items would work again:
You do not want to blindly disable and later enable a JMenuItem
afterward if it was already disabled beforehand.
private ArrayList<JMenuItem> disabledMenuItems = new ArrayList<JMenuItem>();
private void disableAppMenuItems () {
JMenuBar b = getJMenuBar();
for (int i=0; i<b.getMenuCount(); i++) {
JMenu m = b.getMenu(i);
for (int j=0; j<m.getItemCount(); j++) {
JMenuItem mi = m.getItem(j);
if (mi != null && mi.isEnabled()) {
mi.setEnabled(false);
disabledMenuItems.add(mi);
}
}
}
}
private void undoDisableAppMenuItems () {
for (JMenuItem i : disabledMenuItems)
i.setEnabled(true);
disabledMenuItems.clear();
}
Not every JMenuItem
in a JMenu
can be disabled or enabled (e.g., JSeparator
components). That's why the above code covers the case where a JMenuItem
is null.
Upvotes: 1