Python: 鼠标按下时计数,鼠标向上时停止

Python: Counting while mouse Down, stop when mouse Up

我正在尝试制作一个 python 脚本,它在按下鼠标按钮时从 0 开始计数。我的想法是使用 pyHook 在按下鼠标左键时进入一个函数,并在释放鼠标左键时退出该函数。我是 python 的新手,很抱歉解释不当。 一些伪代码:

import pyHook
import pythoncom

def termin():
    return None
def counter(tell):
    a=0
    while True:
        print a
        a+=1
        hm = pyHook.HookManager()
        hm.SubscribeMouseLeftUp(termin)

hm = pyHook.HookManager()
hm.SubscribeMouseLeftDown(counter)
hm.HookMouse()
pythoncom.PumpMessages()
hm.UnhookMouse()

此代码是我的一般想法,但我认为它不会起作用,因为 SubscribeMouseLeftUp 发生在离散时间。我正在寻找的可能是 运行 在某种线程或多处理模块中使用计数器函数和终止函数,并在一个函数中使用条件来终止另一个 运行ning 函数。但我不确定如何进行这项工作。

好的,所以我在 willpower 的评论后尝试了这个脚本:

import pyHook,time,pythoncom

def counter(go):
    for a in range(5):
        time.sleep(1)
        print a
    return True

hm=pyHook.HookManager()
hm.SubscribeMouseLeftDown(counter)
hm.HookMouse()
pythoncom.PumpMessages()
hm.UnhookMouse()

willpower2727 接受的答案是迄今为止我见过的最好的解决方案。在他使用线程发布他的解决方案之前,我编写了以下代码:

from multiprocessing import Process,Queue
import pyHook
import time
import pythoncom
import ctypes

def counter(tellerstate,q):
    while True:
        a=0
        tellerstate=q.get()
        if tellerstate==1:
            while True:
                a+=1
                print a
                tellerstate=q.get()
                if tellerstate==0:
                    break
        time.sleep(0.1)

def mousesignal(q):
    def OnDown(go):
        tellstate=1
        q.put(tellstate)
        return None

    def OnUp(go):
        tellstate=0
        q.put(tellstate)
        return None

    def terminate(go):
        if chr(go.Ascii)=='q' or chr(go.Ascii)=='Q':
            ctypes.windll.user32.PostQuitMessage(0)
            hm.UnhookKeyboard()
            hm.UnhookMouse()
            q.close()
            q.join_thread()
            process_counter.join()
            process_mousesignal.join() 
        return None

    hm=pyHook.HookManager()
    hm.KeyDown = terminate
    hm.MouseLeftDown = OnDown
    hm.MouseLeftUp = OnUp
    hm.HookMouse()
    hm.HookKeyboard()
    pythoncom.PumpMessages()

if __name__ == '__main__':
    tellerstate=0
    q=Queue()
    process_counter = Process(target=counter,args=(tellerstate,q))
    process_mousesignal = Process(target=mousesignal,args=(q,))
    process_mousesignal.start()
    process_counter.start()

我对这段代码的预期行为是计数器和鼠标信号函数应该 运行 作为单独的进程。在 mousesignal 过程中,我根据鼠标输入将 0 或 1 放入队列。计数器函数 运行 连续读取队列并使用 if 语句进入和退出此函数中的循环。这段代码根本不起作用,但我不明白为什么。

根据您提供的示例,您似乎想要计算按下鼠标按钮的秒数?您可以在不使用多线程的情况下执行此操作。以下示例将打印按下鼠标按钮的时间量:

import pyHook
import time
import pythoncom

global starttime
starttime = time.time()
global endtime
endtime = time.time()

def OnDown(go):
    global starttime
    starttime = time.time()
    return True

def OnUp(go):
    global starttime
    global endtime
    endtime = time.time()
    etime = endtime-starttime
    print(etime)
    return True

hm = pyHook.HookManager()
hm.MouseLeftDown = OnDown
hm.MouseLeftUp = OnUp
hm.HookMouse()
pythoncom.PumpMessages()

好的,我有一个在按住鼠标按钮时使用线程执行某些操作的示例。如果用户快速双击鼠标,此示例 breaks/gets 会卡住。它使用一个锁和一个线程,该线程仅在释放锁(由鼠标按下触发)时执行某些代码。

import time
import threading
import pyHook
import pythoncom

def DoThis(Cond):
    while True:
        with Cond: #calling "with" automatically calls acquire() on the lock
            print(time.time())
    print('stopping...')

global Cond
Cond = threading.Lock()#create a threading lock
Cond.acquire() #give the lock to the main thread

global t1
t1 = threading.Thread(target=DoThis,args=(Cond, )) #initialize the thread that does stuff while mouse button is down
t1.start() #start the thread, it won't do anything until mouse button is down

def OnDown(go):
    global Cond
    Cond.release() #allow the thread to acquire the lock
    print('Lock released')
    return True

def OnUp(go):
    global Cond
    Cond.acquire() #take the lock away from the thread
    print('Lock acquired')
    return True

hm = pyHook.HookManager()
hm.MouseLeftDown = OnDown
hm.MouseLeftUp = OnUp
hm.HookMouse()
pythoncom.PumpMessages()

使用线程的挑战在于它们只能启动一次,因此您不能在每次按下鼠标时调用 thread.start(),它只会在第一次运行。通过允许线程保持活动状态但不做任何事情(除了不断检查它是否应该),可以只在鼠标按下时执行一些代码。有一些更复杂的方法可以提高计算机的处理负载(可能使用线程条件而不是常规锁),但这是我的一般想法。