我正在尝试制作一个项目,我想在我的 QSplashScreen 后面放置阴影。有没有办法做到这一点?
我搜索了一下,QGraphicsDropShadowEffect 没有用。
我正在尝试制作一个项目,我想在我的 QSplashScreen 后面放置阴影。有没有办法做到这一点?
我搜索了一下,QGraphicsDropShadowEffect 没有用。
阴影效果通常是操作系统的责任。
对于那些效果不可用的系统,您可以创建“虚拟”光栅化阴影,但有一些缺点:
moveEvent()
仅在移动完成时发送),阴影效果会显示一些伪影;这是显示阴影效果的 QSplashScreen 的可能重新实现。诀窍是创建一个临时的 QGraphicsScene 并添加一个应用了 QGraphicsDropShadowEffect 的 QGraphicsRectItem。
class SplashTest(QtWidgets.QSplashScreen):
_shadowSize = 8
shadowCache = None
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.setWindowFlags(QtCore.Qt.SplashScreen)
self.desktopPixmap = QtWidgets.QApplication.primaryScreen().grabWindow(0)
@QtCore.pyqtProperty(int)
def shadowSize(self):
return self._shadowSize
@shadowSize.setter
def shadowSize(self, shadowSize):
if shadowSize == self._shadowSize:
return
self._shadowSize = shadowSize
if self.shadowCache is None:
self.shadowCache = {}
else:
self.shadowCache.clear()
self.repaint()
def setShadowSize(self, shadowSize):
self.shadowSize = shadowSize
def setPixmap(self, pixmap):
self.shadowCache.clear()
super().setPixmap(pixmap)
size = QtCore.QSize(pixmap.width() + self.shadowSize, pixmap.height() + self.shadowSize)
self.setFixedSize(size)
if self.isVisible():
self.repaint()
def drawShadow(self, event):
if not self.pixmap() or self.pixmap().isNull():
return
shadowCache = self.shadowCache.get((self.width(), self.height()))
if not shadowCache:
# create the shadow effect if it's not cached yet
self.shadowCache[(self.width(), self.height())] = shadowCache = QtGui.QPixmap(self.size())
shadowCache.fill(QtCore.Qt.transparent)
# create a virtual QGraphicsScene to paint onto
scene = QtWidgets.QGraphicsScene()
scene.setSceneRect(QtCore.QRectF(self.desktopPixmap.rect()))
# add a QGraphicsRectItem to the scene that will be used for the shadow
pmItem = scene.addRect(QtCore.QRectF(self.pixmap().rect()).translated(self.geometry().topLeft()))
pmItem.setPen(QtGui.QPen(QtCore.Qt.NoPen))
pmItem.setBrush(QtGui.QBrush(QtCore.Qt.white))
offset = QtCore.QPoint(self.shadowSize / 2, self.shadowSize / 2)
effect = QtWidgets.QGraphicsDropShadowEffect(blurRadius=self.shadowSize, offset=offset)
pmItem.setGraphicsEffect(effect)
pmPainter = QtGui.QPainter(shadowCache)
pmPainter.setRenderHints(pmPainter.Antialiasing)
scene.render(pmPainter, QtCore.QRectF(self.rect()), pmItem.sceneBoundingRect().adjusted(0, 0, self.shadowSize, self.shadowSize))
pmPainter.end()
qp = QtGui.QPainter(self)
# draw the background taken from the root window
qp.drawPixmap(event.rect(), self.desktopPixmap, event.rect().translated(self.pos()))
# draw the shadow
qp.drawPixmap(0, 0, shadowCache)
def event(self, event):
if event.type() == QtCore.QEvent.Paint:
# intercept the Paint event in order to draw the shadow
self.drawShadow(event)
return super().event(event)
def moveEvent(self, event):
self.repaint()
def updateSplash():
# remember: globals should *ALWAYS* be avoided unless you *really* know how to
# use them; this is just for the purpose of this example
global loadingStatus
loadingStatus += 1
splashTest.showMessage('Loading: {}%'.format(loadingStatus))
if loadingStatus >= 100:
timer.stop()
QtCore.QTimer.singleShot(1000, lambda: splashTest.showMessage('Completed'))
QtCore.QTimer.singleShot(5000, splashTest.close)
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
splashTest = SplashTest(shadowSize=16)
splashTest.setPixmap(QtGui.QPixmap('splash.png'))
loadingStatus = 0
timer = QtCore.QTimer(interval=50, timeout=updateSplash)
timer.start()
splashTest.show()
sys.exit(app.exec_())