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

如何为PyQt5的QMenu设置Windows系统级柔和阴影而非默认阴影?

在PyQt5的QMenu中添加Windows系统级柔和阴影

要实现VS Code、Spotify这类应用的系统级柔和阴影,你需要调用Windows原生API(Dwmapi)来为无框窗口启用系统阴影,而非依赖Qt自带的生硬阴影效果。以下是具体实现方案:

实现步骤

  • 导入ctypes模块调用Windows的DwmSetWindowAttribute函数,该函数用于配置桌面窗口管理器(DWM)的窗口属性
  • 自定义QMenu子类,重写showEvent方法,在菜单显示时为其添加系统阴影和匹配的圆角效果
  • 移除原代码中的NoDropShadowWindowHint标志,保留FramelessWindowHint和WA_TranslucentBackground属性以支持自定义样式

修改后的完整代码

import sys
from PyQt5 import QtCore, QtWidgets
import ctypes
from ctypes import wintypes

# 初始化Windows DWM API
dwmapi = ctypes.WinDLL("dwmapi")

# DWM属性常量
DWMWCP_ROUND = 2  # Windows 11圆角样式
DWMSWA_WINDOW_CORNER_PREFERENCE = 33
DWMSWA_MICA_EFFECT = 1029  # 可选,启用Windows 11云母效果

class CustomMenu(QtWidgets.QMenu):
    def showEvent(self, event):
        super().showEvent(event)
        # 获取菜单窗口句柄
        hwnd = int(self.winId())
        
        # 设置窗口圆角,匹配样式表中的border-radius
        corner_preference = wintypes.DWORD(DWMWCP_ROUND)
        dwmapi.DwmSetWindowAttribute(
            wintypes.HWND(hwnd),
            wintypes.DWORD(DWMSWA_WINDOW_CORNER_PREFERENCE),
            ctypes.byref(corner_preference),
            ctypes.sizeof(corner_preference)
        )
        
        # 启用系统阴影(配合圆角自动生效)
        # 可选:启用云母效果增强视觉一致性
        mica_enabled = wintypes.DWORD(1)
        dwmapi.DwmSetWindowAttribute(
            wintypes.HWND(hwnd),
            wintypes.DWORD(DWMSWA_MICA_EFFECT),
            ctypes.byref(mica_enabled),
            ctypes.sizeof(mica_enabled)
        )

def main():
    app = QtWidgets.QApplication(sys.argv)
    win = QtWidgets.QMainWindow()

    app.setStyleSheet('''
        QMenu {
            background: #2b2b2b; 
            color: white;
            border-radius: 5px;
            border: 1px solid #3e3e3e;                    
        }
        QMenu::item {
            border-radius: 3px;
            padding: 4px 25px;
            margin: 2px 5px;
        }
        QMenu::item:selected {
            background: #353535;
        }
    ''')

    menubar = QtWidgets.QMenuBar()
    # 使用自定义菜单类替代默认QMenu
    settingsmenu = CustomMenu(menubar)

    settingsmenu.setTitle("Settings")
    settingsmenu.setWindowFlags(settingsmenu.windowFlags() | QtCore.Qt.FramelessWindowHint)
    # 移除NoDropShadowWindowHint,允许系统添加阴影
    settingsmenu.setAttribute(QtCore.Qt.WA_TranslucentBackground)

    run_on_start = QtWidgets.QAction(text="Run On Startup", checkable=True)   
    start_minimized = QtWidgets.QAction(text="Start Minimized", checkable=True)

    settingsmenu.addAction(run_on_start)
    settingsmenu.addAction(start_minimized)

    menubar.addAction(settingsmenu.menuAction())

    win.setMenuBar(menubar)
    win.resize(400, 300)
    win.show()
    sys.exit(app.exec_())

if __name__ == "__main__":
    main()

注意事项

  • 该方案仅支持Windows 10及以上系统,其中圆角和云母效果为Windows 11专属特性
  • 确保样式表中的border-radius与代码中设置的圆角样式匹配,避免视觉错位
  • 若不需要云母效果,可注释掉对应DwmSetWindowAttribute调用,仅保留圆角设置即可正常显示系统阴影

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 18:15:28