I have run into an oddball case where the useScreenMenuBar property
causes my menu to fail to update correctly. The problem is driven
by a need to provide a dynamic menu, whose contents are provided by
a JNI rounte -- which must not be run from the Swing thread (it
deadlocks if you do). The conventional way of providing dynamic
content in a menu is by setting a MenuListener, and adding the menu
items in the menuSelected method. That works fine, but since it is
run on the Swing thread, I cannot call my JNI method. When I defer
the call to another Thread, the added items are not seen. What
appears to be happening is that the Aqua L&F is building an
independent set of menus and items from the contents of my JMenu
in its own MenuListener (apple.laf.ScreenMenu, ScreenMenuBar and
ScreenMenuItem). Once the parallel hierarchy is set up, it is not
updated from the originals, even if they change. The net result is
that the menu winds up presenting what I intended it to present
the previous time it was shown. If I turn off the Screen Menu Bar
property, it works as expected.
Has anyone else seen this, and developed a work-around? The best
I've been able to come up with is to initially place a disabled
menu item saying to deselect and then reselect the menu to get
the valid list of items. I also thought of placing a listener on
the parent menu of my submenu, but I don't think I can guarantee
that enough time will elapse to allow the item set to be
determined before the user selects the submenu.
The thought of polling this method just to keep a set of current
menu items available just in case the menu is selected turns my
stomach ...
I am attaching sample code that demonstrates this. In the course
of creating this demo, I discovered that there are oddities when
the JMenu is located directly on the JMenuBar, rather than as a
submenu to another JMenu (when not using Screen Menu Bar). In my
case, however, I need to populate a submenu, so that is only of
academic interest.
private static JFrame makeFrame() {
JFrame frm = new JFrame("Menu Update Test");
JMenuBar mbar = new JMenuBar();
JMenu menu = mbar.add(new JMenu("Menu"));
JMenu submenu = new JMenu("Submenu");
// Change testmenu to either menu or submenu, to observe
effects on
// a primary menu or on a nested submenu.
final JMenu testmenu = submenu;
testmenu.add("Initial Item").setEnabled(false);
testmenu.addMenuListener (new MenuListener() {
private int pos = 0;
public void menuSelected(MenuEvent ev) {
// Must use a separate thread to get the item list
Thread t = new Thread() {
public void run() {
// Simulate calling JNI method to
obtain item list
final String[] list = new String[3];
for (int ix = 0 ; ix < list.length ;
++ix) {
list[ix] = ITEMS[pos];
pos = (pos + 1) % ITEMS.length;
}
System.err.println ("Setting menu: "
+ list[0] + " ... " + list[list.length-1]);
// Must update the menu from the
Swing thread
SwingUtilities.invokeLater(new
Runnable() {
public void run() {
testmenu.removeAll();
for (int ix = 0 ; ix <
list.length ; ++ix)
testmenu.add(list[ix]);
}
});
}
};
t.start();
}
public void menuDeselected(MenuEvent ev) {
}
public void menuCanceled(MenuEvent ev) {
}
});
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Java-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
http://lists.apple.com/mailman/options/java-dev/email@hidden