用Python寫一個跟隨鼠標運動的自定義窗口


背景:因為項目需要,要開發一個在PC上運行的應用程序,生成一個跟隨鼠標運動的窗口,並且監聽鼠標的點擊事件,並在窗口上做相應的顯示。

平台:Win7 64位 + Python27 64位

支持庫:PyHook + PyQt5

 

  模塊的安裝這里就不多說了,網上有很多。需要注意的是,PyHook對Python3的支持不是很好,會出現卡死的問題, 還有PyQt5貌似只支持64位。廢話不多說了,開始造~

 

第一步:

  先用PyQt5生成一個自定義的窗口:

  

 1 #!usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 
 4 import sys
 5 from PyQt5.QtCore import *
 6 from PyQt5.QtGui import *
 7 from PyQt5.QtWidgets import *
 8 
 9 class newWindow(QWidget):
10     def __init__(self, parent=None):
11         super(newWindow, self).__init__(parent)
12         self.mypix()
13         self.setWindowFlags(Qt.FramelessWindowHint) #去除界面邊框
14         self.setWindowFlags(Qt.WindowStaysOnTopHint)#窗口顯示在屏幕最上方
15         self.setAttribute(Qt.WA_TranslucentBackground)#背景透明
16 
17     #顯示不規則圖片
18     def mypix(self):
19         self.update()
20         self.pix=QPixmap('./1.png','0',Qt.AvoidDither|Qt.ThresholdAlphaDither|Qt.ThresholdDither)
21         self.resize(self.pix.size())
22         self.setMask(self.pix.mask())
23         
24     def paintEvent(self, QPaintEvent):
25         painter=QPainter(self)
26         painter.drawPixmap(0,0,self.pix.width(),self.pix.height(),self.pix)    
27 
28 if __name__=="__main__":
29     app = QApplication(sys.argv)
30     
31     w = newWindow()
32     w.setWindowTitle('一個窗口')
33     w.show()
34     
35     sys.exit(app.exec_())

 

顯示效果如下:

窗口出來了,下一步救贖讓它跟隨着鼠標進行移動了

 

第二步  監聽鼠標事件

  

 1 #!usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 
 4 import pyHook
 5 import pythoncom
 6 
 7 class MouseListener():
 8 
 9     def __init__(self):
10         
11         #新建鈎子管理器
12         hookmanager = pyHook.HookManager()  
13         #注冊動作回調函數
14         hookmanager.MouseLeftDown = self.onMouseLeftDown 
15         hookmanager.MouseLeftUp = self.onMouseRelease
16         hookmanager.MouseMiddleDown = self.onMouseMiddleDown
17         hookmanager.MouseMiddleUp = self.onMouseRelease
18         hookmanager.MouseRightDown = self.onMouseRightDown
19         hookmanager.MouseRightUp = self.onMouseRelease
20         hookmanager.MouseMove = self.onMouseMove
21         #鈎取鼠標事件
22         hookmanager.HookMouse()
23         #推送window事件消息
24         pythoncom.PumpMessages()
25         
26         
27 
28     def onMouseLeftDown(self, event):
29         print("MouseLeft Down!")
30      
31         return True
32     
33     def onMouseMiddleDown(self, event):
34         print("MouseMiddle Down!")
35 
36         return True
37 
38     def onMouseRightDown(self, event):
39         print("MouseRight Down!")
40 
41         return True
42         
43     def onMouseRelease(self, event):
44         print("Button release!")
45         
46         return True
47 
48     def onMouseMove(self, event):
49         print("Mouse Move!")
50 
51         return True
52     
53 
54 if __name__=="__main__":
55     mouseListener = MouseListener()

 

結果如下:

 

 現在最后的問題就是如何結合這兩個程序了。

因為Qt界面本身是一個死循環,而監聽器里的pythoncom.PumpMessage()也是一個死循環。很自然的想法就是開啟多線程。

開啟多線程會出現兩個問題: 1、因為是死循環,關閉窗口之后,子線程還是在運行,無法關閉。正常手段無法關閉,只能強制關閉,

              但是還是會出現問題。

             2、可能是兩個死循環有影響的原因,當鼠標移動到窗口的時候會卡死。

感興趣的可以試試,代碼就不貼了,下面的寫解決辦法。

 

絞盡腦汁,頭發都掉了一斤還是解決不了!無意中發現去掉pythoncom.PumpMessages()這個語句,程序居然可以運行。哈哈,天不絕我!!!^-^

 

 1 #!usr/bin/env python
 2 #-*- coding:utf-8 -*-
 3 
 4 import pyHook
 5 import pythoncom
 6 
 7 import sys
 8 from PyQt5.QtCore import *
 9 from PyQt5.QtGui import *
10 from PyQt5.QtWidgets import *
11 
12 
13 class newWindow(QWidget):
14      def __init__(self, parent=None):
15          super(newWindow, self).__init__(parent)
16          self.mypix()
17          self.setWindowFlags(Qt.FramelessWindowHint) #去除界面邊框
18          self.setWindowFlags(Qt.WindowStaysOnTopHint)#窗口顯示在屏幕最上方
19          self.setAttribute(Qt.WA_TranslucentBackground)#背景透明
20          #新建鈎子管理器
21          self.hookmanager = pyHook.HookManager()
22          self.hookmanager.MouseMove = self.onMouseMove
23          #鈎取鼠標事件
24          self.hookmanager.HookMouse()
25  
26      #顯示不規則圖片
27      def mypix(self):
28          self.update()
29          self.pix=QPixmap('./1.png','0',Qt.AvoidDither|Qt.ThresholdAlphaDither|Qt.ThresholdDither)
30          self.resize(self.pix.size())
31          self.setMask(self.pix.mask())
32          
33      def paintEvent(self, QPaintEvent):
34          painter=QPainter(self)
35          painter.drawPixmap(0,0,self.pix.width(),self.pix.height(),self.pix)
36 
37 
38      def closeEvent(self, QEvent):
39         self.hookmanager.UnhookMouse()
40         sys.exit()
41 
42      def onMouseMove(self, event):
43         #print("Mouse Move!")
44         (x, y) = event.Position
45         self.move(x, y)
46         return True
47     
48 
49 if __name__=="__main__":
50     app = QApplication(sys.argv)
51      
52     w = newWindow()
53     w.setWindowTitle('一個窗口')
54     w.show()
55      
56     sys.exit(app.exec_())

OK,問題解決了,解釋這么簡單!(PS: 我的IDLE運行,關閉時會出現Runtime Error! 直接用命令行運行就不會出現這個問題了)

 

總結:猜測可能是Qt界面本身就是有類似於pythoncom.PumpMessages()這樣功能的語句,所以前面會出現鼠標移動到界面上就出現卡死的現象。

主要還是對底層不太了解,折騰了許久。

 

 

 

 

 

 

 

 

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM