问题描述在正文开头,望不吝赐教🙏
#这是一个简略的程序,在gui程序里面建立一个线程运行pyhook程序,用来检测鼠标动作。程序能运行,但是很快就会卡死。希望碰到过类似问题的大神给出一个可行的建议。试过将线程放到类的外面能正常运行,但是控制线程和传递参数不方便(才疏学浅)。#pyhook.py
import PyHook3 as pyHook
import pythoncom
class mouse():
def __init__(self):
super().__init__()
#监听键盘事件
def on_key_down(self, event):
# self.lock.acquire()
if event.Key == 'Escape':
win32api.PostQuitMessage()#退出监听循环
return True
#监听鼠标事件
def on_mouse_event(self,event):
if event.MessageName == 'mouse left down':
print("单击")
return True
def run(self,):
self.hm = pyHook.HookManager()#创建一个钩子管理对象
self.hm.MouseAll = self.on_mouse_event
self.hm.KeyDown = self.on_key_down
self.hm.HookMouse()
self.hm.HookKeyboard()
pythoncom.PumpMessages()
#gui.py
from tkinter import *
import threading
import mouse_pyhook
class gui(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry('500x500')
self.title('GUI')
td = threading.Thread(target=self.mouse_click)
td.daemon = True
td.start()
# self.mainloop()
def mouse_click(self):
mp = mouse_pyhook.mouse()
mp.run()
if __name__ == '__main__':
app = gui()
app.mainloop()
你好!看起来你的程序在运行过程中卡死了,这可能与线程的使用不当有关。在Python中,tkinter库是单线程的,所以在使用多线程时需要小心处理。
我注意到你在gui.py中创建了一个Thread对象来运行mouse_click函数。然而,在Python中,tkinter窗口只能在主线程(main thread)中运行。所以,你的mouse_click函数会导致tkinter窗口和pyHook程序在不同的线程中运行,这可能会导致一些问题。
为了解决这个问题,你可以将pyHook程序放在gui类中,并利用after函数来定期检查鼠标事件,而不是使用线程。
下面是修改后的代码:
import PyHook3 as pyHook
import pythoncom
from tkinter import *
class gui(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry('500x500')
self.title('GUI')
self.hm = pyHook.HookManager()# 创建一个钩子管理对象
self.hm.MouseAll = self.on_mouse_event
self.hm.KeyDown = self.on_key_down
self.hm.HookMouse()
self.hm.HookKeyboard()
self.after(100, self.check_events)
# 监听键盘事件
def on_key_down(self, event):
if event.Key == 'Escape':
win32api.PostQuitMessage()# 退出监听循环
return True
# 监听鼠标事件
def on_mouse_event(self,event):
if event.MessageName == 'mouse left down':
print("单击")
return True
def check_events(self):
pythoncom.PumpWaitingMessages()
self.after(100, self.check_events)
if __name__ == '__main__':
app = gui()
app.mainloop()
这样,你的鼠标事件监测程序将在主线程中运行,而不会导致程序卡死。每100毫秒,鼠标事件将被检查一次。
希望这个解决方案对你有帮助!如果还有其他问题,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 什么是钩子管理对象? FishC 发表于 2024-3-14 14:52
你好!看起来你的程序在运行过程中卡死了,这可能与线程的使用不当有关。在Python中,tkinter库是单线程的 ...
感谢大神的回答,这样看起来是没有问题的,另外还有一些疑问,我尝试过用pynput来检测鼠标键盘动作,像正文那样布局,在gui程序中创建线程运行,是能够正常运行的,没有出现卡死的现象,只是经常会被莫名其妙的杀死。因为pynput无法满足需求才转用pyhook。还有一点是会有多个gui程序要用到这个鼠标检测,放在一个文件里面方便一些。不知道有没有其他规避卡死的方法?{:5_93:} 一个CW的梦想 发表于 2024-03-15 10:07
感谢大神的回答,这样看起来是没有问题的,另外还有一 ...
你的问题很有启发性!在处理多个GUI程序共享鼠标检测的情况下,可以采用进程池或多线程池的方式来处理。这样可以确保每个GUI程序都在自己的进程或线程中独立运行,并且不会卡死。
首先,让我们来看看如何使用多线程池来处理多个GUI程序。你可以使用concurrent.futures模块中的ThreadPoolExecutor类来创建一个线程池,并在每个线程中运行相应的GUI程序。下面是示例代码:
import PyHook3 as pyHook
import pythoncom
from tkinter import *
from concurrent.futures import ThreadPoolExecutor
class gui(Tk):
def __init__(self):
Tk.__init__(self)
self.geometry('500x500')
self.title('GUI')
self.hm = pyHook.HookManager()# 创建一个钩子管理对象
self.hm.MouseAll = self.on_mouse_event
self.hm.KeyDown = self.on_key_down
self.hm.HookMouse()
self.hm.HookKeyboard()
self.after(100, self.check_events)
# 监听键盘事件
def on_key_down(self, event):
if event.Key == 'Escape':
win32api.PostQuitMessage()# 退出监听循环
return True
# 监听鼠标事件
def on_mouse_event(self, event):
if event.MessageName == 'mouse left down':
print("单击")
return True
def check_events(self):
pythoncom.PumpWaitingMessages()
self.after(100, self.check_events)
if __name__ == '__main__':
gui_pool = ThreadPoolExecutor(max_workers=5)# 创建一个包含5个线程的线程池
for i in range(5):# 创建5个GUI程序
gui_pool.submit(gui().mainloop)
gui_pool.shutdown(wait=True)
在这个例子中,我们创建了一个包含5个线程的线程池(可以根据实际情况调整线程数量),然后使用submit方法将每个GUI程序的mainloop函数提交到线程池中运行。通过这种方式,你就可以同时运行多个GUI程序,并共享鼠标检测功能。
如果你更喜欢使用进程池来处理多个GUI程序,可以使用multiprocessing模块中的Pool类。原理类似,只是将ThreadPoolExecutor替换为Pool即可。
希望这个解决方案能够满足你的需求,并且避免卡死和被意外杀死的问题!如有其他问题,请继续提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 清風 发表于 2024-3-14 21:06
什么是钩子管理对象?
网络释义:钩子函数是一种回调函数,它允许我们在程序执行的特定点上注入自定义的代码。 在Python中,钩子函数通常用于拦截事件、修改数据或扩展功能。 通过使用钩子函数,我们可以在不修改源代码的情况下改变程序的行为。 一个CW的梦想 发表于 2024-03-15 10:10
网络释义:钩子函数是一种回调函数,它允许我们在程序 ...
钩子函数确实是一种非常有用的编程技术。通过使用钩子函数,我们可以在程序执行的特定点上插入自定义的代码,这样就能够拦截事件、修改数据或扩展功能,而无需修改原始代码。钩子函数通常被用于各种场景,包括图形界面编程、网络编程和系统编程等。
在Python中,钩子函数通常与特定的库或框架一起使用。例如,在图形界面编程中,你可以使用钩子函数来拦截鼠标点击事件或键盘按键事件,并在事件发生时执行自定义的代码。在网络编程中,钩子函数可以用于拦截和解析收到的网络数据,或者用于在发送网络请求之前执行一些预处理操作。在系统编程中,钩子函数可以用于监视文件或进程的变化,并在变化发生时触发相应的操作。
总而言之,钩子函数是一种强大的机制,可以让我们在不修改原始代码的情况下对程序进行定制和扩展。通过合理地使用钩子函数,我们可以更加灵活地处理各种编程任务。希望这个解释对你有所帮助!如还有其他问题,请继续提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。 一个CW的梦想 发表于 2024-3-15 10:10
网络释义:钩子函数是一种回调函数,它允许我们在程序执行的特定点上注入自定义的代码。 在Python中,钩 ...
好的 谢谢 FishC 发表于 2024-3-15 10:08
你的问题很有启发性!在处理多个GUI程序共享鼠标检测的情况下,可以采用进程池或多线程池的方式来处理 ...
感谢大神的回复,问题已经解决。将100毫秒延长到1000毫秒后完美运行,卡死的原因应该是电脑性能不足。后面看看能不能将检测程序独立出来。再次感谢。 一个CW的梦想 发表于 2024-03-15 14:45
感谢大神的回复,问题已经解决。将100毫秒延长到1000 ...
非常高兴能帮助你解决问题!确实,卡死问题有时候可能与电脑性能有关。将检测程序独立出来也是个不错的想法。你可以将鼠标检测程序编写成一个独立的模块,然后在需要使用它的地方导入并调用相应的函数或方法。这样做可以使代码更加模块化和可重用。如果你需要在多个GUI程序中使用相同的鼠标检测功能,可以将鼠标检测程序封装为一个类。下面是一个示例:import PyHook3 as pyHookimport pythoncomclass MouseDetector: def __init__(self): self.hm = pyHook.HookManager() self.hm.MouseAll = self.on_mouse_event self.hm.KeyDown = self.on_key_down self.hm.HookMouse() self.hm.HookKeyboard() def on_key_down(self, event): if event.Key == 'Escape': win32api.PostQuitMessage() return True def on_mouse_event(self, event): if event.MessageName == 'mouse left down': print("单击") return True def start_detection(self): pythoncom.PumpMessages()# 在其他文件中使用鼠标检测程序md = MouseDetector()md.start_detection()通过这种方式,你可以将鼠标检测程序独立出来,并在需要的地方导入并调用start_detection方法。这样可以更好地组织代码,并且方便在多个GUI程序中重用鼠标检测功能。希望这个建议对你有帮助!如果还有其他问题,请随时提问。
以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
页:
[1]