【问题标题】:How to close JFrame after user inactivity?用户不活动后如何关闭 JFrame?
【发布时间】:2014-04-08 23:12:17
【问题描述】:

在用户不活动后如何关闭 JFrame?

到目前为止,

Thread.sleep(10000);

如果有人能给我代码来做这件事,我将不胜感激?

我是 Java 新手,想了解更多关于系统安全的知识

【问题讨论】:

  • 添加点击或按键监听并监听。存储最后一次用户操作的时间并使用摇摆计时器。
  • @Braj,我该如何编码,哈哈
  • @Azar MouseListener 可能不是最好的解决方案,因为它可以被 MouseListeners 的其他组件“隐藏”......只是说;)
  • @MadProgrammer 好点,我没有考虑过。

标签: java swing jframe thread-sleep user-inactivity


【解决方案1】:

这是 Braj 使用 javax.swing.Timer 的想法的示例。

它简化了流程,因为您不需要监视事件之间的时间,并确保在触发计时器时,事件发生在事件调度线程中,进一步降低了复杂性。

还请注意,我将AWTEvent.MOUSE_MOTION_EVENT_MASKAWTEvent.MOUSE_WHEEL_EVENT_MASK 事件包括在内以进行良好的衡量;)

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();
            }
        });
    }

}

【讨论】:

    【解决方案2】:

    试试这个

    要遵循的步骤:

    • 它监听键事件和鼠标事件。
    • 将启动一个新线程来进行检查。
    • 如果时间差超过指定时间(在下面的示例代码中为 10 秒),则处理窗口。
    • 就是这样。

    这里是示例代码:

        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();
    

    【讨论】:

    • 几乎,你的 window.dispose 在 EDT 外被处决。更好的解决方案是使用SwingTimer 并在每次事件通过您的事件处理程序时简单地“重新启动”它。此外,事件掩码是事件类型的位掩码,因此将它们加在一起是行不通的,您需要使用|(我认为)-AWTEvent.KEY_EVENT_MASK | AWTEvent.MOUSE_EVENT_MASK
    • @MadProgrammer 请您使用SwingTimer 发布答案,以便对我和其他人都有帮助。
    • 另外,您没有监控事件发生在哪个窗口;)
    • 我认为只有一个窗口。
    • 我在JFrame 上尝试过关键监听器,但它不起作用。请告诉我好吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-30
    • 1970-01-01
    • 1970-01-01
    • 2012-01-18
    • 2022-01-22
    • 1970-01-01
    相关资源
    最近更新 更多