Re: Adding ExitListeners to Netbeans generated Desktop Application?
On Thu, 07 Aug 2008 16:08:18 +0100, John B. Matthews =
<nospam@nospam.invalid> wrote:
Ah, I see. The problem isn't NetBeans itself; it's (protected) GUI cod=
e
generated by NetBeans. You only need to invoke setQuitHandler(), but y=
ou
need to do it in the JFrame's constructor.
FWIW, the ant target "package," which builds a Mac application bundle,=
is somewhat more transparent than the corresponding Xcode facility.
I look forward to hearing how this progresses.
It's proven to be simpler than expected (for handling Mac menu events, =
that is). Instructions on how I got the hooks to work easily are below. =
=
Right at the bottom is the problem I still haven't yet fixed (regards to=
=
catching the close action).
In the variables section of your application's GUI class (usually =
something-View in the case of netbeans):
-----
public static boolean MAC_OS_X = =
(System.getProperty("os.name").toLowerCase().startsWith("mac os x"));
final static int MENU_MASK = =
Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
-----
They detect which OS you're running, and the format of the shortcut keys=
=
(not sure how necessary the latter is).
After the netbeans generated Code at the beginning of your GUI =
constructor...
-----
public MyAppView(SingleFrameApplication app) {
super(app);
initComponents();
-----
I simply place:
-----
registerForMacOSXEvents();
if (MAC_OS_X){
//hide the menus if it's running on a Mac.
menuBar.removeAll();
}
-----
This enables you to check at runtime whether you're running on a Mac and=
=
then destroy the menu so it fits the usual look and feel of Mac OS X. It=
's =
a bit of a kludge, but it seemed to be the only way of removing the menu=
s =
since the construction code is guarded (not that I'm complaining).
In the IDE generated code for the GUI (after the constructor, not within=
=
it obviously), you can simply insert the registerForMacOSXEvents() metho=
d =
and then include the OSXAdapter.java class in your project, replacing th=
e =
default package name with the one for your project.
That then provides for the About, Preferences, File (open) and Quit menu=
s =
which are the usual items for Mac apps.
My version of the method is trimmed down, as I only need a Quit/Exit and=
=
About menu:
-----
public void registerForMacOSXEvents() {
if (MAC_OS_X) {
try {
// Generate and register the OSXAdapter, passing it a h=
ash =
of all the methods we wish to
// use as delegates for various =
com.apple.eawt.ApplicationListener methods
OSXAdapter.setQuitHandler(this, =
getClass().getDeclaredMethod("exitProperly", (Class[])null));
OSXAdapter.setAboutHandler(this, =
getClass().getDeclaredMethod("about", (Class[])null));
} catch (Exception e) {
System.err.println("Error while loading the OSXAdapter:=
");
e.printStackTrace();
}
}
}
-----
The OSXAdapter.setXXXXHandler methods simply get given the actual name o=
f =
the method you wish to call from your GUI's class. In my example, I'm =
calling exitProperly() - note that there are no brackets in the string =
passed as the method names above.
The problem I'm having now is that when I have attached a WindowListener=
=
which then points to my exitProperly() method, it carries out those =
actions, but is still closing the window if I add a "Do you wish to quit=
?" =
dialog. It seems that the default close action is not being set to do =
nothing.
I had the following code just after the initComponents() line:
-----
this.getFrame().setResizable(false);
this.getFrame().setDefaultCloseOperation(JFrame.DO_NOTHING_ON_C=
LOSE);
this.getFrame().addWindowListener(new Closer());
//I've also tried this, but this gives an error saying it can't be =
applied.
//app being mentioned at the start of the constructor and as super(app)=
;
app.addExitListener(new Closer());
-----
Now this works fine for the non-resizing window and also adds the =
listener, which gets executed when you close the window. However it is =
still exiting the program after performing my specified task in the =
exitProperly() method. The only reason I can see for this is that I am n=
ot =
setting the default close operation for the right 'thing'. If I could wo=
rk =
out what to apply the default close operation to, I won't need to add an=
=
exitlistener (which I don't think would help, as I need to be able to =
totally abort the close operation).
The official Mac example is of no use as it basically closes the window,=
=
but not the menu when you shut it (via the window close button) - then i=
f =
you quit via the menu which is the normal mac method for multiwindow app=
s, =
it pops back up but then closes. They don't seem to have catered for =
single-window applications in that regard, but that's because it basical=
ly =
uses the method I have below - it seems that if it returns true, it quit=
s, =
if it doesn't then it doesn't quit, or at least it shouldn't - if you =
override the default close operation.
I am truly poking around in the dark on this one, as I don't understand =
=
the way that Netbeans has formed the application.
-----
public boolean exitProperly() {
boolean val = false;
if ((JOptionPane.showConfirmDialog(null, "Are you sure?", "Quit=
", =
JOptionPane.YES_NO_OPTION)) == JOptionPane.YES_OPTION) {
val = true;
saveFile();
System.out.println("yes came up, I saved");
System.exit(0);
} else {
System.out.println("no came up");
}
return val;
}
public class Closer extends WindowAdapter {
@Override
public void windowClosing(WindowEvent e) {
System.out.println("Windowclosing");
exitProperly();
}
}
-----