2016-11-20 3 views
1

Я пытаюсь создать скрипт python, который начинает отсчет с 0 при нажатии кнопки мыши. Моя идея - использовать pyHook для входа в функцию при нажатии левой кнопки мыши и выходе из функции при отпускании левой мыши. Я довольно новичок в python, поэтому сожалею о плохих объяснениях. Некоторые псевдокод: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 происходит в дискретном времени. То, что я ищу, возможно, запускает функцию счетчика и функцию termin в каком-то потоковом или многопроцессорном модуле и использует условия в одной функции для завершения другой выполняемой функции. Но я не уверен, как это сделать.

Хорошо, так что я попробовал этот сценарий после того, как комментарий 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 функции должен работать как отдельные процессы. В процессе mousesignal я помещаю либо 0, либо 1 в очередь на основе ввода мыши. Функция счетчика работает непрерывно и считывает очередь и использует операторы if для ввода и выхода из цикла в этой функции. Этот код не работает вообще, но я не могу понять, почему.

+0

Просто подскажите, вы можете попробовать получить рабочий пример программы pyhook, а затем попробовать и настроить в соответствии с вашими потребностями. Как только у вас будет рабочий пример, вам будет намного легче помочь. Я бы предложил этот пример в качестве возможного места для запуска: https://gordoncluster.wordpress.com/2013/09/12/logging-all-keyboard-input-with-python-pyhook/ – willpower2727

+0

Добавлен код рабочего счетчика. – mathiasxx94

+0

Вы заинтересованы в том, чтобы вычислить суммарное время, когда кнопка мыши не работает? Или какой-то другой показатель подсчета? – willpower2727

ответ

0

Ok У меня есть пример использования многопоточности, чтобы сделать что-то, пока кнопка мыши удерживается в нажатом положении. Этот пример ломается/застревает, если пользователь дважды быстро нажимает на мышь. Он использует блокировку и поток, который выполняет только определенный код при освобождении блокировки (запускается с помощью мыши).

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() каждый раз, когда мышь нажата, она будет работать только в первый раз. Предоставляя потоку оставаться в живых, но ничего не делать (за исключением постоянно проверять, следует ли это делать) позволяет использовать только код, когда мышь не работает. Есть несколько более сложных способов сделать это, что может улучшить загрузку на компьютере (возможно, используя условие потока вместо обычной блокировки), но это общая идея, которую я имел.

+0

Это кажется очень многообещающим, я очень ценю вашу помощь, время, чтобы полностью понять модуль потоковой передачи. Я обновил основную запись своей попыткой, используя многопроцессорную обработку, однако она не работает. Если вы хотите взглянуть на него, вы очень желанны. – mathiasxx94

0

На основании приведенного вами примера похоже, что вы хотите подсчитать количество секунд, в течение которых кнопка мыши не работает? Вы можете сделать это, не используя несколько потоков. В следующем примере будет печататься количество времени, кнопка мыши была нажата вниз для:

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() 
+0

Большое спасибо за силу воли. К сожалению, я, возможно, сформулировал свою просьбу с некоторой двусмысленностью. Предполагается, что программа выполняет операцию в цикле, пока нажата кнопка мыши, и я просто использовал подсчет в качестве примера. Причина, по которой я не могу думать о способе без многопроцессорности или потоковой передачи, заключается в том, что, насколько я знаю, программа перестает слушать входной сигнал мыши, когда он переходит в функцию[email protected] – mathiasxx94