以编程方式扩展子JMenuItems

时间:2014-08-12 09:24:22

标签: java swing jmenu jmenuitem jpopupmenu

我想以编程方式在JPopup中扩展特定的JMenuItem。例如,在下面的代码中

import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;

public class AutoExpandSubMenusDemo extends JFrame {

    private final JPopupMenu popup = new JPopupMenu("Popup");

    public AutoExpandSubMenusDemo() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        JMenu menuB = new JMenu("B");

        menuB.add(new JMenuItem("X"));
        JMenuItem menuY = menuB.add(new JMenuItem("Y"));
        menuB.add(new JMenuItem("Z"));

        popup.add(new JMenuItem("A"));
        popup.add(menuB);
        popup.add(new JMenuItem("C"));

        final JButton button = new JButton("Show Popup Menu");
        button.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                popup.show(button, 0, button.getHeight());

                // Show menuY
            }
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(button);
        getContentPane().add(buttonPanel);
    }

    public static void main(String[] args) {
        AutoExpandSubMenusDemo f = new AutoExpandSubMenusDemo();
        f.setSize(500, 300);
        f.setVisible(true);
    }
}

我想展开弹出菜单,以便在按下按钮时展开和选择项目B(menuB)/ Y(menuY)。

很抱歉,如果这很容易做到,但我已经四处搜索,无法弄明白。

我确实找到了

MenuSelectionManager.defaultManager().setSelectedPath(...)

然而,当我尝试它并且javadoc指定从LaF调用它并且不应该被客户端调用时,这不起作用。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:5)

虽然我不建议这样做,但由于文档本身提出反对意见,所以您可以采取以下措施:

import java.awt.event.ActionEvent;
import javax.swing.AbstractAction;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.MenuElement;
import javax.swing.MenuSelectionManager;
import javax.swing.SwingUtilities;

public class AutoExpandSubMenusDemo extends JFrame {

    private final JPopupMenu popup = new JPopupMenu("Popup");

    public AutoExpandSubMenusDemo() {
        setDefaultCloseOperation(EXIT_ON_CLOSE);

        final JMenu menuB = new JMenu("B");

        menuB.add(new JMenuItem("X"));
        final JMenuItem menuY = menuB.add(new JMenuItem("Y"));
        menuB.add(new JMenuItem("Z"));

        popup.add(new JMenuItem("A"));
        popup.add(menuB);
        popup.add(new JMenuItem("C"));

        final JButton button = new JButton("Show Popup Menu");
        button.addActionListener(new AbstractAction() {
            @Override
            public void actionPerformed(ActionEvent e) {
                popup.show(button, 0, button.getHeight());

                SwingUtilities.invokeLater(new Runnable() {

                    public void run() {
                        menuB.setPopupMenuVisible(true);
                        MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{popup, menuB, menuY});
                    }
                });

            }
        });

        JPanel buttonPanel = new JPanel();
        buttonPanel.add(button);
        getContentPane().add(buttonPanel);
    }

    public static void main(String[] args) {
        AutoExpandSubMenusDemo f = new AutoExpandSubMenusDemo();
        f.setSize(500, 300);
        f.setVisible(true);
    }
}

这些代码大部分都是你的。我只补充说:

SwingUtilities.invokeLater(new Runnable() {

    public void run() {
        menuB.setPopupMenuVisible(true);
        MenuSelectionManager.defaultManager().setSelectedPath(new MenuElement[]{popup, menuB, menuY});
    }
});

似乎有用。

您可以避免通过' MenuItem.setArmed(布尔)'来滥用MenuSelectionManager

SwingUtilities.invokeLater(new Runnable() {

    public void run() {
        menuB.setPopupMenuVisible(true);
        menuB.setArmed(true);
        menuY.setArmed(true);
    }
});

在选择另一个菜单项或忽略JPopupMenu之后,弹出窗口仍然可见,但仍然需要解决。

另一种方法是假冒鼠标事件......:D

SwingUtilities.invokeLater(new Runnable() {

    public void run() {                        
        MouseEvent event = new MouseEvent(
                menuB, MouseEvent.MOUSE_ENTERED, 0, 0, 0, 0, 0, false);
        menuB.dispatchEvent(event);
        menuY.setArmed(true);
    }
});

这样就好像用户实际使用了鼠标一样。

答案 1 :(得分:2)

另一个例子:

MenuSelectionManager.defaultManager().setSelectedPath(
    new MenuElement[] {popup, menuB, menuB.getPopupMenu()});

enter image description here

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;

public class AutoExpandSubMenusDemo2 extends JFrame {
  private final JPopupMenu popup = new JPopupMenu("Popup");

  public AutoExpandSubMenusDemo2() {
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    final JMenu menuB = new JMenu("B");

    menuB.add(new JMenuItem("X"));
    final JMenuItem menuY = menuB.add(new JMenuItem("Y"));
    menuB.add(new JMenuItem("Z"));

    popup.add(new JMenuItem("A"));
    popup.add(menuB);
    popup.add(new JMenuItem("C"));

    JPanel buttonPanel = new JPanel();
    buttonPanel.add(new JButton(new AbstractAction("Show menuB Popup") {
      @Override public void actionPerformed(ActionEvent e) {
        JButton button = (JButton) e.getSource();
        popup.show(button, 0, button.getHeight());
        //[Bug ID: JDK-6949414 JMenu.buildMenuElementArray() endless loop]
        //( http://bugs.java.com/bugdatabase/view_bug.do?bug_id=6949414 )
        //menuB.doClick();
        MenuSelectionManager.defaultManager().setSelectedPath(
          new MenuElement[] {popup, menuB, menuB.getPopupMenu()});
      }
    }));
    buttonPanel.add(new JButton(new AbstractAction("Select menuY") {
      @Override public void actionPerformed(ActionEvent e) {
        JButton button = (JButton) e.getSource();
        popup.show(button, 0, button.getHeight());
        MenuSelectionManager.defaultManager().setSelectedPath(
          new MenuElement[] {popup, menuB, menuB.getPopupMenu(), menuY});
      }
    }));
    getContentPane().add(buttonPanel);
  }

  public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
      @Override public void run() {
        createAndShowGUI();
      }
    });
  }
  public static void createAndShowGUI() {
    JFrame f = new AutoExpandSubMenusDemo2();
    f.setSize(500, 300);
    f.setVisible(true);
  }
}