2011-05-15 3 views
21

вот моя проблема: У меня есть jList и всплывающее меню. Когда я нажимаю правой кнопкой мыши на jList, появляется всплывающее меню. Проблема в том, что элемент jList, на который указывает мышь, не будет выбирать. И я хочу, чтобы он это сделал. Когда я нажимаю курсор на элемент в списке и нажимаю правую кнопку, я хочу, чтобы произошло две вещи. Выберите элемент, на который я щелкнул, и покажу всплывающее меню.Всплывающее меню Java swing и jlist

Я попытался это:

jLists.addMouseListener(new MouseAdapter() { 

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

jList.setComponentPopupMenu(jPopupMenu); 

Но это только показывает всплывающее меню. Если удалить эту строку:

jList.setComponentPopupMenu(jPopupMenu); 

затем правой кнопкой мыши выберите работы (но всплывающее меню не отображается).

Итак, как вы считаете, лучший способ заставить эти две функции (оба) работать?

Спасибо и извините за мой английский.

ответ

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

Это должно работать.

EDIT: код проверяет, как press и release события, потому что некоторые платформы показывают всплывающие окна, когда прессы мыши и некоторые другие на выпуске. См. the Swing tutorial для получения дополнительной информации.

+0

Не большой поклонник непроверенного кода, но он был вынужден дать голосование за проверку 'isPopupTrigger()' - хорошего вызова. –

+0

Да, это работает.Благодаря ! – VaclavDedik

+0

@Vena, @Andrew Thompson: Добро пожаловать. –

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

Обратите внимание, что, когда ваше всплывающее окно вызывается с помощью клавиатуры (и вы не переопределить getPopupLocation на целевой компоненте), X, Y местоположение вы получаете в JPopupMenu.show будет середина компоненты. Если в этом случае уже есть выбор, вы, вероятно, не захотите изменить выбор.

Решение, с которым я столкнулся, чтобы решить проблему с клавиатурой против мыши, заключалось в том, чтобы установить свойство клиента на компоненте в переопределении getPopupLocation, а затем проверить его при показе всплывающего окна. Аргументом для getPopupLocation будет null при вызове с клавиатуры. Вот основной код (возможно, реализованный в классе утилиты, доступном вашему компоненту и его всплывающему меню).

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

Затем переопределить getPopupLocation в компоненте:

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

и вызвать 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); 
    } 
}; 
+1

недостающая часть 'jList = new JList () { @Override public Point getPopupLocation (событие MouseEvent) { return JListUtility.getPopupLocation (this, event); } }; ' – palindrom

+0

Спасибо, @palindrom. Я обновил свой ответ, включив использование 'getPopupLocation' –