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>

