1

I have a JDialog class:

public class Test extends JDialog {
private JPanel panel = new JPanel ( new BorderLayout() );
 public Test () {
   super(frame,"Evidenziatore");
   setDefaultCloseOperation(HIDE_ON_CLOSE);
   setVisible(true);
   add( panel, BorderLayout.CENTER );
 }
}

What I'd like to do is to make JDIalog disappear after user has exited from that JDialog or from the JPanel for a few seconds, e.g. using mouseEntered or mouseExited events or after user has clicked somewhere else. I mean something like chrome or firefox search window, avaible using ctrl-f.

How can I do that?

Thanks

Frank
  • 2,083
  • 8
  • 34
  • 52
  • Please have a look at this wonderful answer, regarding [closing a JOptionPane programatically](http://stackoverflow.com/a/18107432/1057230) by @kleopatra :-) – nIcE cOw Aug 23 '13 at 14:11

3 Answers3

2

You could use a Timer which is triggered on a mouseEntered or mouseExited. You could also use a FocusListener to cater for what happens when the Dialog looses focus (timer starts) or when it gains it (timer stops, no timer related event is to be fired).

npinti
  • 51,780
  • 5
  • 72
  • 96
2

Start with taking a look at How to write a mouse listener.

This is, actually, a complex problem.

Basically, when you add a mouse listener to a component that is higher in the visual hierarchy, it's child components (that that higher component covers) will no longer receive mouse events...

So a basic example might look something like this...

import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class AutoHide {

    public static void main(String[] args) {
        new AutoHide();
    }

    private Timer autoHideTimer;

    public AutoHide() {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                try {
                    UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                } catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
                }

                final JFrame frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.setLayout(new BorderLayout());
                frame.add(new JLabel("Auto Hide"));
                frame.pack();
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                autoHideTimer = new Timer(1000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        frame.dispose();
                    }
                });
                autoHideTimer.setRepeats(false);

                frame.addMouseListener(new MouseAdapter() {
                    @Override
                    public void mouseExited(MouseEvent e) {
                        System.out.println("Restart...");
                        autoHideTimer.restart();
                    }

                    @Override
                    public void mouseEntered(MouseEvent e) {
                        System.out.println("Stop");
                        autoHideTimer.stop();
                    }
                });

            }
        });
    }

}

Now this will work, because JLabel doesn't have a MouseListener attached to it, but if you were to, say, add JPanel to the content pane and add a MouseListener to that, it will block the mouse events going to the frame...

MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • 1
    Probably should call `autoHideTimer.setRepeats(false)` too to avoid keeping the timer around after it's become useless. – kiheru Aug 23 '13 at 07:47
  • @kiheru Now you're just spoiling all my fun ;) – MadProgrammer Aug 23 '13 at 07:49
  • sorry I think I miss something because the "autoHideTimer = new Timer(1000, new ActionListener() {..." line doesn't work for me, either "setRepeats()", "restart()", "stop()" methods. Do I maybe have to write them manually :)? – Frank Aug 23 '13 at 08:40
  • @Frank You've imported `java.util.Timer` not `javax.swing.Timer`, check the imports in the example if you're unsure... – MadProgrammer Aug 23 '13 at 09:36
0

Use a Panel with a JTextField! You should write your own TextField and Overwrite the focusLost(FocusEvent e) method. That works like that:

public class MyTextField extends JTextField implements FocusListener

Eclipse (or NetBeans) should warn you that you have to override some methods, do that!

Use a clock or somthing to make that it disapeers after a few secounds. For example:

Thread.sleep(5000);

Now your program should sleep for 5 secounds. Keep in mind that you should use a other thread because if you do not use one the gui will freeze as long as the timer runs!

Gerret
  • 2,948
  • 4
  • 18
  • 28
  • Why override `focusLost`...in fact I don't think `JTextField` has a `focusLost` method to be overridden. What if there are other components that the user is expected to interact with ? – MadProgrammer Aug 23 '13 at 07:42
  • @MadProgrammer sure there is i tried it out... if the focus is lost the user has no courser on it. For example [here](http://stackoverflow.com/questions/1738966/java-jtextfield-with-input-hint/1739037?noredirect=1#comment26947510_1739037) – Gerret Aug 23 '13 at 07:51
  • Now that you've added a `FocusListener` there is a method are methods to be implemented, but `JTextField` doesn't itself have a `focusLost` method. Extending a class for just this purspose seems wasteful to me, simpler just to register a `FocusListener` to a plain old `JTextField` - IMHO - Also, I hope you're not suggesting that the OP use `Thread.sleep` in the EDT – MadProgrammer Aug 23 '13 at 07:54
  • @MadProgrammer ... yea could be -.-' but why do not use it? Maybe he want to do more with his JTextField for example show a hint? Than he can't do that with your solution. The Thread.sleep I suggest because I dont know a other method. Thats the reason why I said "clock or somthing". btw you don't have to make my answer bad it is fully correct... – Gerret Aug 23 '13 at 07:58
  • `JTextField.setToolTipText`? It's not that you answer was bad, it just wouldn't have worked the way you originally posted. It's bad practice to simple override a class to implement an interface which it already has a register method for anyway. Pausing in the EDT will STOP THE WHOLE APPLICATION, so yes, it's a bad suggestion, I'm prodding you to make the answer more clear and less ambigious so the OP doesn't fall into nasty pitfalls – MadProgrammer Aug 23 '13 at 08:01
  • In fact, unless you use `addFoucsListener`, it still won't (work) ;) – MadProgrammer Aug 23 '13 at 08:03
  • Yes, but your intention is unclear. Don't forget, Swing is single threaded environment. It is expected that all interactions with the UI will be done from within the context of the EDT, this would included `frame.dispose` – MadProgrammer Aug 23 '13 at 08:05
  • Also, apart from a passing phrase about the chrome and firefox, we have no context to the question about what the intentions of the OP are ;) – MadProgrammer Aug 23 '13 at 08:05
  • @MadProgrammer so it is actully right? or not? It would work!? – Gerret Aug 23 '13 at 08:08
  • xD @MadProgrammer stop now and let my code its good enough everything work you dont have to do all in the same class so the class keeps clean and the tread.sleep is right too if you use a multithreading program i descriped the problem so it is ok – Gerret Aug 23 '13 at 09:40
  • I'm glad you don't tech people how to shot 8P – MadProgrammer Aug 23 '13 at 10:01
  • @MadProgrammer you always have to give a last comment or not -.-' – Gerret Aug 23 '13 at 10:19