[英]With PyQt5, how to add drop shadow effect on the rectangle area of a layout
我正在尝试实现一个带有标题的图像网格,在 hover 上有一个阴影。 到目前为止,我所做的是在两个小部件上添加阴影(带有图像的 label 和带有标题的 label),但我想在包含它们的矩形区域上添加阴影。 它试图将它们放在另一个小部件上并将效果应用到这个小部件上,但它仍然适用于两个标签。 代码如下。
import sys, os
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
class App(QMainWindow):
def __init__(self):
super().__init__()
self.title = 'PyQt5 layout - pythonspot.com'
self.left = 100
self.top = 100
self.width = 800
self.height = 600
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
content_widget = QWidget()
self.setCentralWidget(content_widget)
self._lay = QGridLayout(content_widget)
self.shadow = QGraphicsDropShadowEffect(self)
self.shadow.setBlurRadius(5)
nb = 6
i = 0
for i in range(0, 12):
panel=QWidget()
vbox = QVBoxLayout()
pixmap = QPixmap(str(i+1)+"jpg")
pixmap = pixmap.scaled(100, 150, transformMode=Qt.SmoothTransformation)
img_label = QLabel(pixmap=pixmap)
vbox.addWidget(img_label)
txt_label = QLabel(str(i+1))
vbox.addWidget(txt_label)
vbox.addStretch(1)
panel.setLayout(vbox)
self._lay.addWidget(panel , int(i/nb), i%nb)
panel.installEventFilter(self)
i = i+1
self.show()
def eventFilter(self, object, event):
if event.type() == QEvent.Enter:
object.setGraphicsEffect(self.shadow)
self.shadow.setEnabled(True)
elif event.type() == QEvent.Leave:
print("Mouse is not over the label")
self.shadow.setEnabled(False)
return False
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = App()
sys.exit(app.exec_())
问题来自一个简单的 QWidget 通常不会自己绘制任何东西的事实:它只是一个透明的小部件。 如果您应用图形效果,它将是该小部件内部的结果。
解决方案是通过调用setAutoFillBackground(True)
来确保小部件不透明。
不幸的是,特别是在您的情况下,结果不会很好,因为您有很多其他小部件并且它们之间有一定的间距。 你最终会在一切背后都有阴影:
解决方案是在设置图形效果时调用raise_()
,以确保小部件实际上高于其他任何东西(显然,在其父级的兄弟姐妹和子孩子中)。
不幸的是 - 再次 - 这有一个小但重要的问题,与您的实现有关:第一次从一个小部件中删除效果,因为它设置在另一个小部件上,周围的小部件没有正确更新。
这主要是由于绘画引擎的优化和图形效果的实现。
为了避免这个问题,有两种可能:
enterEvent
上启用它:class App(QMainWindow):
def __init__(self):
# ...
for i in range(0, 12):
panel = QWidget()
effect = QGraphicsDropShadowEffect(panel, enabled=False, blurRadius=5)
panel.setGraphicsEffect(panel)
# ...
def eventFilter(self, obj, event):
if event.type() == QEvent.Enter and obj.graphicsEffect():
obj.graphicsEffect().setEnabled(True)
elif event.type() == QEvent.Leave and obj.graphicsEffect():
obj.graphicsEffect().setEnabled(False)
return super().eventFilter(obj, event)
update()
:class App(QMainWindow):
def __init__(self):
# ...
self.panels = []
for i in range(0, 12):
panel = QWidget()
self.panels.append(panel)
# ...
def eventFilter(self, obj, event):
if event.type() == QEvent.Enter:
obj.setGraphicsEffect(self.shadow)
self.shadow.setEnabled(True)
obj.raise_()
elif event.type() == QEvent.Leave:
obj.graphicsEffect().setEnabled(False)
rect = self.shadow.boundingRect().toRect()
rect.translate(obj.geometry().topLeft())
for other in self.panels:
if other != obj and other.geometry().intersects(rect):
other.update()
return super().eventFilter(obj, event)
PS: object
是 Python 的内置类型,不要把它当成变量。
self.shadow = QGraphicsDropShadowEffect(self)
self.shadow.setBlurRadius(15)
self.shadow.setXOffset(0)
self.shadow.setYOffset(0)
self.shadow.setColor(QColor(0, 0, 0, 150))
# add the shadow object to the frame
self.ui.topframe.raise_()
self.ui.topframe.setGraphicsEffect(self.shadow)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.