PyQt4中无边框窗口的移动(拖动)
搜索了很多文章,有关于Qt的C++版本无边框窗口的拖动:
例如这篇《Qt 无标题无边框程序的拖动和改变大小》http://blog.csdn.net/kfbyj/article/details/9284923
其中主要讲到两种方法,但是PyQt(Qt的Python版本)实现就没有找到,以下主要讲PyQt4中的实现
方法1:在QWidget/QDialog中重写mousePressEvent和mouseMoveEvent方法,利用move方法移动窗口
这种方法相对简单,但是缺陷在于会在鼠标按下移动过程中,整个窗口是实时移动,实时重绘,移动快了会出现重影(由于多次重绘)。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31 |
#!/usr/bin/python #-*-coding:utf-8-*- from PyQt4.QtGui import
* from PyQt4.Qt import
* from PyQt4.QtCore import
* class AboutUsDialog(QDialog): def __init__(self, parent=None): super(AboutUsDialog, self).__init__(parent) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) def mousePressEvent(self, event): if
event.button() == Qt.LeftButton: self.dragPosition = event.globalPos() - self.frameGeometry().topLeft() QApplication.postEvent(self, QEvent(174)) event.accept() def mouseMoveEvent(self, event): if
event.buttons() == Qt.LeftButton: self.move(event.globalPos() - self.dragPosition) event.accept() if __name__ == ‘__main__‘ : import
sys app = QApplication(sys.argv) aboutus = AboutUsDialog() aboutus.show() sys. exit (app.exec_()) |
而正常的windows窗体移动都会在鼠标按下后呈现虚线边框,只移动虚线边框,鼠标放开后才会将窗体真正移动
方法二:使用winEvent处理消息,将鼠标点击窗体内的事件WM_NCHITTEST,模拟成为点击原生标题栏的事件HTCAPTION。在无边框的窗口中增加isInTitle方法来判断鼠标位置是否在窗口中自定义的标题栏中。
此方法可以实现鼠标在自定义栏中的鼠标拖动,但是暂时不支持鼠标双击进行最大化切换和还原。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 |
#!/usr/bin/python #-*-coding:utf-8-*- from PyQt4.QtGui import
* from PyQt4.Qt import
* from PyQt4.QtCore import
* class AboutUsDialog(QWidget): def __init__(self, parent=None): super(AboutUsDialog, self).__init__(parent) self.setWindowFlags(Qt.FramelessWindowHint | Qt.Dialog) def isInTitle(self, xPos, yPos): return
yPos < 30 class MyApplication(QApplication): def __init__(self, args): super(MyApplication, self).__init__(args) def GET_X_LPARAM(self, param): #define LOWORD(l) ((WORD)((DWORD_PTR)(l) & 0xffff)) #define HIWORD(l) ((WORD)((DWORD_PTR)(l) >> 16)) #define GET_X_LPARAM(lp) ((int)(short)LOWORD(lp)) #define GET_Y_LPARAM(lp) ((int)(short)HIWORD(lp)) return
param & 0xffff def GET_Y_LPARAM(self, param): return
param >> 16 def winEventFilter(self, msg): if
msg.message == 0x84: #WM_NCHITTEST form = self.activeWindow() if
form: xPos = self.GET_X_LPARAM(msg.lParam) - form.frameGeometry().x() yPos = self.GET_Y_LPARAM(msg.lParam) - form.frameGeometry().y() # 鼠标在窗体自定义标题范围内,窗体自定义一个isInTitle的方法判断 # if yPos < 30 and xPos < 456: if
not form.isMaximized() and hasattr(form, ‘isInTitle‘ ) and form.isInTitle(xPos, yPos): return
True, 0x2 #HTCAPTION return
False, 0 if __name__ == ‘__main__‘ : import
sys app = MyApplication(sys.argv) aboutus = AboutUsDialog() aboutus.showNormal() sys. exit (app.exec_()) |
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。