У меня есть этот код
import sys # +++
from PyQt5.QtCore import Qt, QUrl
from PyQt5.QtWidgets import QApplication, QWidget, QMainWindow, QVBoxLayout, QLabel
from PyQt5.QtQml import QQmlApplicationEngine
from PyQt5.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PyQt5 import QtCore, QtGui, QtWidgets
'''
from PySide2.QtCore import Qt, QUrl
from PySide2.QtWidgets import QApplication, QWidget, QMainWindow, QVBoxLayout, QLabel
from PySide2.QtQml import QQmlApplicationEngine
from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PySide2 import QtCore, QtGui, QtWidgets
'''
class BlurEffect(QtWidgets.QGraphicsBlurEffect):
effectRect = None
def setEffectRect(self, rect):
self.effectRect = rect
self.update()
def draw(self, qp):
if self.effectRect is None or self.effectRect.isNull():
# no valid effect rect to be used, use the default implementation
super().draw(qp)
print('bao')
else:
qp.save()
# clip the drawing so that it's restricted to the effectRect
qp.setClipRect(self.effectRect)
# call the default implementation, which will draw the effect
super().draw(qp)
# get the full region that should be painted
fullRegion = QtGui.QRegion(qp.viewport())
# and subtract the effect rectangle
fullRegion -= QtGui.QRegion(self.effectRect)
qp.setClipRegion(fullRegion)
# draw the *source*, which has no effect applied
self.drawSource(qp)
qp.restore()
class Window(QtWidgets.QWidget):
def __init__(self):
super().__init__()
background = QtGui.QPixmap('background.png')
# apply a background to this widget, note that this only serves for the
# graphics effect to know what's outside the boundaries
p = self.palette()
p.setBrush(p.Window, QtGui.QBrush(background))
self.setPalette(p)
self.resize(background.size())
# this layout is only for the child "sub" widget
mainLayout = QtWidgets.QVBoxLayout(self)
mainLayout.setContentsMargins(0, 0, 0, 0)
# the "sub" widget, that contains the main interface
self.subWidget = QtWidgets.QWidget()
mainLayout.addWidget(self.subWidget)
# set the background for the subwidget; note that we can't use setPalette()
# because palette and fonts are inherited by children; using ".QWidget"
# we ensure that the background is only applied to the subwidget
self.subWidget.setStyleSheet('''
.QWidget {
background-image: url(background.png);
}
''')
# some random widgets
subLayout = QtWidgets.QGridLayout(self.subWidget)
for row in range(3):
for col in range(3):
btn = QtWidgets.QPushButton()
subLayout.addWidget(btn, row, col)
btn.setText('Open menu')
btn.setFocus()
btn.clicked.connect(self.openMenu)
# create an instance of our effect subclass, and apply it to the subwidget
self.effect = BlurEffect()
self.subWidget.setGraphicsEffect(self.effect)
self.effect.setEnabled(False)
self.effect.setBlurRadius(10)
# create the menu container, that *HAS* to have this main widget as parent
self.topMenu = QtWidgets.QWidget(self)
self.topMenu.setVisible(False)
self.topMenu.setFixedWidth(200)
# move the menu outside the window left margin
self.topMenu.move(-self.topMenu.width(), 0)
menuLayout = QtWidgets.QVBoxLayout(self.topMenu)
menuLayout.addSpacing(20)
for b in range(4):
btn = QtWidgets.QPushButton('Button {}'.format(b + 1))
menuLayout.addWidget(btn)
menuLayout.addSpacing(10)
closeButton = QtWidgets.QPushButton('Close menu')
menuLayout.addWidget(closeButton)
closeButton.clicked.connect(self.closeMenu)
# a stretch to ensure that the items are always aligned on top
menuLayout.addStretch(1)
# an animation that will move the menu laterally
self.menuAnimation = QtCore.QVariantAnimation()
self.menuAnimation.setDuration(500)
self.menuAnimation.setEasingCurve(QtCore.QEasingCurve.OutQuart)
self.menuAnimation.setStartValue(-self.topMenu.width())
self.menuAnimation.setEndValue(0)
self.menuAnimation.valueChanged.connect(self.resizeMenu)
self.menuAnimation.finished.connect(self.animationFinished)
# a simple transparent widget that is used to hide the menu when
# clicking outside it; the event filter is to capture click events
# it may receive
self.clickGrabber = QtWidgets.QWidget(self)
self.clickGrabber.installEventFilter(self)
self.clickGrabber.setVisible(False)
def resizeMenu(self, value):
# move the menu and set its geometry to the effect
self.topMenu.move(value, 0)
self.effect.setEffectRect(self.topMenu.geometry())
def openMenu(self):
if self.topMenu.x() >= 0:
# the menu is already visible
return
# ensure that the menu starts hidden (that is, with its right border
# aligned to the left of the main widget)
self.topMenu.move(-self.topMenu.width(), 0)
self.topMenu.setVisible(True)
self.topMenu.setFocus()
# enable the effect, set the forward direction for the animation, and
# start it; it's important to set the effect rectangle here too, otherwise
# some flickering might show at the beginning
self.effect.setEffectRect(self.topMenu.geometry())
self.effect.setEnabled(True)
self.menuAnimation.setDirection(QtCore.QVariantAnimation.Forward)
self.menuAnimation.start()
# "show" the grabber (it's invisible, but it's there) and resize it
# to cover the whole window area
self.clickGrabber.setGeometry(self.rect())
self.clickGrabber.setVisible(True)
# ensure that it is stacked under the menu and above everything else
self.clickGrabber.stackUnder(self.topMenu)
def closeMenu(self):
# in case that the menu has changed its size, set again the "start" value
# to its negative width, then set the animation direction to backwards
# and start it
self.menuAnimation.setStartValue(-self.topMenu.width())
self.menuAnimation.setDirection(QtCore.QVariantAnimation.Backward)
self.menuAnimation.start()
# hide the click grabber
self.clickGrabber.setVisible(False)
def animationFinished(self):
# if the animation has ended and the direction was backwards it means that
# the menu has been closed, hide it and disable the effect
if self.menuAnimation.direction() == QtCore.QVariantAnimation.Backward:
self.topMenu.hide()
self.effect.setEnabled(False)
def focusNextPrevChild(self, next):
if self.topMenu.isVisible():
# a small hack to prevent tab giving focus to widgets when the
# menu is visible
return False
return super().focusNextPrevChild(next)
def eventFilter(self, source, event):
if source == self.clickGrabber and event.type() == QtCore.QEvent.MouseButtonPress:
# the grabber has been clicked, close the menu
self.closeMenu()
return super().eventFilter(source, event)
def resizeEvent(self, event):
super().resizeEvent(event)
# always set the menu height to that of the window
self.topMenu.setFixedHeight(self.height())
# resize the grabber to the window rectangle, even if it's invisible
self.clickGrabber.setGeometry(self.rect())
if self.topMenu.isVisible():
# resize the effect rectangle
self.effect.setEffectRect(self.topMenu.geometry())
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
w = Window()
w.resize(640, 570)
w.show()
sys.exit(app.exec_())
Мне нужно иметь возможность применить эффект размытия к нескольким виджетам одновременно
И проблема в том, когда я добавляю
self.effect2 = BlurEffect()
self.subWidget.setGraphicsEffect(self.effect2)
self.effect2.setEnabled(False)
self.effect2.setBlurRadius(10)
после
self.effect = BlurEffect()
self.subWidget.setGraphicsEffect(self.effect)
self.effect.setEnabled(False)
self.effect.setBlurRadius(10)
Я получаю эту ошибку
Traceback (последний вызов был последним): файл "C: \ Users \ пользователь \ Desktop \ test \ widgets \ menu.py ", строка 157, в файле openMenu self.effect.setEffectRect (self.topMenu.geometry ())" C: \ Users \ user \ Desktop \ test \ widgets \ menu.py ", строка 15, в setEffectRect self.update () RuntimeError: упакованный объект C / C ++ типа BlurEffect был удален
Кто-нибудь знает, как это исправить?
photoshop