我在 PyQt5 上使用
QGraphicsView
小部件,并创建了一些自定义 QGraphicsItems
。
当我添加这三行时:
blur = _QtWidgets.QGraphicsBlurEffect()
blur.setBlurRadius(1.1)
self.setGraphicsEffect(blur)
在我的自定义项目的“祖父母”中,我得到了这个:
此外,似乎没有任何东西在移动,我的鼠标没有移动,甲板没有做任何事情......
我找到了这篇文章,但它对我没有帮助,我作为参数传递的每个提示都产生了相同的结果。
我还尝试直接在 QGraphicsView 上传递模糊效果,但它仅在 QGraphicsView 更改(调整大小,...)时起作用,并且不适用于任何项目更新。
我该怎么办?
感谢您的帮助!
正确设置每个元素的边界矩形后,我得到了这个:
但我仍然遇到动画不起作用、鼠标不动等问题......
这里有一个重现它的小方法,仅包含背景和鼠标:
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)
# Here are the three lines...
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) # use any QImage you want
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) # use any QImage you want
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()
在两个项目的
paint
方法中更改该项目的路径进行测试。您会看到鼠标不随着这三条线移动,并且在没有它们的情况下移动,因为背景不会随着树线调整大小,并且在没有它们的情况下成功调整大小。
关于我的环境,我使用的是Python3.10.12,带有PyQt5和qt5.15.3(通过qtdiag命令给出);我使用的是带有 Ubuntu22.04 LTS 的 x86-64 计算机。
根据@musicamante(谢谢你),我唯一缺少的是在调整大小和替换函数中调用
prepareGeometryChange
方法:
def set_size(self, size: int) -> None:
self._width, self._height = size, size
self.prepareGeometryChange() # this will make the graphics item update again
但是也有一种可能是在我绘制图像时仅将模糊效果应用于图像(在我的情况下效果更好),可以在这个答案中找到:
def applyEffectToImage(self, src: _QtGui.QImage, effect: _QtWidgets.QGraphicsEffect, extent: int = 0) -> _QtGui.QImage:
scene = _QtWidgets.QGraphicsScene()
item = _QtWidgets.QGraphicsPixmapItem()
item.setPixmap(_QtGui.QPixmap.fromImage(src))
item.setGraphicsEffect(effect)
scene.addItem(item)
res = _QtGui.QImage(src.size() + _QtCore.QSize(extent*2, extent*2), _QtGui.QImage.Format.Format_ARGB32)
res.fill(_QtCore.Qt.GlobalColor.transparent)
ptr = _QtGui.QPainter(res)
scene.render(ptr, _QtCore.QRectF(), _QtCore.QRectF( -extent, -extent, src.width()+extent*2, src.height()+extent*2 ) )
ptr.end()
return res
这样,我可以绘制所有图形,并且仅将模糊应用于需要它的图像。