Java swing弹出菜单和jlist

Vac*_*dik 21 java swing menu popup jlist

这是我的问题:我有一个jList和一个弹出菜单.当我右键单击jList时,弹出菜单显示.问题是鼠标指向的jList项目不会选择.我希望它能做到这一点.当我将光标指向列表中的某个项目并按下右键时,我想要发生两件事.选择我单击的项目并显示弹出菜单.

我试过这个:

jLists.addMouseListener(new MouseAdapter() {

     @Override
     public void mousePressed(MouseEvent e) {
            jList.setSelectedIndex(jList.locationToIndex(e.getPoint()));
     }
});

jList.setComponentPopupMenu(jPopupMenu);
Run Code Online (Sandbox Code Playgroud)

但它只显示弹出菜单.如果我删除这一行:

jList.setComponentPopupMenu(jPopupMenu);
Run Code Online (Sandbox Code Playgroud)

然后右键单击选择工作(但弹出菜单不显示).

那么,您认为使这两个功能(两者)都起作用的最佳方法是什么?

谢谢,抱歉我的英语.

Alb*_*dez 27

不要这样做setComponentPopupMenu.在MouseAdapter执行以下操作:

public void mousePressed(MouseEvent e)  {check(e);}
public void mouseReleased(MouseEvent e) {check(e);}

public void check(MouseEvent e) {
    if (e.isPopupTrigger()) { //if the event shows the menu
        jList.setSelectedIndex(jList.locationToIndex(e.getPoint())); //select the item
        jPopupMenu.show(jList, e.getX(), e.getY()); //and show the menu
    }
}
Run Code Online (Sandbox Code Playgroud)

这应该工作.

编辑:代码现在检查两者pressrelease事件,因为一些平台在鼠标按下时显示弹出窗口,而在发布时显示其他一些平台.有关详细信息,请参阅Swing教程.

  • 请注意,以这种方式避免使用`setComponentPopupMenu`意味着您将无法通过键盘调用弹出菜单. (3认同)
  • 老实说,我会使用`if(e.getButton()== MouseEvent.BUTTON3)`而不是`if(e.isPopupTrigger())`,原因很简单,触发器方法总是为我返回false.否则我会100%编码@jmendeth +1. (2认同)

Ran*_*een 9

如果你想继续使用setComponentPopupMenu(这很好,因为它以跨平台的方式处理弹出窗口的鼠标和键盘调用),你可以覆盖JPopupMenu.show(Component, int, int)以选择适当的行.

JPopupMenu jPopupMenu = new JPopupMenu() {
    @Override
    public void show(Component invoker, int x, int y) {
        int row = jList.locationToIndex(new Point(x, y));
        if (row != -1) {
            jList.setSelectedIndex(row);
        }
        super.show(invoker, x, y);
    }
};

jList.setComponentPopupMenu(jPopupMenu);
Run Code Online (Sandbox Code Playgroud)

请注意,当您通过键盘调用弹出窗口时(并且您也不会覆盖getPopupLocation目标组件),您获得的x,y位置JPopupMenu.show将是组件的中点.如果在这种情况下已经有选择,您可能不想更改选择.

我想出解决键盘与鼠标调用问题的解决方案是在覆盖的组件上设置客户端属性getPopupLocation,然后在显示弹出窗口时检查它.该参数getPopupLocationnull在通过键盘调用.这是核心代码(可能在组件及其弹出菜单中可用的实用程序类中实现).

private static final String POPUP_TRIGGERED_BY_MOUSE_EVENT = "popupTriggeredByMouseEvent"; // NOI18N

public static Point getPopupLocation(JComponent invoker, MouseEvent event)
{
    boolean popupTriggeredByMouseEvent = event != null;
    invoker.putClientProperty(POPUP_TRIGGERED_BY_MOUSE_EVENT, Boolean.valueOf(popupTriggeredByMouseEvent));
    if (popupTriggeredByMouseEvent)
    {
        return event.getPoint();
    }
    return invoker.getMousePosition();
}

public static boolean isPopupTriggeredByMouseEvent(JComponent invoker)
{
    return Boolean.TRUE.equals(invoker.getClientProperty(POPUP_TRIGGERED_BY_MOUSE_EVENT));
}
Run Code Online (Sandbox Code Playgroud)

然后getPopupLocation在组件中覆盖:

@Override
public Point getPopupLocation(MouseEvent event)
{
    return PopupMenuUtils.getPopupLocation(this, event);
}
Run Code Online (Sandbox Code Playgroud)

并调用isPopupTriggeredByMouseEvent覆盖JPopupMenu.show以确定是否在弹出位置选择行(或者对底层组件可能有意义的任何操作):

JPopupMenu jPopupMenu = new JPopupMenu() {
    @Override
    public void show(Component invoker, int x, int y) {
        int row = jList.locationToIndex(new Point(x, y));
        if (row != -1 && PopupMenuUtils.isPopupTriggeredByMouseEvent((JComponent) invoker)) {
            jList.setSelectedIndex(row);
        }
        super.show(invoker, x, y);
    }
};
Run Code Online (Sandbox Code Playgroud)