JMenuBar 禁用后无法启用

问题描述 投票:0回答:2

我在显示

JMenuBar
之前禁用
FileDialog
(因为当
FileDialog
可见时,菜单项仍然处于活动状态)使用
getJMenuBar().setEnabled(false)
,然后在
getJMenuBar().setEnabled(true)
关闭后调用
FileDialog
,但是菜单项在启用后不会变为活动状态 - 如果我更改为另一个应用程序并返回到我的应用程序,它们就会变为活动状态。我尝试致电
getJMenuBar().revalidate()
和/或
getJMenuBar().repaint()
但无济于事。

值得注意的是,我使用的是屏幕菜单栏,就像在 OS X 上一样。显示问题的示例代码:

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();
    }

}

预先感谢您的意见/建议!

java swing jmenubar
2个回答
2
投票

对我来说,我可以通过启用/禁用每个

JMenuItem
而不是菜单栏或菜单本身来解决问题。

我也在 EDT 上做了所有事情,以防万一这就是问题所在,但没有帮助。

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[] arguements) {
        System.setProperty("apple.laf.useScreenMenuBar", "true");
        EventQueue.invokeLater(()->{
            new MenuTest().buildGui();
                });
    }

}

0
投票

我可以确认 Matt 的答案在 macOS 上对我有用。但有些事情他没有提到,我会的,希望能节省一些时间。

事情1

我尝试仅禁用

JMenu
中的
JMenuBar
组件,这样我就只需编写一个
for
循环。我得到了与尝试暂时禁用
JMenuBar
时相同的行为。

        JMenuBar b = getJMenuBar();
        for (int i=0; i<b.getMenuCount(); i++)
            b.getMenu(i).setEnabled(false); // then true later

事情2

仅暂时禁用

JMenuBar
,如果我执行以下操作之一,菜单项将再次工作:

  1. 先关注另一个应用程序,然后再关注此应用程序
  2. 使该应用程序以任何方式在事件调度线程上进行交互

事情3

如果事先已经禁用了

JMenuItem
,您不希望盲目禁用然后再启用它。

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();
}

事情4

并非

JMenuItem
中的每个
JMenu
都可以禁用或启用(例如,
JSeparator
组件)。这就是为什么上面的代码涵盖了
JMenuItem
为空的情况。

© www.soinside.com 2019 - 2024. All rights reserved.