JPopupMenu.setSelected(Component) does not work - workaround suggestion

Hello everyone,

as you might have already recognized, setSelected() of JPopupMenu does not what one expects, i.e. selecting the passed component. Instead, the first element stays selected.

I was able to workaround the problem. My workaround is actually a hack, but it works from 1.4 to 6.0: I am emulating an appropriate amount of "Cursor down" key strokes. See the attached code.

// $Id$

// (C) cantamen/Dirk Hillbrecht 2007

// Released under LGPL or GPL+library exception

package biz.chitec.qdemo.swing;

import java.awt.Component;

import java.awt.Toolkit;

import java.awt.event.KeyEvent;

import javax.swing.AbstractButton;

import javax.swing.JPopupMenu;

/** JPopupMenu with working selection of certain elements in the item list.

*

* {@link JPopupMenu#setSelected(Component)} does not work as one expects. This class defines a replacement method

* which does the job. It's actually a hack. The method {@link #setSelectedItem(Component)} takes the currently

* selected item and emulates pressing the "cursor down" key enough times so that the wanted element is selected.

*

* @version $Id$

* @author cantamen/Dirk Hillbrecht 2007. Released under LGPL or GPL+library exception

*/

publicclass SelectableJPopupMenuextends JPopupMenu{

/** Return the index of the currently selected element in the menu.

*

* @return Index of selected element or -1 if no element is selected.

*/

publicint getSelectedIndex(){

for (int i=0;i<getComponentCount();i++){

Component c=getComponent(i);

if ((cinstanceof AbstractButton) && ((AbstractButton)c).isSelected())

return i;

}

return -1;

}

/** Select the element at the given index.

*

* @param selidx Index to select or -1 if nothing should be selected.

*/

publicvoid setSelectedIndex(int selidx){

if (selidx==-1)

getSelectionModel().clearSelection();

int oldsel=getSelectedIndex();

if (oldsel==-1)

oldsel=0;

if (selidx><oldsel)

selidx+=getComponentCount();

for (int i=oldsel;i<selidx;i++){

Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new KeyEvent(this,

KeyEvent.KEY_PRESSED,System.currentTimeMillis(),0,KeyEvent.VK_DOWN,KeyEvent.CHAR_UNDEFINED));

Toolkit.getDefaultToolkit().getSystemEventQueue().postEvent(new KeyEvent(this,

KeyEvent.KEY_RELEASED,System.currentTimeMillis(),0,KeyEvent.VK_DOWN,KeyEvent.CHAR_UNDEFINED));

}

}

/** Select the given item.

*

* If the menu does not contain the given item, the selection is cleared.

*

* @param selitem Item to select or null if no item should be selected.

*/

publicvoid setSelectedItem(Component selitem){

int selidx=-1;

if (selitem!=null){

for (int i=0;i<getComponentCount();i++){

if (selitem.equals(getComponent(i))){

selidx=i;

break;

}

}

}

setSelectedIndex(selidx);

}

}

// end of file

Perhaps this helps someone else saving some hours of coding around this problem.

Best regards,

Dirk

Message was edited by:

DirkHillbrecht>

[5286 byte] By [DirkHillbrechta] at [2007-11-27 11:19:37]
# 1

This posting shows another approach:

http://forum.java.sun.com/thread.jspa?forumID=57&threadID=641745

camickra at 2007-7-29 14:37:45 > top of Java-index,Desktop,Core GUI APIs...