当前位置: 首页 > 面试题库 >

从JButton显示/隐藏JPopupMenu;FocusListener无法正常工作?

汪玮
2023-03-14
问题内容

我需要一个带有附加的下拉样式菜单的JButton。因此,我采用了JPopupMenu并将其附加到JButton上,就像在下面的代码中看到的那样。它需要做的是:

  • 单击时显示弹出窗口
  • 如果第二次单击则将其隐藏
  • 如果在弹出窗口中选择了一项,则将其隐藏
  • 如果用户单击屏幕上的其他位置,则将其隐藏

这4种方法都可以使用,但是由于我使用的是boolean标志,如果用户单击其他位置或选择了一个项目,则必须在该按钮上再次单击两次才能再次显示它。这就是为什么我尝试添加一个FocusListener(它绝对没有响应)来解决此问题,并在这种情况下将标志设置为false的原因。

编辑:在答案中的最后尝试…

这里是侦听器:(它在扩展JButton的类中,因此第二个侦听器在JButton上。)

// Show popup on left click.
menu.addFocusListener(new FocusListener() {
 @Override
 public void focusLost(FocusEvent e) {
  System.out.println("LOST FOCUS");
  isShowingPopup = false;
 }

 @Override
 public void focusGained(FocusEvent e) {
  System.out.println("GAINED FOCUS");
 }
});

addActionListener(new ActionListener() {
 @Override
 public void actionPerformed(ActionEvent e) {
  System.out.println("isShowingPopup: " + isShowingPopup);
  if (isShowingPopup) {
   isShowingPopup = false;
  } else {
   Component c = (Component) e.getSource();
   menu.show(c, -1, c.getHeight());
   isShowingPopup = true;
  }
 }
});

我已经为此打了太久了。如果有人可以告诉我这是怎么回事,那太好了!

谢谢!

码:

public class Button extends JButton {

    // Icon.
    private static final ImageIcon ARROW_SOUTH = new ImageIcon("ArrowSouth.png");

    // Unit popup menu.
    private final JPopupMenu menu;

    // Is the popup showing or not?
    private boolean isShowingPopup = false;

    public Button(int height) {
        super(ARROW_SOUTH);
        menu = new JPopupMenu(); // menu is populated somewhere else

        // FocusListener on the JPopupMenu
        menu.addFocusListener(new FocusListener() {
            @Override
            public void focusLost(FocusEvent e) {
                System.out.println("LOST FOCUS");
                isShowingPopup = false;
            }

            @Override
            public void focusGained(FocusEvent e) {
                System.out.println("GAINED FOCUS");
            }
        });

        // ComponentListener on the JPopupMenu
        menu.addComponentListener(new ComponentListener() {
            @Override
            public void componentShown(ComponentEvent e) {
                System.out.println("SHOWN");
            }

            @Override
            public void componentResized(ComponentEvent e) {
                System.out.println("RESIZED");
            }

            @Override
            public void componentMoved(ComponentEvent e) {
                System.out.println("MOVED");
            }

            @Override
            public void componentHidden(ComponentEvent e) {
                System.out.println("HIDDEN");
            }
        });

        // ActionListener on the JButton
        addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.out.println("isShowingPopup: " + isShowingPopup);
                if (isShowingPopup) {
                    menu.requestFocus();
                    isShowingPopup = false;
                } else {
                    Component c = (Component) e.getSource();
                    menu.show(c, -1, c.getHeight());
                    isShowingPopup = true;
                }
            }
        });

        // Skip when navigating with TAB.
        setFocusable(true); // Was false first and should be false in the end.

        menu.setFocusable(true);
    }

}

问题答案:

这是另一种方法,即使不是很优雅,也算是不错的,据我所知,它是可行的。首先,在最顶部,我添加了一个名为的第二个布尔值showPopup

FocusListener必须如下:

    menu.addFocusListener(new FocusListener() {
        @Override
        public void focusLost(FocusEvent e) {
            System.out.println("LOST FOCUS");
            isShowingPopup = false;
        }

        @Override
        public void focusGained(FocusEvent e) {
            System.out.println("GAINED FOCUS");
            isShowingPopup = true;
        }
    });

isShowingPopup布尔没有得到改变其他地方-如果它获得焦点,它假定它表示,如果它失去焦点,它假定它不是。

接下来,ActionListener按钮上的有所不同:

   addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            System.out.println("isShowingPopup: " + isShowingPopup);
            if (showPopup) {
                Component c = (Component) e.getSource();
                menu.show(c, -1, c.getHeight());
                menu.requestFocus();
            } else {
                showPopup = true;
            }
        }
    });

现在出现了真正的新东西。这是一个MouseListener按钮:

    addMouseListener(new MouseAdapter() {
        @Override
        public void mousePressed(MouseEvent e) {
            System.out.println("ispopup?: " + isShowingPopup);
            if (isShowingPopup) {
                showPopup = false;
            }
        }

        @Override
        public void mouseReleased(MouseEvent e) {
            showPopup = true;
        }
    });

基本上,mousePressed在菜单失去焦点之前被调用,因此isShowingPopup反映了是否在按下按钮之前显示了弹出窗口。然后,如果菜单在那里,我们将其设置showPopupfalse,这样该actionPerformed方法在调用菜单后(放开鼠标后)就不会显示菜单。

在每种情况下,它的行为均符合预期,但只有一种:如果显示菜单,并且用户在按钮上按下鼠标但将其释放到按钮外,actionPerformed则永远不会调用。这意味着它showPopup仍然为假,并且下次按下该按钮时不会显示菜单。要解决此问题,mouseReleased方法将重置showPopup。据我所知,该mouseReleased方法在after之后被调用actionPerformed

我在结果按钮上玩了一点,对按钮做了所有我想得到的事情,并且按预期工作。但是,我不是100%肯定事件将始终以相同的顺序发生。

最终,我认为这至少值得一试。



 类似资料:
  • 在我的Swing应用程序中,我有2个JFrameA和B。当我单击JFrameA上的按钮时,它会打开JFrameB并隐藏它自己(我设法完成了这部分) 在JFrame B上,我在JTabbedPane上放置了4个JPanels。每个JPanel有2个JButtons。 我该怎么做? //JPanel类 公共类AddItemPanel扩展javax.swing.jPanel{

  • 主要内容:实例,jQuery hide() 和 show(),实例,实例,实例,jQuery toggle(),实例隐藏、显示、切换,滑动,淡入淡出,以及动画,哇哦! 因为时间是宝贵的,我们提供快捷方便的学习方法。 在小牛知识库,你可以学习需要的知识。 实例 jQuery hide() 简单的jQuery hide()方法演示。 jQuery hide() 另一个hide()实例。演示如何隐藏文本。 jQuery hide() 和 show() 通过 jQuery,您可以使用 hide() 和

  • 排除不显示字段 Model.findAll({ attributes: { exclude: ['baz'] } });

  • 提供显示/隐藏元素的功能。 标题 内容 类型 通用 支持布局 responsive,fixed-height,fill,container,fixed 所需脚本 https://c.mipcdn.com/static/v2/mip-toggle/mip-toggle.js 示例 基本使用 你可以使用事件 toggle, show 或 hide 以控制 mip-toggle 组件的显示与隐藏。 <b

  • 我正在为我的android乞丐项目创建一个1对1扑克芯片计数器应用程序。当我按下任何调用displayBetPlayer1或displayBetPlayer2的按钮(+、-、Bet/Rise)时,我会收到一个运行时错误,所以我知道问题出在这些方法上。我还看到导入语句有一些不对劲的地方,但我对此太陌生,不明白是什么。有人知道问题出在哪里吗?(我将在注释中发布activity_main.xml,因为它

  • 我正在尝试将约束移到底部。UI视图的常量,其中我的UITextField显示后位于键盘上方。我设置了通知观察器,但由于某种原因,它不起作用。 当我打印