添加QGraphicsBlurEffect后QGraphicsView失效,该如何解决?
PyQt5中QGraphicsItem添加模糊效果后交互失效、显示异常问题
在PyQt5中使用QGraphicsView组件并创建自定义QGraphicsItem时,未添加效果前元素显示正常。但在自定义元素的祖父类GameDisplayedElement中添加以下模糊效果代码后:
blur = _QtWidgets.QGraphicsBlurEffect() blur.setBlurRadius(1.1) self.setGraphicsEffect(blur)
出现两个核心问题:
- 元素显示异常
- 所有元素无法移动、鼠标交互完全失效
尝试过调整模糊参数,问题依旧;直接给QGraphicsView添加模糊效果,仅在视图resize时生效,元素更新时无效果。
【编辑】修正所有元素的bounding rect后,显示问题有所改善,但动画、鼠标交互等问题仍未解决。
复现代码
替换代码中两个元素paint方法里的图片路径即可测试,添加模糊代码后鼠标无法移动、背景无法自适应窗口大小,移除则恢复正常:
from PyQt5 import QtWidgets as _QtWidgets, uic as _uic from PyQt5 import QtCore as _QtCore from PyQt5 import QtGui as _QtGui class GameWidget(_QtWidgets.QGraphicsView): def __init__(self): super().__init__() self._scene: _QtWidgets.QGraphicsScene = _QtWidgets.QGraphicsScene() self.setScene(self._scene) self._main_graphic = MainDisplayedElement() self._main_graphic.setZValue(-10) self._scene.addItem(self._main_graphic) self._mouse = MouseDisplayedElement() self._mouse.set_size(40) self._mouse.setZValue(1000) self._scene.addItem(self._mouse) self.setMouseTracking(True) self.setInteractive(True) self.setVerticalScrollBarPolicy(_QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) self.setHorizontalScrollBarPolicy(_QtCore.Qt.ScrollBarPolicy.ScrollBarAlwaysOff) def onShow(self): self.resizeEvent() def resizeEvent(self, event = None) -> None: w, h = self.width() - 2, self.height() - 2 self.setSceneRect(-w / 2, -h / 2, w, h) self._main_graphic.set_rect(-w / 2, -h / 2, w, h) def mouseMoveEvent(self, event: _QtGui.QMouseEvent) -> None: super().mouseMoveEvent(event) position: _QtCore.QPointF = event.pos() position.setX(int(position.x() - self.width() / 2)) position.setY(int(position.y() - self.height() / 2)) event.ignore() x, y = position.x(), position.y() self._mouse.set_position(x, y) self._scene.update() class GameDisplayedElement(_QtWidgets.QGraphicsObject): def __init__(self, x: int, y: int, width: int, height: int, parent = None): super().__init__(parent) self._width: int = width self._height: int = height self._x: int = x self._y: int = y self.setAcceptHoverEvents(True) self.setAcceptedMouseButtons(_QtCore.Qt.MouseButton.AllButtons) # 模糊效果代码 blur = _QtWidgets.QGraphicsBlurEffect() blur.setBlurRadius(1.1) blur.setBlurHints(_QtWidgets.QGraphicsBlurEffect.BlurHint.QualityHint) self.setGraphicsEffect(blur) def paint(self, painter: _QtGui.QPainter, options: _QtWidgets.QStyleOptionGraphicsItem, widget: _QtWidgets.QWidget) -> None: pass def boundingRect(self) -> _QtCore.QRectF: x = self._x - self._width / 2 y = self._y - self._height / 2 return _QtCore.QRectF(int(x), int(y), int(self._width), int(self._height)) class MainDisplayedElement(GameDisplayedElement): def __init__(self, parent=None): super().__init__(0, 0, 0, 0) self._size = 150 self.setAcceptHoverEvents(False) self.setAcceptedMouseButtons(_QtCore.Qt.MouseButton.NoButton) def paint(self, painter: _QtGui.QPainter, options: _QtWidgets.QStyleOptionGraphicsItem, widget: _QtWidgets.QWidget) -> None: a = open("./any_image.png", "rb") data = a.read() a.close() image = _QtGui.QImage.fromData(data) # 替换为任意QImage x = 0 while x - self._size <= self._width / 2: y = 0 while y - self._size <= self._height / 2: painter.drawImage(_QtCore.QRectF(x, y, self._size, self._size), image) painter.drawImage(_QtCore.QRectF(-x-self._size, y, self._size, self._size), image) painter.drawImage(_QtCore.QRectF(x, -y-self._size, self._size, self._size), image) painter.drawImage(_QtCore.QRectF(-x-self._size, -y-self._size, self._size, self._size), image) y += self._size x += self._size def set_rect(self, x: float, y: float, w: float, h: float) -> None: self._x = 0 self._y = 0 self._width = w self._height = h class MouseDisplayedElement(GameDisplayedElement): def __init__(self, parent = None): super().__init__(0, 0, 50, 50, parent) self.setAcceptHoverEvents(False) self.setAcceptedMouseButtons(_QtCore.Qt.MouseButton.NoButton) def paint(self, painter: _QtGui.QPainter, options: _QtWidgets.QStyleOptionGraphicsItem, widget: _QtWidgets.QWidget) -> None: a = open("./any_image.png", "rb") data = a.read() a.close() image = _QtGui.QImage.fromData(data) # 替换为任意QImage painter.drawImage(_QtCore.QRectF(self._x, self._y, self._width, self._height), image) def set_size(self, size: int) -> None: self._width, self._height = size, size def hoverMoveEvent(self, event: _QtGui.QHoverEvent) -> None: event.ignore() def mousePressEvent(self, event): event.ignore() def set_position(self, x: int, y: int) -> None: self._x = x self._y = y app = _QtWidgets.QApplication(['']) widg = GameWidget() widg.show() app.exec()
环境信息
- Python 3.10.12
- PyQt5 及 Qt 5.15.3
- 运行环境:x86-64 架构的 Ubuntu 22.04 LTS
内容的提问来源于stack exchange,提问作者Kaki In
相关产品推荐
相关产品推荐

