• PyQt4中无边框窗口的移动(拖动)


    搜索了很多文章,有关于Qt的C++版本无边框窗口的拖动:

    例如这篇《Qt 无标题无边框程序的拖动和改变大小》http://blog.csdn.net/kfbyj/article/details/9284923

    其中主要讲到两种方法,但是PyQt(Qt的Python版本)实现就没有找到,以下主要讲PyQt4中的实现

    方法1:在QWidget/QDialog中重写mousePressEvent和mouseMoveEvent方法,利用move方法移动窗口

    这种方法相对简单,但是缺陷在于会在鼠标按下移动过程中,整个窗口是实时移动,实时重绘,移动快了会出现重影(由于多次重绘)。

    #!/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方法来判断鼠标位置是否在窗口中自定义的标题栏中。

    此方法可以实现鼠标在自定义栏中的鼠标拖动,但是暂时不支持鼠标双击进行最大化切换和还原。

    #!/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_())    
  • 相关阅读:
    pyinstaller 打包后无法运行
    Android Uiautomator2 gradlew 坑
    JNDI 在 J2EE 中的角色
    23种设计模式
    Struts2工作原理
    SpringMVC工作原理
    堆内存设置
    安装和使用 memcached
    SQL面试题及答案
    30多条mysql数据库优化方法,千万级数据库记录查询轻松解决
  • 原文地址:https://www.cnblogs.com/anic/p/3542822.html
Copyright © 2020-2023  润新知