开发者

Java swing popup menu and jlist

here is my problem: I have a jList and a popup menu. When I right click the jList, the popup menu shows. The problem is that the jList item which the mouse is pointing at won't se开发者_如何学运维lect. And I want it to do that. When I point my cursor at an item in the list and press the right button, I want two things to happen. Select the item on which I clicked and show the popup menu.

I tried this:

jLists.addMouseListener(new MouseAdapter() {

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

jList.setComponentPopupMenu(jPopupMenu);

But it only shows the popup menu. If I delete this line:

jList.setComponentPopupMenu(jPopupMenu);

then the right-click select works (but the popup menu doesn't show).

So, what do you think is the best way to make these two functions (both) work ?

Thanks and sorry for my english.


Don't do setComponentPopupMenu. In the MouseAdapter do the following:

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
    }
}

This should work.

EDIT: The code now checks both press and release events, because some platforms show popups when mouse presses and some other on release. See the Swing tutorial for more info.


If you want to continue to use setComponentPopupMenu (which is nice because it handles mouse and keyboard invocations of the popup in a cross platform way), you could override JPopupMenu.show(Component, int, int) to select the appropriate row.

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);

Note that when your popup is invoked via the keyboard (and you don't also override getPopupLocation on your target component), the x, y location you get in JPopupMenu.show will be the midpoint of your component. If there's already a selection in this case you probably don't want to change the selection.

The solution I came up with to solve the keyboard vs. mouse invocation problem was to set a client property on the component in an override of getPopupLocation and then check it when showing the popup. The argument to getPopupLocation will be null when invoked via the keyboard. Here's the core code (perhaps implemented in a utility class available to your component and its popup menu).

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));
}

Then override getPopupLocation in your component:

@Override
public Point getPopupLocation(MouseEvent event)
{
    return PopupMenuUtils.getPopupLocation(this, event);
}

and call isPopupTriggeredByMouseEvent in an override of JPopupMenu.show to determine whether or not to select the row at the popup location (or whatever action may make sense for the underlying component):

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);
    }
};
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜