tags:

views:

221

answers:

5

So if I was writing pseudo code:

if(mouseInsideFrame==true)
    frame.setVisible(true);
else
    frame.setVisible(false);

What method would I use for the mouseInsideFrame in the if statement?

Thanks

A: 

Normally you could use listeners. Specifically:

frame.addMouseListener(new MouseListener() {
    public void mouseEntered(MouseEvent evt) {
        frame.setVisible(true);
    }

    public void mouseExited(MouseEvent evt) {
        frame.setVisible(false);
    }
});

But the problem is that since your JFrame is not visible, there is no way to listen to mouse events!!!! At least, from what I know....

Alex
Nettogrof
Yes, you're right! Sorry! :-)
Alex
+1  A: 

Update: Same method as before, but with more explicit step-by-step explanation.

Other respondents wonder what you want to achieve with this and question the design behind an app that unexpectedly jumps up at the user. I guess it's a matter of how dead set you are to implement this functionality exactly as you described. The technique itself may be useful for other purposes too, which is my main motivation for my new, improved revision of this answer.


As far as I know, a frame that's not visible can't capture mouse events. So it won't know if the mouse is inside it or not.

There's a loophole around this problem: If you make your frame visible but borderless and fully transparent, it will be visible in the technical sense but invisible to the user for practical purposes.

The borderless part is easy: setUndecorated(true).

It would be great if JFrame had a method like setOpaque() or setTranslucent() where you could make it fully transparent, but alas, it doesn't.

Another answer mentions a solution based on a Sun private class which does permit you to make the window transparent. This will work for current and probably near-future Sun JREs but is far from guaranteed to work with other and future JREs, so I can't recommend it. Sun expliticly advises against using their private classes this way.

There's an alternate, somewhat hacky alternative: The frame is left fully visible but it displays the image of a screenshot of the screen behind it. Because this means we're effectively looking through the frame, it's effectively invisible. This solution is described here: http://onjava.com/pub/a/onjava/excerpt/swinghks_hack41/index.html?CMP=OTC-FP2116136014 . The author and I both admit to this being a a bit clumsy; it also involves a lot more code than should be necessary. But it's based on standard Java coding and should be supported unchanged in many Java environments upward of about version 1.4 or so.

The tip describes how to create a Component that displays the screen background. That's fine for when you want the frame to be invisible, but what happens when you want it to be normally visible?

The thing to do is to give the JFrame's ContentPane a CardLayout and add both the TransparentBackground component and your intended main visible component (likely a JPanel) to it. With that set up, switching between "invisible" and visible involves simply:

  • setUndecorated(false) // (true)
  • cardLayout.last() // (first)

This switching, of course, will be controlled by a MouseListener you can add to the JFrame.

Carl Smotricz
sounds unacceptable on many levels
medopal
@medopal: Java is more an "application" language than a "systems" language, thus a few things that *should* or at least *could* be simpler, aren't. While my proposed solution looks a bit clumsy, it will work. With that, I believe I've offered the best answer so far. I regret that you were apparently unable to understand it.
Carl Smotricz
A: 

Out of the top of my head, there is a fairly easy way to get the position of the mouse on the screen (I think it has something to do with Toolkit). Now, if you can combine that with a way to find out your frame's position on the screen (if you don't already know), you have your solution.

I'm curious what you're trying to do though.

Bart van Heukelom
+1  A: 

I came across a post on java.net that covers visibility options, including this one using a private AWT API.

public class TransparentFrame {
  private static final float OPAQUE = 1.0f;
  private static final float TRANSLUCENT = 0.1f;

  public static void main(String[] args) {
    final JFrame frame = new JFrame();
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(600, 400);
    frame.addMouseListener(new MouseAdapter() {
      @Override
      public void mouseEntered(MouseEvent e) {
        com.sun.awt.AWTUtilities.setWindowOpacity(frame, OPAQUE);
      }

      @Override
      public void mouseExited(MouseEvent e) {
        com.sun.awt.AWTUtilities.setWindowOpacity(frame, TRANSLUCENT);
      }
    });
    frame.setVisible(true);
  }
}

This is OK for toy code, but obviously I wouldn't use a private com.sun class for portable production code.

McDowell
A: 

Given what you are trying to do, I would say you need two frames (or perhaps just JPanels and frame that does a lot of changing. One is to capture the mouse moving over it (make it transparent, undecorated or otherwise acceptably out of the way) and when the mouse moves over it, show the new frame (or panel) and then hide that when the mouse moves out of it.

The other answers here give you the basics on how to capture the mouse events and set the frame undecorated and transparent.

Yishai