JPopupMenu操作未触发

时间:2016-04-26 09:44:12

标签: java swing popupmenu

这是我所拥有的(一个siplified版本)。 (我找到了代码的方式):

class CustomPopup extends JPopupMenu {
    public CustomPopup() {}

    @Override
    public void setVisible(boolean visible)
    {
        // Case 1:
        //if (visible) super.setVisible(visible);
        // Case 2:
        super.setVisible(visible);
    }
}

class CustomPanel extends JPanel {
    // .../...
    public CustomPanel() {
        setSize(200, 200);
        addMouseListener( new MouseAdapter(){
            @Override
            public void mousePressed( MouseEvent e ){
                onMousePressed( e );
            }
        });

    }

    public void onMousePressed( MouseEvent e )
    {
        JPopupMenu pop = new JPopupMenu();

        pop.add( new AbstractAction( "foo" )
        {
            @Override
            public void actionPerformed( ActionEvent e )
            {
                // do stuff
                System.out.println("this is executed");
            }
        });
        pop.show( e.getComponent(), e.getX(), e.getY() );
    }
}

public class TestPopup extends JFrame {
    CustomPanel _pp;
    CustomPopup _cpop;

    public TestPopup () {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(333, 333);
        _cpop = new CustomPopup();
        _pp = new CustomPanel();
        _cpop.add(_pp);

        addMouseListener( new MouseAdapter(){
            @Override
            public void mousePressed( MouseEvent e ){
                _cpop.show(e.getComponent(), 0, 0);
            }
        });
    }
    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                (new TestPopup()).setVisible(true);
            }
        });
    }
}

弹出菜单显示自定义面板。与它交互时,它会显示一个带有选项列表的经典弹出菜单。

我的问题是CustomPopup并没有按照自己的意愿关闭。罪魁祸首显然是setVisible的覆盖,但是如果我删除覆盖方法(或注释掉条件)我还有另一个问题:actionPerformed上添加的pop方法永远不会被调用。

在第一种情况下:

  1. CustomPopup打开
  2. 我点击其中的内容
  3. JPopupMenu打开CustomPopup仍然可见
  4. 我点击新菜单的项目
  5. 触发Action
  6. 在第二种情况下:

    1. CustomPopup打开
    2. 我点击其中的内容
    3. JPopupMenu打开,隐藏CustomPopup
    4. 我点击新菜单的项目
    5. Action 已触发
    6. 我的结论是CustomPopup必须能够触发动作,即使我不明白为什么。所以我的问题是:如何以不会违反默认CustomPopup行为的方式保持JPopupMenu开放,或者如何在隐藏CustomPopup的情况下正确触发操作?

1 个答案:

答案 0 :(得分:2)

它看起来弹出窗口的父母必须是可见的动作触发(对我来说听起来似乎合情合理)。所以除了最后一步之外,你让所有人都能使它工作:自己关闭自定义弹出窗口。这是代码:

class CustomPopup extends JPopupMenu {
    public CustomPopup() {}

    @Override
    public void setVisible(boolean visible)
    {
        // Case 1:
        if (visible) super.setVisible(visible);
        // Case 2:
//        super.setVisible(visible);
    }
    public void makeInvisible() {
        super.setVisible(false);
    }
}

class CustomPanel extends JPanel {
    // .../...
    public CustomPanel() {
        setSize(200, 200);
        addMouseListener( new MouseAdapter(){
            @Override
            public void mousePressed( MouseEvent e ){
                onMousePressed( e );
            }
        });

    }

    public void onMousePressed( MouseEvent e )
    {
        JPopupMenu pop = new JPopupMenu();

        pop.add( new AbstractAction( "foo" )
        {
            @Override
            public void actionPerformed( ActionEvent e )
            {
                // do stuff
                System.out.println("this is executed");
                Component comp = (Component) e.getSource();
                if (comp != null && comp.getParent() instanceof JPopupMenu) {
                    JPopupMenu popupMenu = (JPopupMenu) comp.getParent();
                    if (popupMenu.getInvoker() instanceof CustomPanel) {
                        CustomPopup cpop = (CustomPopup) popupMenu.getInvoker().getParent();
                        cpop.makeInvisible();
                    }
                }
            }
        });
        pop.show( e.getComponent(), e.getX(), e.getY() );
    }
}

public class TestPopup extends JFrame {
    CustomPanel _pp;
    CustomPopup _cpop;

    public TestPopup () {
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(333, 333);
        _cpop = new CustomPopup();
        _pp = new CustomPanel();
        _cpop.add(_pp);

        addMouseListener( new MouseAdapter(){
            @Override
            public void mousePressed( MouseEvent e ){
                _cpop.show(e.getComponent(), e.getX(), e.getY());
            }
        });
    }
    public static void main(String[] args) {
        java.awt.EventQueue.invokeLater(new Runnable() {
            public void run() {
                (new TestPopup()).setVisible(true);
            }
        });
    }
}