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
相关产品推荐
相关产品推荐

