Pyqt实现无边框窗口拖动以及窗口大小改变

本文实例为大家分享了Pyqt实现无边框窗口拖动及大小改变的具体代码,供大家参考,具体内容如下

做个记录,绘制边框阴影可以忽略这里不是主要

根据网上某位仁兄Qt的实现转过来的大笑,上完整代码

# coding:utf-8
from PyQt4.Qt import *
import sys 

PADDING=4
sys.setrecursionlimit(10000)
class ShadowWidget(QWidget):
  def __init__(self,parent=None):
    super(ShadowWidget,self).__init__(parent)
    self.setWindowFlags(Qt.FramelessWindowHint|Qt.WindowSystemMenuHint)
    self.setAttribute(Qt.WA_TranslucentBackground)
    self.SHADOW_WIDTH=0  #边框距离
    self.isLeftPressDown = False #鼠标左键是否按下
    self.dragPosition=0   #拖动时坐标
    self.Numbers = self.enum(UP=0, DOWN=1, LEFT=2, RIGHT=3, LEFTTOP=4, LEFTBOTTOM=5, RIGHTBOTTOM=6, RIGHTTOP=7, NONE=8) #枚举参数
    self.setMinimumHeight(500) #窗体最小高度
    self.setMinimumWidth(1000) #窗体最小宽度
    self.dir=self.Numbers.NONE #初始鼠标状态
    self.setMouseTracking(True) 

  #绘制边框阴影
  def drawShadow(self,painter):
    #绘制左上角、左下角、右上角、右下角、上、下、左、右边框
    self.pixmaps=QStringList()
    self.pixmaps.append(QString("./img/border/left_top.png"))
    self.pixmaps.append(QString("./img/border/left_bottom.png"))
    self.pixmaps.append(QString("./img/border/right_top.png"))
    self.pixmaps.append(QString("./img/border/right_bottom.png"))
    self.pixmaps.append(QString("./img/border/top_mid.png"))
    self.pixmaps.append(QString("./img/border/bottom_mid.png"))
    self.pixmaps.append(QString("./img/border/left_mid.png"))
    self.pixmaps.append(QString("./img/border/right_mid.png"))
    painter.drawPixmap(0, 0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[0]))  #左上角
    painter.drawPixmap(self.width()-self.SHADOW_WIDTH, 0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[2]))  #右上角
    painter.drawPixmap(0,self.height()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[1]))  #左下角
    painter.drawPixmap(self.width()-self.SHADOW_WIDTH, self.height()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[3])) #右下角
    painter.drawPixmap(0, self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH, QPixmap(self.pixmaps[6]).scaled(self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH)) #左
    painter.drawPixmap(self.width()-self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.SHADOW_WIDTH, self.height()-2*self.SHADOW_WIDTH, QPixmap(self.pixmaps[7]).scaled(self.SHADOW_WIDTH, self.height()- 2*self.SHADOW_WIDTH)) #右
    painter.drawPixmap(self.SHADOW_WIDTH, 0, self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[4]).scaled(self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH)) #上
    painter.drawPixmap(self.SHADOW_WIDTH, self.height()-self.SHADOW_WIDTH, self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH, QPixmap(self.pixmaps[5]).scaled(self.width()-2*self.SHADOW_WIDTH, self.SHADOW_WIDTH))  #下 

  #枚举参数
  def enum(self,**enums):
    return type('Enum', (), enums) 

  def region(self,cursorGlobalPoint):
    #获取窗体在屏幕上的位置区域,tl为topleft点,rb为rightbottom点
    rect = self.rect()
    tl = self.mapToGlobal(rect.topLeft())
    rb = self.mapToGlobal(rect.bottomRight()) 

    x = cursorGlobalPoint.x()
    y = cursorGlobalPoint.y() 

    if(tl.x() + PADDING >= x and tl.x() <= x and tl.y() + PADDING >= y and tl.y() <= y):
      #左上角
      self.dir = self.Numbers.LEFTTOP
      self.setCursor(QCursor(Qt.SizeFDiagCursor))  #设置鼠标形状
    elif(x >= rb.x() - PADDING and x <= rb.x() and y >= rb.y() - PADDING and y <= rb.y()):
      #右下角
      self.dir = self.Numbers.RIGHTBOTTOM
      self.setCursor(QCursor(Qt.SizeFDiagCursor))
    elif(x <= tl.x() + PADDING and x >= tl.x() and y >= rb.y() - PADDING and y <= rb.y()):
      #左下角
      self.dir = self.Numbers.LEFTBOTTOM
      self.setCursor(QCursor(Qt.SizeBDiagCursor))
    elif(x <= rb.x() and x >= rb.x() - PADDING and y >= tl.y() and y <= tl.y() + PADDING):
      #右上角
      self.dir = self.Numbers.RIGHTTOP
      self.setCursor(QCursor(Qt.SizeBDiagCursor))
    elif(x <= tl.x() + PADDING and x >= tl.x()):
      #左边
      self.dir = self.Numbers.LEFT
      self.setCursor(QCursor(Qt.SizeHorCursor))
    elif( x <= rb.x() and x >= rb.x() - PADDING):
      #右边 

      self.dir = self.Numbers.RIGHT
      self.setCursor(QCursor(Qt.SizeHorCursor))
    elif(y >= tl.y() and y <= tl.y() + PADDING):
      #上边
      self.dir = self.Numbers.UP
      self.setCursor(QCursor(Qt.SizeVerCursor))
    elif(y <= rb.y() and y >= rb.y() - PADDING):
      #下边
      self.dir = self.Numbers.DOWN
      self.setCursor(QCursor(Qt.SizeVerCursor))
    else:
      #默认
      self.dir = self.Numbers.NONE
      self.setCursor(QCursor(Qt.ArrowCursor)) 

  def mouseReleaseEvent(self,event):
    if(event.button() == Qt.LeftButton):
      self.isLeftPressDown = False
      if(self.dir != self.Numbers.NONE):
        self.releaseMouse()
        self.setCursor(QCursor(Qt.ArrowCursor)) 

  def mousePressEvent(self,event):
    if(event.button()==Qt.LeftButton):
      self.isLeftPressDown=True
      if(self.dir != self.Numbers.NONE):
        self.mouseGrabber()
      else:
        self.dragPosition = event.globalPos() - self.frameGeometry().topLeft() 

  def mouseMoveEvent(self,event):
    gloPoint = event.globalPos()
    rect = self.rect()
    tl = self.mapToGlobal(rect.topLeft())
    rb = self.mapToGlobal(rect.bottomRight()) 

    if(not self.isLeftPressDown):
      self.region(gloPoint)
    else:
      if(self.dir != self.Numbers.NONE):
        rmove=QRect(tl, rb)
        if(self.dir==self.Numbers.LEFT):
          if(rb.x() - gloPoint.x() <= self.minimumWidth()):
            rmove.setX(tl.x())
          else:
            rmove.setX(gloPoint.x())
        elif(self.dir==self.Numbers.RIGHT):
          print u"youbian"
          rmove.setWidth(gloPoint.x() - tl.x())
        elif(self.dir==self.Numbers.UP):
          if(rb.y() - gloPoint.y() <= self.minimumHeight()):
            rmove.setY(tl.y())
          else:
            rmove.setY(gloPoint.y())
        elif(self.dir==self.Numbers.DOWN):
          rmove.setHeight(gloPoint.y() - tl.y())
        elif(self.dir==self.Numbers.LEFTTOP):
          if(rb.x() - gloPoint.x() <= self.minimumWidth()):
            rmove.setX(tl.x())
          else:
            rmove.setX(gloPoint.x())
          if(rb.y() - gloPoint.y() <= self.minimumHeight()):
            rmove.setY(tl.y())
          else:
            rmove.setY(gloPoint.y())
        elif(self.dir==self.Numbers.RIGHTTOP):
          rmove.setWidth(gloPoint.x() - tl.x())
          rmove.setY(gloPoint.y())
        elif(self.dir==self.Numbers.LEFTBOTTOM):
          rmove.setX(gloPoint.x())
          rmove.setHeight(gloPoint.y() - tl.y())
        elif(self.dir==self.Numbers.RIGHTBOTTOM):
          rmove.setWidth(gloPoint.x() - tl.x())
          rmove.setHeight(gloPoint.y() - tl.y())
        else:
          pass
        self.setGeometry(rmove)
      else:
        self.move(event.globalPos() - self.dragPosition)
        event.accept() 

if __name__ == '__main__':
  app = QApplication(sys.argv)
  shadow = ShadowWidget()
  shadow.show()
  sys.exit(app.exec_()) 

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • python应用程序在windows下不出现cmd窗口的办法

    python写的GTK程序,会有这样一个怪现象,本来在cmd下用 python xxx.py 启动,还好好的,但是用py2exe编译以后,再用subprocess调用命令行程序的时候,就发现一个黑乎乎的cmd窗口跳出来了,特别难看,要消除它其实也还比较容易,但是要使用startupinfo这个windows only的参数,以下代码是linux和windows通用的例子: 复制代码 代码如下: if os.name == 'nt':    startupinfo = subprocess.STA

  • python的tkinter布局之简单的聊天窗口实现方法

    本文实例展示了一个python的tkinter布局的简单聊天窗口.分享给大家供大家参考之用.具体方法如下: 该实例展示的是一个简单的聊天窗口,可以实现下方输入聊天内容,点击发送,可以增加到上方聊天记录列表中.现在只是"单机"版. 右侧预留了空位可以放点儿其它东西.感兴趣的读者可以进一步做成socket双方互聊. 以下是功能代码部分: from Tkinter import * import datetime import time root = Tk() root.title(unic

  • python实现根据窗口标题调用窗口的方法

    本文实例讲述了python实现根据窗口标题调用窗口的方法.分享给大家供大家参考.具体分析如下: 当你知道一个windows窗口的标题后,可以用下面的代码调用窗口,甚至向窗口内写入内容. #-*-coding:utf-8-*- import win32gui,win32con #下面的是窗口的标题名称,这样是一定错的,但在控制台就可以正常使用 #写在文件里要用U编码 a=u"jb51.net" dlg=win32gui.FindWindow(None,a) //用控件的ID取得控件的句柄

  • PyQt5每天必学之QSplitter实现窗口分隔

    QSplitter使用户可以通过拖动子面板的边界控制子面板的大小.在我们的例子中,我们使用了两个QSplitter 对三个QFrame 控件进行了分隔. #!/usr/bin/python3 # -*- coding: utf-8 -*- """ PyQt5 教程 这个例子说明如何使用QSplitter部件. 作者:我的世界你曾经来过 博客:http://blog.csdn.net/weiaitaowang 最后编辑:2016年8月4日 """

  • PyQT实现多窗口切换

    最近做个软件,用PyQT写的,在实现菜单栏点击弹出新窗口的时候严重被卡壳,发现用WxPython的思想和方式来做完全无法实现.PyQT的中文资料实在是太少了.看了点英文资料和QT的资料,逆推PyQT的实现方法,总算搞定.下面是一个小demo. 主界面的代码如下所示: # -*- coding: utf-8 -*- from PyQt4 import QtCore, QtGui from dialog1 import Dialog1 from dialog2 import Dialog2 impo

  • PyQt5每天必学之创建窗口居中效果

    本文实例为大家分享了PyQt5如何能够创建在桌面屏幕上居中窗口的具体代码,供大家参考,具体内容如下 下面的脚本说明我们如何能够创建在桌面屏幕上居中的窗口. #!/usr/bin/python3 # -*- coding: utf-8 -*- """ PyQt5 教程 这个程序是将一个窗口显示在屏幕的中心. 作者:我的世界你曾经来过 博客:http://blog.csdn.net/weiaitaowang 最后编辑:2016年7月30日 """ i

  • python3+PyQt5+Qt Designer实现堆叠窗口部件

    本文是对<Python Qt GUI快速编程>的第9章的堆叠窗口例子Vehicle Rental用Python3+PyQt5+Qt Designer进行改写. 第一部分无借用Qt Designer,完全用代码实现. 第二部分则借用Qt Designer,快速实现. 第一部分: import sys from PyQt5.QtCore import (Qt) from PyQt5.QtWidgets import (QApplication, QComboBox, QDialog, QDialo

  • PyQt5实现无边框窗口的标题拖动和窗口缩放

    网上找了半天都找不到好用的PyQt5无边框窗口的实现,借鉴部分前辈的窗口拖放代码,自己实现了一下无边框窗口,问题可能还有一点,慢慢改吧 先做个笔记 py文件 #!/usr/bin/env python #-*- coding:utf-8 -*- from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QVBoxLayout from PyQt5.QtCore import Qt, QPoint from PyQt5.QtGui impo

  • Python实现遍历windows所有窗口并输出窗口标题的方法

    本文实例讲述了Python实现遍历windows所有窗口并输出窗口标题的方法.分享给大家供大家参考.具体如下: 这段代码可以让Python遍历当前Windows下所有运行程序的窗口,并获得运行窗口的标题输出 #! /usr/bin/env python # -*- coding: utf-8 -*- from win32gui import * titles = set() def foo(hwnd,mouse): #去掉下面这句就所有都输出了,但是我不需要那么多 if IsWindow(hwn

  • PyQt5每天必学之关闭窗口

    最简单的关闭一个窗口的方法是点击标题栏上的 x 标志.但是,在下面的例子中,我们将展示如何通过编程来控制关闭窗口.我们将使用PyQt5的信号/槽. 以下是我们在例子中使用到的 QPushButton 控件的构造方法. QPushButton(string text, QWidget parent = None) text 参数是在按钮上显示的文本.parent 要将按钮控件放在哪里.在下面的例子中我们要将按钮控件放到 QWidget里.一个应用程序的窗口控件可以形成一个分层结构,在这个层次,大多

随机推荐