1

How would I go about closing a JFrame after user inactivity?

So far I have,

Thread.sleep(10000);

I would greatly appreciate it if someone could give me code to do this?

I am new to Java and want to know more about system security

user2269663
  • 23
  • 1
  • 4

2 Answers2

4

This is an example of Braj's idea using a javax.swing.Timer.

It simplifies the process, as you don't need to monitor the time between events and ensures that when the timer is triggered, the event occurs within the Event Dispatching Thread, further reducing the complexity.

Also note that I included the AWTEvent.MOUSE_MOTION_EVENT_MASK and AWTEvent.MOUSE_WHEEL_EVENT_MASK events for good measure ;)

import java.awt.AWTEvent;
import java.awt.Component;
import java.awt.EventQueue;
import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.AWTEventListener;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;
import javax.swing.Timer;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;

public class AutoClose {

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

    private Timer timer;
    private JLabel label;
    private JFrame frame;

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

                label = new JLabel("Waiting...");
                frame = new JFrame("Testing");
                frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                frame.add(label);
                frame.setSize(200, 200);
                frame.setLocationRelativeTo(null);
                frame.setVisible(true);

                Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {

                    private int count;

                    @Override
                    public void eventDispatched(AWTEvent event) {
                        Object source = event.getSource();
                        if (source instanceof Component) {
                            Component comp = (Component) source;
                            Window win = null;
                            if (comp instanceof Window) {
                                win = (Window) comp;
                            } else {
                                win = SwingUtilities.windowForComponent(comp);
                            }
                            if (win == frame) {
                                timer.restart();
                                label.setText("Interrupted..." + (++count));
                            }
                        }
                    }
                }, AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK | AWTEvent.MOUSE_MOTION_EVENT_MASK | AWTEvent.MOUSE_WHEEL_EVENT_MASK);

                timer = new Timer(5000, new ActionListener() {
                    @Override
                    public void actionPerformed(ActionEvent e) {
                        frame.dispose();
                    }
                });
                // You could use a WindowListener to start this
                timer.start();
            }
        });
    }

}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
3

Try this one

Steps to follow:

  • Its listening for key event as well as mouse event.
  • A new thread is started that will check.
  • If the time difference is more than specified time (10 sec in below sample code) then dispose the window.
  • That's all.

Here is the sample code:

    private long time;

    ...

    long eventMask = AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK;

    Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() {
        public void eventDispatched(AWTEvent e) {
            time = System.currentTimeMillis();
        }
    }, eventMask);

    time = System.currentTimeMillis();
    new Thread(new Runnable() {

        @Override
        public void run() {
            while (true) {
                if (System.currentTimeMillis() - time > 10000) {
                    widnow.dispose();
                    break;
                }
            }
        }
    }).start();
Braj
  • 46,415
  • 5
  • 60
  • 76
  • 1
    Almost, you're `window.dispose` is been executed off the EDT. A better solution would be to use a `SwingTimer` and simply "restart" it each time an event went through your event handler. Also, the event mask is a bitmask of the event types so adding them together won't work, you would need to use `|` (I think) - `AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK` – MadProgrammer Apr 08 '14 at 23:37
  • @MadProgrammer Please can you post an answer using `SwingTimer`, so that it can be helpful for me as well as others. – Braj Apr 08 '14 at 23:43
  • Also, you're not monitoring which window the events occur on ;) – MadProgrammer Apr 08 '14 at 23:43
  • I think there is only one window. – Braj Apr 08 '14 at 23:44
  • I have tried key listener on `JFrame` but it was not working. Please can you tell me? – Braj Apr 08 '14 at 23:46
  • `window.dispose is been executed off the EDT.` Are you talking about `EventQueue.invokeLater()`? – Braj Apr 08 '14 at 23:48
  • `EventQueue.invokeLater()` - That's one solution. The OP hasn't given enough context over what they really want, personally, if I'm auto closing a Window, I want to make sure I'm only monitoring events from that window ... – MadProgrammer Apr 08 '14 at 23:55
  • The test I've posted works with key events as well. A `KeyListener` itself won't work, as it requires that the component it is attached to is focusable AND has focus. A `JFrame` actually can't achieve all these requirements, as it's covered by a `JRootPane` and "content pane" which will probably mask these events... – MadProgrammer Apr 08 '14 at 23:57
  • +1 for awt events (right and correct way) -1mio for Thread.sleep, – mKorbel Apr 09 '14 at 06:48
  • @mKorbel I know that its not a good practice to use `Thread.sleep()` in a swing application. I'll take care it. Thanks – Braj Apr 09 '14 at 07:30