views:

91

answers:

3

I looked through ApplicationListener, and they don't have it in there. On a Mac, it's when that application has the equivalent of focus; its menu is in the top menu bar.

Also, if you know this, could you tell me how my application can request to de-focus itself?

+3  A: 

Implementations of windowActivated() and windowDeactivated() in WindowListener or WindowAdapter will tell you when a window is activated or deactivated. You don't need ApplicationListener for that.

Addendum: Although not required in this case, a transparent implementation of the additional functionality specified in ApplicationListener may be found in this example.

Addendum: See also How to Write Window Listeners.

Addendum: I think I see what you mean. In the example OSXAdapter, which uses -Dapple.laf.useScreenMenuBar=true, the menus disappear when the last window (HIDE_ON_CLOSE by default) closes. It's less than optimal, but the About… and Preferences menus remain in the application menu; choosing either restores the screen menu. Another possibility is to modify the dock menu in com.apple.eawt.Application.

import java.awt.EventQueue;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowFocusListener;
import java.awt.event.WindowListener;
import java.awt.event.WindowStateListener;
import javax.swing.JButton;
import javax.swing.JFrame;

public class WindowTest extends JFrame implements ActionListener,
    WindowListener, WindowFocusListener, WindowStateListener {

    public static final void main(String args[]) throws Exception {
        EventQueue.invokeLater(new Runnable() {

            @Override
            public void run() {
                new WindowTest("One");
                new WindowTest("Two");
            }
        });
    }

    public WindowTest(String name) {
        super(name);
        this.setName(name);
        this.setLayout(new GridLayout(0, 1));
        createButton("Back");
        createButton("Front");
        createButton("Hide");
        this.addWindowListener(this);
        this.addWindowFocusListener(this);
        this.addWindowStateListener(this);
        this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        this.setLocationRelativeTo(null);
        this.pack();
        this.setVisible(true);
    }

    private void createButton(String name) {
        JButton b = new JButton(name);
        this.add(b);
        b.addActionListener(this);
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        String s = e.getActionCommand();
        if ("Back".equals(s)) {
            this.toBack();
        } else if ("Front".equals(s)) {
            this.toFront();
        } else {
            this.setExtendedState(JFrame.ICONIFIED);
        }
    }

    @Override
    public void windowOpened(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowClosing(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowClosed(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowIconified(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowDeiconified(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowActivated(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowDeactivated(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowGainedFocus(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowLostFocus(WindowEvent e) {
        System.out.println(e);
    }

    @Override
    public void windowStateChanged(WindowEvent e) {
        System.out.println(e);
    }

}
trashgod
The problem is, I hid my window by using `frame.setVisible(false)`, which hides the window, but does not function like a Mac's 'hide' option. It hides the frame, however the application retains focus. Using `frame.toBack()` didn't work either; the application retained focus, just the window was moved to the back. On a mac, when you hide an application, the application hides all of its windows and defocuses, and unhides them all when you give the application focus. However, with `frame.setVisible()`, even when you defocus the application and give it focus back, it doesn't reappear.
Stuart
(Continued) They're completely different methods, `setVisible()` and a Mac's hide function. The problem is, I already use a WindowListener, but the window doesn't reappear when I give it focus, so it doesn't work. You see my big problems, here? I've tried these. Do you have any other suggestions? I know you probably don't have experience with Macs, but you've been very helpful in the past.
Stuart
@Stuart: `toBack()` makes no promises about focus. AFAIK, switching applications is the user's purview. The example above shows `Window` events for two windows, but you might explore the tutorial, too.
trashgod
I already use OSXAdapter, but it is inadequate. I cannot manage or detect application focus at all, among other things. I wish I could find a way to do this...
Stuart
trashgod
I know about the window losing and gaining focus. I'm talking about the application having focus. On a Mac, the menu is at the very top of the screen, not in windows. That means you still have a menu at the top regardless of the application having any windows open. What I'm trying to do is detect when that top menu changes, and application focus is exchanged, not when windows exchange focus, because sometimes my application will not have windows open.
Stuart
The application menu remains after all windows are closed, but I don't know of an alt-tab event. I've elaborated above.
trashgod
I have an idea. Using Java, it is possible to run AppleScript. What I'll do is tell my Java application to hide. I just hope the window listener sees hiding and unhiding as activating and deactivating, otherwise detecting when the user switches back will become very complicated...
Stuart
I never tried to call `Applescript`. Although `ProcessBuilder` will work, it seems awkward. In any case `setExtendedState(JFrame.ICONIFIED)` generates the corresponding `WindowEvent`, as can be seen by using the dock menu with the example above.
trashgod
+1  A: 

could you tell me how my application can request to de-focus itself?

You can try:

frame.toBack();

If that doesn't work then you can iconify your application in which case focus should go to the previous application.

frame.setExtendedState(...);
camickr
For reference, both work as expected on Mac OS X.
trashgod
A: 

The Java programming language is platform-independent. Rather than reading Apple's reference documentation, you should be using the official Java API Reference Documentation. There you will find documentation for JFrame, WindowListener, and WindowAdapter. You can register a WindowListener on a JFrame, using the addWindowListener function. The window listener may be used to intercept and handle a variety of window-related events including activated/deactived (which window is on top) or gained focus/ lost focus (which window will receive keyboard events). If you are supplying your own WindowListener and don't want to implement every single function, WindowAdapter is useful for that purpose as it implements WindowListener but provides empty definitions for each function. As for defocusing (in the sense that you mean), toBack may be used for that, while toFront does the opposite.

Edit
Most of this information was already given in previous posts; however, I added this to emphasize:

  • Java is a platform-independent language.
  • Java is a product of Sun Microsystems (now Oracle).
  • Consquently, using the official Java API Reference Documentation from Sun makes way more sense than relying on any reference documentation provided by Apple, because anything contained within the official API reference documentation will work on all platforms; whereas, anything from Apple's reference documentation may very well to be specific to Apple's implementation.
  • The reference documentation for JFrame from the official, authoritative reference documentation gives all the information necessary for answering the question (hence yet another reason to consult the official API reference documentation, rather than relying on Apple's documentation).
Michael Aaron Safyan
-1, WindowListener was suggested 6 hours earlier. toBack() was suggested 5 hours earlier. I see no reason to repeat the suggestions.
camickr
Moreover, `ApplicationListener` is intended to supplement, rather than supplant, the core UI. See `README.txt` for the `OSXAdapter` example cited in my answer.
trashgod
@camickr, I wanted to emphasize the use of official reference documentation (see my edit). In addition, the others fail to indicate that "focus" in Java terminology implies keyboard focus (not which window is on top), which my answer also gives.
Michael Aaron Safyan