Mailing Lists: Apple Mailing Lists

Image of Mac OS face in stamp
 
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Screen Menu Bar Async Updates



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.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.event.*;

public class MenuUpdate {
private final static String[] ITEMS = { "Able", "Baker", "Charlie", "Delta", "Echo", "Foxtrot", "Golf", "Hotel" };


    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    JFrame frm = makeFrame();
                    frm.pack();
                    frm.show();
                }
            });
    }

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


        if (testmenu == submenu) menu.add(submenu);

        frm.setJMenuBar (mbar);
        frm.getContentPane().setPreferredSize(new Dimension(256, 64));

        return frm;
    }
}

_______________________________________________
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

This email sent to email@hidden


Visit the Apple Store online or at retail locations.
1-800-MY-APPLE

Contact Apple | Terms of Use | Privacy Policy

Copyright © 2007 Apple Inc. All rights reserved.