记录一下 QT 中异形窗口的创建。

主要标志

在 QWidget 中,通过给窗口设置特定的标志,可以将窗口设置为不同的形状,比如让窗口无标题,或者直接让主窗口透明

setWindowFlags(Qt.FramelessWindowHint)      # 去掉标题栏
setMask(QPixmap(img).mask())                # 设置图片透明的地方为穿透
setAttribute(Qt.WA_TranslucentBackground)   # 设置窗口透明

当为窗口设置了使用图片作为 Mask 遮罩后,Qt.FramelessWindowHint 标志会自动指定。

实现示例

创建一个基本窗口
# Author: Mirror
import sys
from PySide2.QtWidgets import QApplication, QWidget
from PySide2.QtCore import Qt
from PySide2.QtGui import QPixmap

class MainWindow(QWidget):
    def __init__(self,):
        super().__init__()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = MainWindow()  # 实例化窗口小部件
    form.show()
    sys.exit(app.exec_())

窗口效果
原窗口.png

设置窗口标志
self.setWindowFlags(Qt.FramelessWindowHint)  # 去掉标题

窗口效果
窗口会变成一块没有标题的白板
无标题窗口.png

设置窗口Mask
self.starticon = QPixmap(r"ImagePath")
self.setMask(self.starticon.mask())

窗口效果窗口会根据你使用的 Mask 图片进行裁剪
设置Mask的窗口.png

窗口重写事件

由于窗口被设置为无标题窗口后,鼠标不能对窗口进行移动,因此,我们还需要将窗口的鼠标事件进行重写。
完整代码:

# !/user/bin/python37
# -*- coding: utf-8 -*-
# Author:Mirror
# Time: 2022/03/26
# ================================
import sys
from PySide2.QtWidgets import QApplication,QWidget
from PySide2.QtCore import Qt
from PySide2.QtGui import QPixmap, QCursor

class MainWindow(QWidget):
    def __init__(self,):
        super().__init__()
        self.setWindowFlags(Qt.FramelessWindowHint)  # 去掉标题(还有一些别的窗口类型选择,请自行查阅)
        self.starticon = QPixmap(r"E:\Python_study\startLauncher\Icon\startBackgroundMask.svg")
        self.setMask(self.starticon.mask())

    # 鼠标按下
    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self.m_drag = True  # 鼠标按下或抬起标志位
            self.m_DragPosition = event.globalPos() - self.pos()  # 当前单击点相对于窗口本身的坐标(只检测窗口中的点击)
            self.setCursor(QCursor(Qt.SizeAllCursor))  # 设置光标形状 小手抓取

        if event.button() == Qt.RightButton:  # 按下右键 取消左键按下,结束鼠标移动时间
            if self.m_drag == True:
                self.m_drag = False

    # 鼠标移动
    def mouseMoveEvent(self, QMouseEvent):
        if Qt.LeftButton and self.m_drag:
            # 当左键移动窗体修改偏移值
            self.move(QMouseEvent.globalPos() - self.m_DragPosition)

    # 鼠标抬起
    def mouseReleaseEvent(self, QMouseEvent):
        self.m_drag = False
        self.setCursor(QCursor(Qt.ArrowCursor))


if __name__ == "__main__":
    app = QApplication(sys.argv)
    form = MainWindow()
    form.show()
    sys.exit(app.exec_())

通过上面的代码,我们就可以获得一个可以被鼠标移动的异形窗口啦。