如何获得鼠标移动之间的时间?

Posted

技术标签:

【中文标题】如何获得鼠标移动之间的时间?【英文标题】:How to get time between mouse moves? 【发布时间】:2018-08-01 00:46:56 【问题描述】:

我正在尝试获取鼠标移动时间之间的毫秒时间。我正在为鼠标移动事件使用一个库,以便它在全局范围内工作。问题是使用下面的代码,时间总是为零。

        @Override
        public void mouseMoved(GlobalMouseEvent event)
        
            //times the mouse has moved
            moveCount++;

            //if it's the first time moving mouse then it's the start time
            if (moveCount % 2 != 0)
            
                startTime = System.currentTimeMillis();
            

            //if it's the second time moving the mouse then it's the end 
            //time
            if (moveCount % 2 == 0)
            
                long endTime = System.currentTimeMillis();
                long time = (endTime - startTime);

                System.out.println(time);
            
        

【问题讨论】:

您可能需要比毫秒更高的分辨率。使用System.nanoTime() 尝试纳秒 How do I measure time elapsed in Java?的可能重复 mouseMoved 会被非常频繁地调用。鼠标一拖可能会导致数十或数百次调用。尝试更高分辨率的时间戳 顺便说一句,我认为您的概念可能略有错误。考虑一下我正在将鼠标从 A 移动到 B,从 B 移动到 C。这可能会生成两个事件,即“鼠标在 B 点”和“鼠标在 C 点”。这是两个动作,但您的代码只会假设一个动作,并完全忽略从 B 到 C 的移动。 @DennyWilliams:您是否尝试检测鼠标运动(从 A 点到 B 点)以及该运动的时间? 【参考方案1】:

如果您想检测鼠标移动及其属性,让我们先定义移动:

鼠标移动可以定义为开始将鼠标指针从A点移动到B点,然后鼠标指针停留在B 点超过一个阈值,将其检测为运动的结束。

如果我们像上面那样定义问题,我们可以通过在鼠标开始移动时启动一个计时器,然后在鼠标移动时重新启动该计时器来解决它。然后,如果计时器在 阈值 之后超时,我们可以假设该动作结束于之前开始的运动。那么鼠标指针从A点到达B点所经过的时间就是这次移动的时间。

要以体面的方式对上述想法进行编码,我们可以按以下形式定义 MouseMovementListenerMouseMovementEvent 和其他实用程序类:

我们的自定义事件:

import java.awt.Point;

public class MouseMovementEvent 
    private Point startPoint;
    private Point endPoint;
    private Long  startNanoTime;
    private Long  endNanoTime;

    public MouseMovementEvent(Point startPoint, Point endPoint, Long startNanoTime, Long endNanoTime) 
        this.startPoint = startPoint;
        this.endPoint = endPoint;
        this.startNanoTime = startNanoTime;
        this.endNanoTime = endNanoTime;
    

    public Point getStartPoint() 
        return startPoint;
    
    public Point getEndPoint() 
        return endPoint;
    
    public Long getStartNanoTime() 
        return startNanoTime;
    
    public Long getEndNanoTime() 
        return endNanoTime;
           
    public Long getMotionDurationInNanos() 
        return endNanoTime - startNanoTime;
    

监听器接口:

public interface MouseMovementListener 
    void movementOccured(MouseMovementEvent e);

然后是监控鼠标移动的代码并将其转换为Movement Event

import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionAdapter;

import javax.swing.JComponent;
import javax.swing.Timer;

public class MouseMovementMonitor 

    private Point startPoint;
    private Point currentPoint;
    private Long  startTime;
    private Timer timer;

    public MouseMovementMonitor(JComponent componentToMonitor, int motionTimeDelay, final MouseMovementListener movementListener) 
        timer = new Timer(motionTimeDelay, new ActionListener() 

            @Override
            public void actionPerformed(ActionEvent e) 

                if(startPoint != null && !startPoint.equals(currentPoint)) 
                    movementListener.movementOccured(
                            new MouseMovementEvent(startPoint, currentPoint, startTime, System.nanoTime())
                        );
                

                startPoint = null; // either can be 
                startTime  = null;

                // or reset process can be as follow instead of the two above lines: 
                // startPoint = currentPoint;
                // startTime  = System.nanoTime();

                timer.stop();
            

        );

        componentToMonitor.addMouseMotionListener(new MouseMotionAdapter() 

            @Override
            public void mouseMoved(MouseEvent e) 
                if(startPoint == null) 
                    startPoint = e.getPoint();
                    startTime  = System.nanoTime();
                
                currentPoint = e.getPoint();
                //
                if(timer.isRunning())
                    timer.restart();
                else
                    timer.start();
            
        );
    

最后测试一下:

import java.awt.BorderLayout;
import java.awt.Color;

import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.WindowConstants;

public class Test 
    public static void main(String[] args) 
        JPanel p = new JPanel();
        p.setBackground(Color.PINK);

        new MouseMovementMonitor(p, 500, new MouseMovementListener() 
            @Override
            public void movementOccured(MouseMovementEvent e) 
                System.out.println("Movement Duration in nanos: " + e.getMotionDurationInNanos());              
            
        );

        JFrame f = new JFrame();
        f.setBounds(200,200,200,200);
        f.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
        f.setLayout(new BorderLayout());
        f.add(p, BorderLayout.CENTER);
        f.setVisible(true);
    

在此示例中,我没有公开移动的 开始结束 点,但我们的 MouseMovementEvent 对象拥有这些信息,如果您需要的话。

希望这会有所帮助!

【讨论】:

以上是关于如何获得鼠标移动之间的时间?的主要内容,如果未能解决你的问题,请参考以下文章

js中鼠标移动事件触发时,如何获得当前鼠标在哪一个元素上

js中鼠标移动事件触发时,如何获得当前鼠标所在元素的内容

virtualbox如何能够让鼠标在主机和虚拟机之间自由移动,和移动东西?

Qt 的鼠标事件

Qt 如何获取滚动窗体中鼠标点击的坐标

js如何获取鼠标在某元素移动时~鼠标指针在元素中的坐标?