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

PySide2:带阴影效果的Widget上方组件被遮挡问题求助

问题:带阴影效果的Widget遮挡上层虚拟键盘

我正在为触摸屏应用开发自定义虚拟键盘(未使用PyQt自带虚拟键盘,因需自定义额外按钮与功能)。该键盘采用类结构,调用show_keyboard时绘制按钮,其父Widget背景透明度设为0.95,内部通过QVBoxLayout布局包含字符按钮行及功能按钮。

当前遇到的问题:将此键盘放在带阴影效果的Widget上方时,键盘主Widget会被该带阴影的Widget遮挡;移除阴影效果后显示恢复正常。


示例代码

from PyQt5.QtWidgets import (QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, 
                             QPushButton, QApplication, QSizePolicy)
from PyQt5.QtGui import QGuiApplication, QColor, QGraphicsDropShadowEffect
from PyQt5.QtCore import Qt, QSize, QRect

class MyMainWindow(QMainWindow):
    def __init__(self):
        super(MyMainWindow, self).__init__()

        central_widget = QWidget(self)
        central_layout = QVBoxLayout()
        central_widget.setLayout(central_layout)
        central_widget.layout().setAlignment(Qt.AlignBottom)

        self.setCentralWidget(central_widget)

        self.under_widget_with_shadow = QWidget()
        self.under_widget_with_shadow.setStyleSheet("background-color: gray")
        self.under_widget_with_shadow.setFixedSize(QSize(
            QGuiApplication.primaryScreen().size().width(),
            200
        ))
        # shadow effect
        under_widget_shadow_effect = QGraphicsDropShadowEffect(self)
        under_widget_shadow_effect.setBlurRadius(15)
        under_widget_shadow_effect.setOffset(-3, -3)
        under_widget_shadow_effect.setColor(QColor(200, 0, 0))
        under_widget_shadow_effect.setEnabled(True)
        self.under_widget_with_shadow.setGraphicsEffect(under_widget_shadow_effect)

        self.under_widget_without_shadow = QWidget()
        self.under_widget_without_shadow.setStyleSheet("background-color: gray")
        self.under_widget_without_shadow.setFixedSize(QSize(
            QGuiApplication.primaryScreen().size().width(),
            200,
        ))

        self.above_widget = QWidget(self)
        self.above_widget.setStyleSheet("background-color: lightgray")
        above_layout = QVBoxLayout()
        self.above_widget.setLayout(above_layout)
        self.above_widget.setGeometry(QRect(
            0, QGuiApplication.primaryScreen().size().height() - 500,
            QGuiApplication.primaryScreen().size().width(), 500,
        ))

        for char in ['A', 'B', 'C', 'D']:
            row_widget = QWidget()
            row_layout = QHBoxLayout()
            row_widget.setLayout(row_layout)
            for i in range(1, 12):
                btn = QPushButton()
                btn.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
                btn.setText(f"{char}{i}")
                row_layout.addWidget(btn)
            above_layout.addWidget(row_widget)

        central_layout.addWidget(self.under_widget_without_shadow)
        central_layout.addWidget(self.under_widget_with_shadow)


if __name__ == '__main__':
    app = QApplication([])
    window = MyMainWindow()
    window.showFullScreen()
    exit(app.exec_())

问题截图

BUG截图


解决方案

这个问题的核心原因是:QGraphicsEffect会改变Widget的绘制层级——给Widget添加阴影效果后,它会被转移到一个独立的绘制层,默认优先级高于未设置GraphicsEffect的上层Widget,哪怕上层Widget的几何位置在上方。

以下是三种可行的解决方法:

方法1:给上层键盘Widget添加空的GraphicsEffect

让键盘Widget也进入相同的绘制层级,确保z-order规则生效:

# 假设你的键盘主Widget是self.keyboard_widget
empty_effect = QGraphicsEffect()
self.keyboard_widget.setGraphicsEffect(empty_effect)

方法2:调整Widget父子关系并强制提升层级

将键盘Widget设为central_widget的子控件,而非主窗口直接子控件,再调用raise_()强制置于最上层:

# 修改键盘Widget的父控件
self.above_widget = QWidget(central_widget)
# 在完成所有布局设置后执行
self.above_widget.raise_()

方法3:替换透明度设置方式

若键盘父Widget的透明度是通过StyleSheet设置的,改用Qt原生半透明属性避免冲突:

self.keyboard_parent_widget.setAttribute(Qt.WA_TranslucentBackground)
self.keyboard_parent_widget.setStyleSheet("background-color: rgba(255,255,255, 95%)")

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 19:43:15