[英]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.