Rap*_*ber 2 python scroll pyautogui
pyautogui 滚动量值 1 太小,2 对于我想要执行的特定任务来说太大。有没有办法在中间滚动?我尝试了1.5,但没有成功。
我使用的是 OSX 10.13,当使用触控板时,我肯定可以比 pyautogui 所做的更精确地滚动。
这是一个一直困扰我的问题,所以我查看了 pyautogui 源代码并能够解决该问题。这可能是一个很长的答案;我将尝试详细解释每一步。请注意,这仅适用于 Mac。(如果您想要答案而不是解释,请滚动到底部)
\n\n首先,这是滚动函数的源代码:
\n\ndef _scroll(clicks, x=None, y=None):\n _vscroll(clicks, x, y)\n\ndef _vscroll(clicks, x=None, y=None):\n _moveTo(x, y)\n clicks = int(clicks)\n for _ in range(abs(clicks) // 10):\n scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n None, # no source\n Quartz.kCGScrollEventUnitLine, # units\n 1, # wheelCount (number of dimensions)\n 10 if clicks >= 0 else -10) # vertical movement\n Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\n\n scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n None, # no source\n Quartz.kCGScrollEventUnitLine, # units\n 1, # wheelCount (number of dimensions)\n clicks % 10 if clicks >= 0 else -1 * (-clicks % 10)) # vertical movement\n Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\nRun Code Online (Sandbox Code Playgroud)\n\n让我们来分解一下:
\n\n1.
\n\ndef _scroll(clicks, x=None, y=None):\n_vscroll(clicks, x, y)\nRun Code Online (Sandbox Code Playgroud)\n\n这只是_vscroll函数的包装,很简单。
2.
\n\n要认识到的主要事情是,针对 Mac 的 pyautogui 使用 Quartz Core Graphics,它所做的只是为 Quartz 代码提供一个更简单、更易读的包装器。
\n\n使用滚动函数,它所做的是创建一个滚动事件:
\n\nscrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent
然后发布它:
\n\nQuartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)
忽略发布的细节,我们不会更改任何内容。
\n\n对我来说,这段代码似乎在重复,而且我不知道为什么for包含循环之后的任何代码。我从源代码中删除了它,一切正常;如果有人知道为什么包含此代码,请在下面评论并纠正我。
3.
\n\n所以我们留下了以下代码(忽略鼠标moveTo,它与滚动本身无关):
clicks = int(clicks)\nfor _ in range(abs(clicks) // 10):\n scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n None, # no source\n Quartz.kCGScrollEventUnitLine, # units\n 1, # wheelCount (number of dimensions)\n 10 if clicks >= 0 else -10) # vertical movement\n\n Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\nRun Code Online (Sandbox Code Playgroud)\n\na的格式CGEventCreateScrollWheelEvent如下:
Quartz.CGEventCreateScrollWheelEvent(source, units, wheelCount, scroll distance)
在本source例中是None,不用担心,我们只处理 1 个轮子,wheelCount所以1。
因此,源代码正在执行的操作是滚动 的距离\xc2\xb110 Quartz.kCGScrollEventUnitLine,这是一次“滚动”的计算机单位。无论您指定多少次,它都会在循环中重复此操作for,因为如果一次发送太多滚动单元,系统可能会出现错误。
因此,在 pyautogui 上可以滚动的最小次数是该循环的一次迭代,它发送一个计算机单元。问题是这些单位对于精细滚动来说太大了。
\n\n解决方案
\n\n我们需要更改可以发送的最小值。目前它是 1 Quartz.kCGScrollEventUnitLine,但我们可以通过用零替换它们来将它们更改为基本单位。我还认为不需要地板划分clicks( in range(abs(clicks) // 10)) 然后发送10滚动单元。
我们可以更改这两部分,并删除不必要的重复:
\n\ndef _scroll(clicks, x=None, y=None):\n _vscroll(clicks, x, y)\n\ndef _vscroll(clicks, x=None, y=None):\n _moveTo(x, y)\n clicks = int(clicks)\n for _ in range(abs(clicks)): # <------------------------------------\n scrollWheelEvent = Quartz.CGEventCreateScrollWheelEvent(\n None, # no source\n 0, # units <------------------------------------------------\n 1, # wheelCount (number of dimensions)\n 1 if clicks >= 0 else -1) # vertical movement <--------------\n Quartz.CGEventPost(Quartz.kCGHIDEventTap, scrollWheelEvent)\nRun Code Online (Sandbox Code Playgroud)\n\n如果您不愿意编辑源代码本身,您可以直接在代码中使用这些函数,无需使用 pyautogui。只需pyobjc安装(如果您使用 pyautogui,无论如何您都会拥有),删除_moveTo(x, y)关键字参数,并使用以下导入:
from Quartz.CoreGraphics import CGEventCreateScrollWheelEvent, CGEventPost, kCGHIDEventTap
我意识到这个答案有点晚了,但我来寻找这个问题的答案并看到了你的问题;当我解决这个问题时,我想我应该分享知识。
\n| 归档时间: |
|
| 查看次数: |
6102 次 |
| 最近记录: |