pyQt5设计无边框窗口

from PyQt5.QtWidgets import QWidget, QLabel, QPushButton, QVBoxLayoutfrom PyQt5.QtCore import Qt, QPointfrom PyQt5.QtGui import QFont, QCursor

class QTitleLabel(QLabel):    """    新建标题栏标签类    """    def __init__(self, *args):        super(QTitleLabel, self).__init__(*args)        self.setAlignment(Qt.AlignLeft | Qt.AlignVCenter)        self.setFixedHeight(30)

class QTitleButton(QPushButton):    """    新建标题栏按钮类    """    def __init__(self, *args):        super(QTitleButton, self).__init__(*args)        self.setFont(QFont("Webdings")) # 特殊字体以不借助图片实现最小化最大化和关闭按钮        self.setFixedWidth(40)

class QUnFrameWindow(QWidget):    """    无边框窗口类    """    def __init__(self):        super(QUnFrameWindow, self).__init__(None, Qt.FramelessWindowHint) # 设置为顶级窗口,无边框        self._padding = 5 # 设置边界宽度为5        self.initTitleLabel() # 安放标题栏标签        self.setWindowTitle = self._setTitleText(self.setWindowTitle) # 用装饰器将设置WindowTitle名字函数共享到标题栏标签上        self.setWindowTitle("UnFrameWindow")        self.initLayout() # 设置框架布局        self.setMinimumWidth(250)        self.setMouseTracking(True) # 设置widget鼠标跟踪        self.initDrag() # 设置鼠标跟踪判断默认值

    def initDrag(self):        # 设置鼠标跟踪判断扳机默认值        self._move_drag = False        self._corner_drag = False        self._bottom_drag = False        self._right_drag = False

    def initTitleLabel(self):        # 安放标题栏标签        self._TitleLabel = QTitleLabel(self)        self._TitleLabel.setMouseTracking(True) # 设置标题栏标签鼠标跟踪(如不设,则标题栏内在widget上层,无法实现跟踪)        self._TitleLabel.setIndent(10) # 设置标题栏文本缩进        self._TitleLabel.move(0, 0) # 标题栏安放到左上角

    def initLayout(self):        # 设置框架布局        self._MainLayout = QVBoxLayout()        self._MainLayout.setSpacing(0)        self._MainLayout.addWidget(QLabel(), Qt.AlignLeft) # 顶一个QLabel在竖放框架第一行,以免正常内容挤占到标题范围里        self._MainLayout.addStretch()        self.setLayout(self._MainLayout)

    def addLayout(self, QLayout):        # 给widget定义一个addLayout函数,以实现往竖放框架的正确内容区内嵌套Layout框架        self._MainLayout.addLayout(QLayout)

    def _setTitleText(self, func):        # 设置标题栏标签的装饰器函数        def wrapper(*args):            self._TitleLabel.setText(*args)            return func(*args)        return wrapper

    def setTitleAlignment(self, alignment):        # 给widget定义一个setTitleAlignment函数,以实现标题栏标签的对齐方式设定        self._TitleLabel.setAlignment(alignment | Qt.AlignVCenter)

    def setCloseButton(self, bool):        # 给widget定义一个setCloseButton函数,为True时设置一个关闭按钮        if bool == True:            self._CloseButton = QTitleButton(b‘\xef\x81\xb2‘.decode("utf-8"), self)            self._CloseButton.setObjectName("CloseButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式            self._CloseButton.setToolTip("关闭窗口")            self._CloseButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)            self._CloseButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度            self._CloseButton.clicked.connect(self.close) # 按钮信号连接到关闭窗口的槽函数

    def setMinMaxButtons(self, bool):        # 给widget定义一个setMinMaxButtons函数,为True时设置一组最小化最大化按钮        if bool == True:            self._MinimumButton = QTitleButton(b‘\xef\x80\xb0‘.decode("utf-8"), self)            self._MinimumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式            self._MinimumButton.setToolTip("最小化")            self._MinimumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)            self._MinimumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度            self._MinimumButton.clicked.connect(self.showMinimized) # 按钮信号连接到最小化窗口的槽函数            self._MaximumButton = QTitleButton(b‘\xef\x80\xb1‘.decode("utf-8"), self)            self._MaximumButton.setObjectName("MinMaxButton") # 设置按钮的ObjectName以在qss样式表内定义不同的按钮样式            self._MaximumButton.setToolTip("最大化")            self._MaximumButton.setMouseTracking(True) # 设置按钮鼠标跟踪(如不设,则按钮在widget上层,无法实现跟踪)            self._MaximumButton.setFixedHeight(self._TitleLabel.height()) # 设置按钮高度为标题栏高度            self._MaximumButton.clicked.connect(self._changeNormalButton) # 按钮信号连接切换到恢复窗口大小按钮函数

    def _changeNormalButton(self):        # 切换到恢复窗口大小按钮        try:            self.showMaximized() # 先实现窗口最大化            self._MaximumButton.setText(b‘\xef\x80\xb2‘.decode("utf-8")) # 更改按钮文本            self._MaximumButton.setToolTip("恢复") # 更改按钮提示            self._MaximumButton.disconnect() # 断开原本的信号槽连接            self._MaximumButton.clicked.connect(self._changeMaxButton) # 重新连接信号和槽        except:            pass

    def _changeMaxButton(self):        # 切换到最大化按钮        try:            self.showNormal()            self._MaximumButton.setText(b‘\xef\x80\xb1‘.decode("utf-8"))            self._MaximumButton.setToolTip("最大化")            self._MaximumButton.disconnect()            self._MaximumButton.clicked.connect(self._changeNormalButton)        except:            pass

    def resizeEvent(self, QResizeEvent):        # 自定义窗口调整大小事件        self._TitleLabel.setFixedWidth(self.width()) # 将标题标签始终设为窗口宽度        # 分别移动三个按钮到正确的位置        try:            self._CloseButton.move(self.width() - self._CloseButton.width(), 0)        except:            pass        try:            self._MinimumButton.move(self.width() - (self._CloseButton.width() + 1) * 3 + 1, 0)        except:            pass        try:            self._MaximumButton.move(self.width() - (self._CloseButton.width() + 1) * 2 + 1, 0)        except:            pass        # 重新调整边界范围以备实现鼠标拖放缩放窗口大小,采用三个列表生成式生成三个列表        self._right_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1)                           for y in range(1, self.height() - self._padding)]        self._bottom_rect = [QPoint(x, y) for x in range(1, self.width() - self._padding)                         for y in range(self.height() - self._padding, self.height() + 1)]        self._corner_rect = [QPoint(x, y) for x in range(self.width() - self._padding, self.width() + 1)                                    for y in range(self.height() - self._padding, self.height() + 1)]

    def mousePressEvent(self, event):        # 重写鼠标点击的事件        if (event.button() == Qt.LeftButton) and (event.pos() in self._corner_rect):            # 鼠标左键点击右下角边界区域            self._corner_drag = True            event.accept()        elif (event.button() == Qt.LeftButton) and (event.pos() in self._right_rect):            # 鼠标左键点击右侧边界区域            self._right_drag = True            event.accept()        elif (event.button() == Qt.LeftButton) and (event.pos() in self._bottom_rect):            # 鼠标左键点击下侧边界区域            self._bottom_drag = True            event.accept()        elif (event.button() == Qt.LeftButton) and (event.y() < self._TitleLabel.height()):            # 鼠标左键点击标题栏区域            self._move_drag = True            self.move_DragPosition = event.globalPos() - self.pos()            event.accept()

    def mouseMoveEvent(self, QMouseEvent):        # 判断鼠标位置切换鼠标手势        if QMouseEvent.pos() in self._corner_rect:            self.setCursor(Qt.SizeFDiagCursor)        elif QMouseEvent.pos() in self._bottom_rect:            self.setCursor(Qt.SizeVerCursor)        elif QMouseEvent.pos() in self._right_rect:            self.setCursor(Qt.SizeHorCursor)        else:            self.setCursor(Qt.ArrowCursor)        # 当鼠标左键点击不放及满足点击区域的要求后,分别实现不同的窗口调整        # 没有定义左方和上方相关的5个方向,主要是因为实现起来不难,但是效果很差,拖放的时候窗口闪烁,再研究研究是否有更好的实现        if Qt.LeftButton and self._right_drag:            # 右侧调整窗口宽度            self.resize(QMouseEvent.pos().x(), self.height())            QMouseEvent.accept()        elif Qt.LeftButton and self._bottom_drag:            # 下侧调整窗口高度            self.resize(self.width(), QMouseEvent.pos().y())            QMouseEvent.accept()        elif Qt.LeftButton and self._corner_drag:            # 右下角同时调整高度和宽度            self.resize(QMouseEvent.pos().x(), QMouseEvent.pos().y())            QMouseEvent.accept()        elif Qt.LeftButton and self._move_drag:            # 标题栏拖放窗口位置            self.move(QMouseEvent.globalPos() - self.move_DragPosition)            QMouseEvent.accept()

    def mouseReleaseEvent(self, QMouseEvent):        # 鼠标释放后,各扳机复位        self._move_drag = False        self._corner_drag = False        self._bottom_drag = False        self._right_drag = False

if __name__ == "__main__":    from PyQt5.QtWidgets import QApplication    import sys    app = QApplication(sys.argv)    app.setStyleSheet(open("./UnFrameStyle.qss").read())    window = QUnFrameWindow()    window.setCloseButton(True)    window.setMinMaxButtons(True)    window.show()    sys.exit(app.exec_())执行上面.py文件需要将下面的.qss文件与.py文件放在同一文件夹

QTitleLabel{
background-color: Gainsboro;
font: 100 10pt;
}

/**********Button**********/
QTitleButton{
background-color: rgba(255, 255, 255, 0);
color: black;
border: 0px;
font: 100 10pt;
}
QTitleButton#MinMaxButton:hover{
background-color: #D0D0D1;
border: 0px;
font: 100 10pt;
}
QTitleButton#CloseButton:hover{
background-color: #D32424;
color: white;
border: 0px;
font: 100 10pt;
}

转:https://blog.csdn.net/qq_38528972/article/details/78573591



原文地址:https://www.cnblogs.com/jieliu8080/p/10512779.html

时间: 2024-07-30 10:19:17

pyQt5设计无边框窗口的相关文章

PYQT设计无边框窗体

#UI.py,通过UI设计师制作后直接转换为UI.py脚本 # -*- coding: utf-8 -*-from PyQt4 import QtCore, QtGui try:    _fromUtf8 = QtCore.QString.fromUtf8except AttributeError:    _fromUtf8 = lambda s: s class Ui_Form(object):    def setupUi(self, Form):        Form.setObject

141107●Winform拖动无边框窗口、播放音频、启动外部exe程序

鼠标拖动无边框窗口 1. //鼠标拖动 Point downpoint = new Point(); //事件,鼠标按下,获取当前坐标 private void panel1_MouseDown(object sender, MouseEventArgs e) { downpoint.X = -e.X; downpoint.Y = -e.Y; } //事件,鼠标移动,赋值新坐标 private void panel1_MouseMove(object sender, MouseEventArgs

【Qt编程】无边框窗口的拖动

在上一篇文章中,我们讲述了如何进行无边框窗口的缩放与拖动,而在一些情况下,我们的窗口只需要进行拖动也不需要改变其大小,比如:QQ的登录窗口.本来在上一篇文章中已经讲述了如何进行窗口的拖动,但是却与窗口的缩放相关的程序放在一起,下面专门单独分离出来. 窗口的拖放只涉及到鼠标事件:按下操作.释放操作和移动操作,因此只需要重写这三个函数.由于程序比较简单,并且注释也比较详细,就不作过多介绍.新建一个基类为QWidget的Qt Gui应用程序,只需修改widget.h和widget.cpp文件如下: 1

【Qt编程】无边框窗口的缩放与拖动

在现在,绝大多数软件都向着简洁,时尚发展.就拿有道的单词本和我做的单词本来说,绝大多数用户肯定喜欢我所做的单词本(就单单界面,关于颜色搭配和布局问题,大家就不要在意了). 有道的单词本: 我所做的单词本: 很明显,两者的主要区别就是周围的边框问题.你可以对比QQ以前的版本和这几年的版本,就会发现都倾向于下面这种窗口模式.下面我们就说说如何用Qt实现无边框窗口的缩放与拖动. 对于无边框窗口的拖动其实很简单,其基本思想是,在鼠标移动前后记录鼠标的坐标,然后将窗口移动这两个坐标之差的距离即可,具体实现

winform无边框窗口拖动

无边框的窗口想拖动,只需要在置顶的容器上添加对应的mousedown 和 mousemove 事件就可以实现了.代码如下: 1 //拖动窗口 2 private Point mPoint = new Point(); 3 4 private void panel1_MouseDown(object sender, MouseEventArgs e) 5 { 6 mPoint.X = e.X; 7 mPoint.Y = e.Y; 8 } 9 10 private void panel1_Mouse

Winform 无边框窗口移动自定义边框粗细颜色

1 using System; 2 using System.Collections.Generic; 3 using System.ComponentModel; 4 using System.Data; 5 using System.Drawing; 6 using System.Linq; 7 using System.Text; 8 using System.Threading.Tasks; 9 using System.Windows.Forms; 10 11 namespace Wi

QT界面开发-(特效)无边框窗口+背景图片

转发自邵发<C/C++系列教程>Qt界面开发 https://chuanke.baidu.com/4509752-209060.html 1.自己用代码画界面 2.用Laber控件放一张背景大图 hpp 1 #include <QtWidgets> 2 3 4 private: 5 virtual void paintEvent(QPaintEvent *event); 6 7 virtual void mouseMoveEvent(QMouseEvent * event); 8

重写mouseEvent 事件 怎么实现自定义的无边框窗口移动

void MainWindow::mousePressEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) { m_Drag = true; m_DragPosition = event->globalPos() - this->pos(); event->accept(); } } void MainWindow::mouseMoveEvent(QMouseEvent *event) { if (m_

Delphi中拖动无边框窗口的5种方法

1.MouseMove事件中加入: // ReleaseCapture;// Perform(WM_SYSCOMMAND, $F017 , 0); 2.MouseDown事件中加入: // POSTMESSAGE(Self.Handle,WM_LBUTTONUP,0,0);// POSTMESSAGE(Self.Handle,274,61458,0); 3.MouseDown事件中加入: // ReleaseCapture;// Perform(WM_SYSCOMMAND, $F012, 0);