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

QFrame添加QDropShadowEffect致QWebEngineView冻结,如何解决?

问题

给QFrame添加QGraphicsDropShadowEffect后,其内部的QWebEngineView内容冻结,仅在界面失去焦点时才会更新;移除阴影效果后QWebEngineView恢复正常运行。

相关调用代码:

self.shadow_effect([self.ui.frame_render])

完整代码

Main.py

from PyQt5.QtWidgets import QMainWindow,QApplication,QVBoxLayout,QGraphicsDropShadowEffect,QWidget,QLabel
from PyQt5 import QtWebEngineWidgets
from PyQt5.QtCore import QUrl
from new_ui import Ui_MainWindow

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

        self.ui = Ui_MainWindow()
        self.ui.setupUi(self)
            
        frame_layout = QVBoxLayout()
        self.ui.frame_render.setLayout(frame_layout)

        frame_layout.addWidget(self.show_render())
        
        self.shadow_effect([self.ui.frame_render])
    
    def show_render(self):
        graphics_render = QtWebEngineWidgets.QWebEngineView(parent=self.ui.frame_render)
        graphics_render.setUrl(QUrl("https://www.youtube.com/"))
        return graphics_render
        
    def shadow_effect(self,widgets=[],blur=25,xofset=-2,yofset=-2):
        for w in widgets:
            effect = QGraphicsDropShadowEffect(w)
            effect.setBlurRadius(blur)
            effect.setXOffset(xofset)
            effect.setYOffset(yofset)
            w.setGraphicsEffect(effect)

app = QApplication([])
m = Main()
m.show()
app.exec_()

new_ui.py

from PyQt5 import QtCore, QtGui, QtWidgets

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(800, 600)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.stackedWidget = QtWidgets.QStackedWidget(self.centralwidget)
        self.stackedWidget.setGeometry(QtCore.QRect(40, 0, 741, 511))
        self.stackedWidget.setObjectName("stackedWidget")
        self.page = QtWidgets.QWidget()
        self.page.setObjectName("page")
        self.frame_render = QtWidgets.QFrame(self.page)
        self.frame_render.setGeometry(QtCore.QRect(250, 20, 381, 201))
        self.frame_render.setStyleSheet("background:white;\nborder-radius:50px;")
        self.frame_render.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_render.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_render.setObjectName("frame_render")
        self.frame_one = QtWidgets.QFrame(self.page)
        self.frame_one.setGeometry(QtCore.QRect(150, 300, 401, 211))
        self.frame_one.setStyleSheet("background:red;")
        self.frame_one.setFrameShape(QtWidgets.QFrame.StyledPanel)
        self.frame_one.setFrameShadow(QtWidgets.QFrame.Raised)
        self.frame_one.setObjectName("frame_one")
        self.label = QtWidgets.QLabel(self.page)
        self.label.setGeometry(QtCore.QRect(-40, 110, 631, 261))
        self.label.setText("")
        self.label.setPixmap(QtGui.QPixmap("../../Pictures/wallpapersden.com_windows-11-4k-black-blue-art_3840x2160.jpg"))
        self.label.setScaledContents(True)
        self.label.setObjectName("label")
        self.label.raise_()
        self.frame_render.raise_()
        self.frame_one.raise_()
        self.stackedWidget.addWidget(self.page)
        self.page_2 = QtWidgets.QWidget()
        self.page_2.setObjectName("page_2")
        self.stackedWidget.addWidget(self.page_2)
        MainWindow.setCentralWidget(self.centralwidget)
        self.menubar = QtWidgets.QMenuBar(MainWindow)
        self.menubar.setGeometry(QtCore.QRect(0, 0, 800, 21))
        self.menubar.setObjectName("menubar")
        MainWindow.setMenuBar(self.menubar)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        MainWindow.setStatusBar(self.statusbar)

        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "MainWindow"))
解决方案

问题根源是QGraphicsDropShadowEffect会强制父组件及其子组件使用软件渲染,而QWebEngineView依赖硬件加速实现实时刷新,两者冲突导致冻结。以下是三种可行解决方法:

方法一:阻断QWebEngineView的图形效果继承

修改show_render方法,给QWebEngineView单独设置空的图形效果,避免继承父Frame的阴影效果:

def show_render(self):
    graphics_render = QtWebEngineWidgets.QWebEngineView(parent=self.ui.frame_render)
    graphics_render.setUrl(QUrl("https://www.youtube.com/"))
    # 禁用父组件的图形效果传递
    graphics_render.setGraphicsEffect(None)
    return graphics_render

方法二:使用嵌套Frame隔离阴影效果

在外层Frame添加阴影,内部用一个子Frame承载QWebEngineView,避免阴影直接作用于WebView:

def __init__(self):
    super(QMainWindow,self).__init__()
    self.ui = Ui_MainWindow()
    self.ui.setupUi(self)

    # 创建内部承载内容的Frame
    content_frame = QFrame(self.ui.frame_render)
    content_frame.setStyleSheet("background:white; border-radius:50px;")
    content_frame.setFrameShape(QtWidgets.QFrame.StyledPanel)
    content_frame.setFrameShadow(QtWidgets.QFrame.Raised)

    # 给外层Frame设置布局
    outer_layout = QVBoxLayout(self.ui.frame_render)
    outer_layout.setContentsMargins(0,0,0,0)  # 消除间距,保持圆角一致性
    outer_layout.addWidget(content_frame)

    # 给内部Frame设置布局并添加WebView
    inner_layout = QVBoxLayout(content_frame)
    inner_layout.addWidget(self.show_render())

    # 仅给外层Frame添加阴影效果
    self.shadow_effect([self.ui.frame_render])

方法三:强制WebEngine使用软件渲染(备选)

如果上述方法无效,可以关闭WebEngine的硬件加速,强制使用软件渲染。在创建QApplication之前添加以下代码:

# 关闭WebEngine硬件加速
QtWebEngineWidgets.QWebEngineSettings.globalSettings().setAttribute(
    QtWebEngineWidgets.QWebEngineSettings.Accelerated2dCanvasEnabled, False
)
QtWebEngineWidgets.QWebEngineSettings.globalSettings().setAttribute(
    QtWebEngineWidgets.QWebEngineSettings.WebGLEnabled, False
)

app = QApplication([])
m = Main()
m.show()
app.exec_()

注意:此方法会降低页面渲染性能,仅在其他方案不可行时使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 20:15:22