加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 从JButton显示/隐藏JPopupMenu; FocusListener无法正常

发布时间:2020-12-15 03:06:39 所属栏目:Java 来源:网络整理
导读:我需要一个带有附加下拉样式菜单的JButton.所以我拿了一个JPopupMenu并以你在下面的代码中看到的方式将它附加到JButton.它需要做的是: 单击时显示弹出窗口 如果再次点击,请隐藏它 如果在弹出窗口中选择了某个项目,则将其隐藏 如果用户点击屏幕中的其他位置,
我需要一个带有附加下拉样式菜单的JButton.所以我拿了一个JPopupMenu并以你在下面的代码中看到的方式将它附加到JButton.它需要做的是:

>单击时显示弹出窗口
>如果再次点击,请隐藏它
>如果在弹出窗口中选择了某个项目,则将其隐藏
>如果用户点击屏幕中的其他位置,则隐藏它

这4件事情都有效,但由于我正在使用的布尔标志,如果用户点击其他地方或选择了一个项目,我必须在按钮上单击两次才会再次显示.这就是为什么我试图添加一个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,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,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反映了在按下按钮之前是否显示了弹出窗口.然后,如果菜单在那里,我们只是将showPopup设置为false,这样actionPerformed方法一旦被调用就不显示菜单(在放开鼠标之后).

这种情况在每种情况下都表现如预期但只有一种:如果显示菜单并且用户将鼠标按在按钮上但将其释放到其外部,则从未调用actionPerformed.这意味着showPopup仍为false,下次按下按钮时菜单未显示.要解决此问题,mouseReleased方法会重置showPopup.据我所知,在actionPerformed之后调用mouseReleased方法.

我玩了一下结果按钮,做了我能想到的所有按钮,它按预期工作.但是,我并非100%确定事件将始终以相同的顺序发生.

最终,我认为这至少值得尝试.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读