Littlefean / mouse-track

记录在做不同事情时鼠标移动轨迹的样子
MIT License
114 stars 36 forks source link

[Solved]增加鼠标滚轮滚动位置操作记录 #10

Open FoxonFires opened 2 hours ago

FoxonFires commented 2 hours ago

参照services\move_tracker.py和click_tracker.py,照猫画虎新增了一个鼠标滚轮操作记录,翻文档或代码时也能证明没摸鱼……

还是直接贴在这里了: services\scroll_tracker.py

import tkinter as tk

from service.image_cache import ImageCache
from service.types import Color

class ScrollTracker(tk.BooleanVar):
    def __init__(self, cache: ImageCache):
        """A tracker that maintains a state of whether it should track or not"""
        super(ScrollTracker, self).__init__(value=True)
        self.cache = cache

    def track(self, x: int, y: int, dx: int, dy: int):
        if self.get():

            R = int(255*(dx + 1) / 2)   # 没有能测试横向滚的设备,Shift+滚轮还是(0, +-1)
            G = int(255*(dy + 1) / 2)   # 上下滚动时(dx, dy) = (0, +-1)
            B = 255
            colour = (R, G, B, 255)     # 借一下法线贴图的颜色映射

            # print(f"scroll at ({x}, {y}), dir({dx}, {dy}), UV({R}, {G}, {B})")
            self.cache.ellipse(x, y, color = colour)

顺便更新了一些其他文件,调用上面的: services\trackers.py

from typing import Dict

from pynput import mouse

from service.click_tracker import ClickTracker
from service.move_tracker import MoveTracker
from service.scroll_tracker import ScrollTracker

class Trackers(mouse.Listener):
    def __init__(self,
                 click_trackers: Dict[mouse.Button, ClickTracker],
                 move_tracker: MoveTracker,
                 scroll_tracker: ScrollTracker
                 ):
        """
        Implemented by pynput.mouse
        The `mouse.Listener` will create a thread.
        """
        self.click_trackers = click_trackers
        self.move_tracker = move_tracker
        self.scroll_tracker = scroll_tracker

    def reset(self):
        """Reset the mouse listener"""
        super(Trackers, self).__init__(
            on_move=self.move_tracker.on_move,
            on_click=self.on_click,
            on_scroll=self.on_scroll
        )

    def on_click(self, x, y, button, pressed):
        """Pick the right tracker and track"""
        if pressed:
            self.click_trackers[button].track(x, y)

    def on_scroll(self, x, y, dx, dy):
        self.scroll_tracker.track(x, y, dx, dy)

以及main.py初始化的应用构造函数:

class App(tk.Tk):
    def __init__(self):
        super(App, self).__init__()

        # 配置ui信息
        self.title("Mouse Tracker")
        self.geometry("400x400")
        icon_path = './assert/a952d-5afjj.icns'
        if sys.platform.startswith("darwin"):
            icon_image = ImageTk.PhotoImage(Image.open(icon_path))
            self.iconphoto(True, icon_image)
        else:
            self.wm_iconbitmap('./assert/favicon.ico')
        self.config(
            background='#2e3e26',
        )

        # 绑定数据信息
        self.imageCache = ImageCache(
            get_main_screen_size()
        )

        self.line_opacity_value = tk.IntVar(value=50)
        self.line_opacity = InputRange(
            '线条不透明度(实时)',
            variable=self.line_opacity_value,
            from_=1,
            to=100,
        )

        self.line_width_value = tk.IntVar(value=2)
        self.line_width = InputRange(
            '线条宽度(实时)',
            variable=self.line_width_value,
            from_=1,
            to=25,
        )

        self.trackers = Trackers(
            click_trackers={
                mouse.Button.left: ClickTracker(cache=self.imageCache, color=Colors.Left),
                mouse.Button.right: ClickTracker(cache=self.imageCache, color=Colors.Right),
                mouse.Button.middle: ClickTracker(
                    cache=self.imageCache, color=Colors.Middle
                ),
            },
            move_tracker=MoveTracker(self.imageCache, self.line_opacity_value, self.line_width_value),
            scroll_tracker=ScrollTracker(cache=self.imageCache),
        )
        # 挂载组件
        self.radio_list = [     #勾选checklist
            Radio(self, text=text, variable=tracker)
            for text, tracker in zip(
                ["记录左键点击位置", "记录右键点击位置", "记录中键点击位置", "记录鼠标移动轨迹", "记录滚轮滚动位置"],
                [*self.trackers.click_trackers.values(), self.trackers.move_tracker, self.trackers.scroll_tracker],
            )
        ]
        self.switch_button = SwitchButton(
            [self.start_tracking, self.stop_tracking],
            ['开始记录', '结束记录'],
        )
        self.open_out_files = SwitchButton(
            [open_out_folder], ['打开out文件夹']
        )
FoxonFires commented 2 hours ago

上头,调了大半夜,晚安(¦3[▓▓] 晚安

FoxonFires commented 2 hours ago

又发现了已知问题:使用笔记本触摸板双指滑动时(识别为滚轮),会造成迟滞页面卡顿,并伴随系统蜂鸣警告;手松开后需要等待几秒才能将缓冲区的硬件输入消息处理完毕,很明显是on_scroll()处理过慢阻塞了硬件输入。触摸板为联想 拯救者isk15原装,系统win 7。 PS:在我之前拿win api的 lowlevel钩子写过的一个鼠标键盘输入统计程序也出现过这个问题,但那边不会稳定触发。可能需要和监听鼠标移动on_move()一样需要优化或设置自锁?