You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PyQt6实现Windows带标题栏透明内容窗口(可拖拽调整)

问题描述

需在Windows平台使用PyQt6开发一款屏幕覆盖窗口,具体需求:

  • 基于PyQt6开发
  • 具备常规窗口外观,标题栏与边框完全不透明
  • 支持常规拖拽移动和调整大小操作
  • 窗口内容区域完全透明(禁止使用setWindowOpacity(.8)这类整体透明方式)
  • 仅适配Windows平台

尝试多种方案未达预期:

  • 启用FramelessWindowHint后可实现内容透明,但丢失系统自带的拖拽和调整大小功能
  • 添加自定义调整手柄后,窗口调整时出现抖动
  • 未启用无框属性时,窗口背景始终为黑色

解决方案

核心思路:保留Windows系统自带的标题栏和边框(避免自定义交互的抖动问题),通过PyQt6的WA_TranslucentBackground属性配合样式表/窗口掩码实现内容区域完全透明。

方案一:样式表实现内容透明(简单易用)

import sys
from PyQt6.QtWidgets import QMainWindow, QApplication, QWidget, QVBoxLayout
from PyQt6.QtCore import Qt, QRect
from PyQt6.QtGui import QPainter, QColor

class ScreenOverlayWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        # 基础窗口设置
        self.setWindowTitle("屏幕元素捕获窗口")
        self.setGeometry(300, 300, 400, 300)
        # 启用半透明背景属性(Windows平台下生效)
        self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
        # 可选:设置窗口始终置顶
        self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.Window)

        # 中心部件(内容区域)
        central_widget = QWidget()
        self.setCentralWidget(central_widget)
        layout = QVBoxLayout(central_widget)
        
        # 设置内容区域完全透明
        central_widget.setStyleSheet("background-color: rgba(0, 0, 0, 0);")

    def paintEvent(self, event):
        # 可选:绘制内容区域边框,方便可视化窗口范围
        painter = QPainter(self)
        painter.setPen(QColor(0, 128, 255))
        title_bar_height = self.style().pixelMetric(self.style().PixelMetric.PM_TitleBarHeight)
        border_rect = QRect(0, title_bar_height, self.width(), self.height() - title_bar_height)
        painter.drawRect(border_rect)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ScreenOverlayWindow()
    window.show()
    sys.exit(app.exec())

关键说明

  1. 保留系统交互:未使用FramelessWindowHint,完全依赖Windows系统自带的标题栏拖拽、边框调整大小功能,无抖动问题。
  2. 内容透明实现:通过WA_TranslucentBackground属性配合中心部件的透明样式表,实现内容区域完全透明,标题栏和边框保持系统默认的不透明状态。
  3. 可视化边框:paintEvent中绘制的边框仅用于直观显示窗口范围,可根据需求删除。

方案二:窗口掩码实现精确透明控制

如果需要更精确地控制透明区域(比如仅保留标题栏和四周边框),可使用窗口掩码:

import sys
from PyQt6.QtWidgets import QMainWindow, QApplication, QWidget
from PyQt6.QtCore import Qt, QRegion, QRect
from PyQt6.QtGui import QPainter, QColor

class ScreenOverlayWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("屏幕元素捕获窗口")
        self.setGeometry(300, 300, 400, 300)
        self.setWindowFlags(Qt.WindowType.WindowStaysOnTopHint | Qt.WindowType.Window)
        self.update_window_mask()

    def update_window_mask(self):
        # 获取系统标题栏高度和边框宽度
        title_bar_height = self.style().pixelMetric(self.style().PixelMetric.PM_TitleBarHeight)
        border_width = 2  # 适配Windows系统边框宽度,可根据实际调整

        # 创建窗口掩码:仅保留标题栏和四周边框,中间内容区域透明
        region = QRegion(0, 0, self.width(), title_bar_height)  # 标题栏区域
        # 左侧边框
        region += QRegion(0, title_bar_height, border_width, self.height() - title_bar_height)
        # 右侧边框
        region += QRegion(self.width() - border_width, title_bar_height, border_width, self.height() - title_bar_height)
        # 底部边框
        region += QRegion(border_width, self.height() - border_width, self.width() - 2*border_width, border_width)
        
        self.setMask(region)

    def resizeEvent(self, event):
        # 窗口大小变化时更新掩码
        self.update_window_mask()
        super().resizeEvent(event)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = ScreenOverlayWindow()
    window.show()
    sys.exit(app.exec())

关键说明

  1. 精确透明控制:通过QRegion定义窗口可见区域,仅保留标题栏和边框,中间内容区域完全透明。
  2. 动态更新掩码:窗口大小变化时自动更新掩码,确保边框始终正常显示。

内容的提问来源于stack exchange,提问作者rrz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 21:38:12