当前位置: 首页 > 知识库问答 >
问题:

是否有方法检测JPopupMenu中的当前选择(SelectionModel ChangeListener不工作)

云何平
2023-03-14

我想检测JPopupMenu中的选择何时更改。不是在单击菜单项时,而是在选择(武装)菜单项时。用更简单的话,我想检测到这一点:

应该起作用的是将ChangeListener添加到其SelectionModel中,但它似乎不响应选择事件:

public class PopupSelection extends JFrame {
    private static final long serialVersionUID = 363879723515243543L;

    public PopupSelection() {
        super("something");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new FlowLayout());

        JLabel label = new JLabel("right click me");

        JPopupMenu menu = new JPopupMenu();
        menu.getSelectionModel().addChangeListener(System.out::println);

        JMenuItem menuItem1 = new JMenuItem("Item1");
        JMenuItem menuItem2 = new JMenuItem("Item2");
        JMenuItem menuItem3 = new JMenuItem("Item3");
        menu.add(menuItem1);
        menu.add(menuItem2);
        menu.add(menuItem3);

        label.setComponentPopupMenu(menu);

        getContentPane().add(label);
        setSize(400, 400);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new PopupSelection().setVisible(true));
    }
}

我尝试的第二件事是使用PropertyChangeListener,但它也不起作用(不检测此特定事件):

menu.addPropertyChangeListener(System.out::println);

在XY问题的情况下,我的最终目标是在用户使用箭头按钮更改菜单的选择时适当地增加/减少该滚动条:

共有1个答案

鞠凌龙
2023-03-14

在项目的按钮模型上使用更改侦听器。以下是解决方案:

import java.awt.Component;
import java.awt.FlowLayout;
import java.util.stream.Stream;

import javax.swing.AbstractButton;
import javax.swing.ButtonModel;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import javax.swing.SwingUtilities;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

/**
 * <code>PopupSelection</code>.
 */
public class PopupSelection extends JFrame {
    private static final long serialVersionUID = 363879723515243543L;

    public PopupSelection() {
        super("something");
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setLayout(new FlowLayout());

        JLabel label = new JLabel("right click me");

        JPopupMenu menu = new MyPopupMenu();
        menu.getSelectionModel().addChangeListener(System.out::println);

        JMenuItem menuItem1 = new JMenuItem("Item1");
        JMenuItem menuItem2 = new JMenuItem("Item2");
        JMenuItem menuItem3 = new JMenuItem("Item3");
        menu.add(menuItem1);
        menu.add(menuItem2);
        menu.add(menuItem3);

        label.setComponentPopupMenu(menu);

        getContentPane().add(label);
        setSize(400, 400);
        setLocationRelativeTo(null);
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(() -> new PopupSelection().setVisible(true));
    }

    private static class MyPopupMenu extends JPopupMenu {

        private final ChangeListener listener = this::changed;

        @Override
        protected void addImpl(Component comp, Object constraints, int index) {
            super.addImpl(comp, constraints, index);
            if (comp instanceof AbstractButton) {
                ((AbstractButton) comp).getModel().addChangeListener(listener);
            }
        }

        @Override
        public void remove(int index) {
            Component comp = getComponent(index);
            if (comp instanceof AbstractButton) {
                ((AbstractButton) comp).getModel().removeChangeListener(listener);
            }
            super.remove(index);
        }

        private void changed(ChangeEvent e) {
            ButtonModel model = (ButtonModel) e.getSource();
            AbstractButton selected = Stream.of(getComponents()).filter(AbstractButton.class::isInstance)
                    .map(AbstractButton.class::cast)
                    .filter(b -> b.getModel().isArmed() && b.getModel() == model).findAny().orElse(null);
            setSelected(selected);
        }
    }
}
 类似资料:
  • 我的应用程序需要知道用户选择的基本音频路径的能力。在iOS上,这是微不足道的,因为你只需注册一个回调,你就知道音频的确切去向。 在Android上,我很高兴看到< code>MediaRouter类,然而令我沮丧的是,没有可预测的方法来确定路由类型。例如,当切换到蓝牙A2DP设备时,唯一的标识项是< code>RouteInfo.getName()方法,但这会返回A2DP设备的友好名称,因此无法进

  • 本文向大家介绍Android中检测当前是否为主线程最可靠的解决方法,包括了Android中检测当前是否为主线程最可靠的解决方法的使用技巧和注意事项,需要的朋友参考一下 如果在Android中判断某个线程是否是主线程?对于这个问题,你可能说根据线程的名字,当然这个可以解决问题,但是这样是最可靠的么?万一某天Google一下子将线程的名字改称其他神马东西呢。 方法揭晓 下面的方法是最可靠的解决方案。

  • 本文向大家介绍C#检测是否有u盘插入的方法,包括了C#检测是否有u盘插入的方法的使用技巧和注意事项,需要的朋友参考一下 本文实例讲述了C#检测是否有u盘插入的方法。分享给大家供大家参考。具体如下: 该C#代码可监控是否有u盘插入,同时可以监控其它驱动器的变化 希望本文所述对大家的C#程序设计有所帮助。

  • 本文向大家介绍Ruby中检测Gem是否安装的方法,包括了Ruby中检测Gem是否安装的方法的使用技巧和注意事项,需要的朋友参考一下 最近参加七牛的demo大赛,决定使用ruby开发。于是遇到了一些疑问,然后解决了,这里记录一下。 在Ruby中,Gem是一个很常见的东西,其相当于插件,Ruby有很多很棒的gem,避免了我们重复造轮子,我的demo中需要安装gem,但是为了更加实现好一些,先检测gem

  • 问题内容: 我想将CSS规则应用于其类之一与指定前缀匹配的任何元素。 例如,我想要一个规则,该规则将适用于以(A和C,但以下代码段中不包含B)开头的类的div : 某种组合: 和 在CSS 2.1下可以使用吗?它可以在任何CSS规范下执行吗? 注意:我知道我可以使用jQuery来模拟。 问题答案: 这不是可行的与CSS2.1,但它有可能与CSS3属性字符串匹配选择(这 是 在IE7 +支持): 注

  • 我想知道的所有值是否为空。除了必须检查映射中每个条目中的值之外,还有什么是最好的方法?