Reputation: 47
I need to make the background of the "menu_pos_" block translucent and blur everything on the back. And leave the text clear. This effect is usually called the frosted glass effect.
But unfortunately I could only blur the whole widget
import sys
from PyQt5.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PyQt5 import QtWidgets
from PyQt5 import QtGui
from PyQt5 import QtCore
from PyQt5.QtCore import QPropertyAnimation, QPoint
from PyQt5.QtWidgets import QGraphicsEffect
#Or
'''
from PySide2.QtCore import (QCoreApplication, QMetaObject, QObject, QPoint,
QRect, QSize, QUrl, Qt)
from PySide2 import QtWidgets
from PySide2 import QtGui
from PySide2 import QtCore
from PySide2.QtCore import QPropertyAnimation, QPoint
from PySide2.QtWidgets import QGraphicsEffect
'''
class test_mynu(QtWidgets.QWidget):
def __init__(self, arr="", parent=None):
super(test_mynu, self).__init__(parent)
self._expand = False # - self.__expand ; + self._expand !!!
#------menu_pos_block------
self.menu_pos_block = QtWidgets.QWidget()
blur = QtWidgets.QGraphicsBlurEffect(blurRadius=5)
self.menu_pos_block.setGraphicsEffect(blur)
#------menu_pos_block_layout------
self.menu_pos_block_layout = QtWidgets.QHBoxLayout(self.menu_pos_block)
self.menu_pos_block_layout.setObjectName(u"menu_pos_block_layout")
#------menu_pos_label------
self.menu_pos_label = QtWidgets.QLabel()
self.menu_pos_label.setText(arr)
self.menu_pos_block_layout.addWidget(self.menu_pos_label)
#------ADD------
lay = QtWidgets.QHBoxLayout(self)
lay.addWidget(self.menu_pos_block)
class MainWindow(QtWidgets.QMainWindow):
# number of radio
def num(self):
return 3
def __init__(self, parent=None):
super().__init__(parent)
self.toggle_animations = QtCore.QSequentialAnimationGroup(self)
#------centralwidget------
centralwidget = QtWidgets.QWidget()
centralwidget.setObjectName(u"centralwidget")
self.setCentralWidget(centralwidget)
#------layout------
central_w_layout = QtWidgets.QGridLayout(centralwidget)
central_w_layout.setObjectName(u"central_w_layout")
#------Spacer------
vs_up = QtWidgets.QSpacerItem(17, 105, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
central_w_layout.addItem(vs_up, 0, 1, 1, 1)
hs_left = QtWidgets.QSpacerItem(327, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
central_w_layout.addItem(hs_left, 1, 0, 1, 1)
hs_right = QtWidgets.QSpacerItem(326, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
central_w_layout.addItem(hs_right, 1, 2, 1, 1)
vs_down = QtWidgets.QSpacerItem(20, 105, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
central_w_layout.addItem(vs_down, 2, 1, 1, 1)
#------block------
block = QtWidgets.QWidget()
block.setObjectName(u"block")
central_w_layout.addWidget(block, 1, 1, 1, 1) ######
#------layout------
layout_block = QtWidgets.QVBoxLayout(block)
layout_block.setObjectName(u"layout_block")
#------menu_block------
menu_block = QtWidgets.QWidget()
menu_block.setObjectName(u"menu_block")
layout_block.addWidget(menu_block) ######
#------menu_layout------
menu_layout = QtWidgets.QHBoxLayout(menu_block)
menu_layout.setObjectName(u"menu_layout")
self.menu_but = []
self.menu_pos = []
self.menu_by_pos = None
for i in range(self.num()):
menu_pos_block = test_mynu("menu_{}".format(i))
menu_pos_block.setObjectName("menu_pos_{}".format(i))
self.menu_pos.append(menu_pos_block)
self.menu_pos[i].setGeometry(QRect(menu_pos_block.width(), menu_pos_block.height(), 151, 181))
menu_layout.addWidget(self.menu_pos[i])
#------menu_block_but------
self.menu_block_but = QtWidgets.QWidget()
self.menu_block_but.setObjectName(u"menu_block_but")
menu_layout.addWidget(self.menu_block_but) ######
#------menu_block_but_layout------
menu_block_but_layout = QtWidgets.QVBoxLayout(self.menu_block_but)
menu_block_but_layout.setObjectName(u"menu_block_but_layout")
#------menu_but_radio------
for i in range(self.num()):
menu_but_radio = QtWidgets.QRadioButton('{}'.format(i))
menu_but_radio.setObjectName("{}".format(i))
menu_but_radio.toggled.connect(self.menu_animation)
self.menu_but.append(menu_but_radio)
menu_block_but_layout.addWidget(menu_but_radio)
# Связывание меню к кнопкам и наоборот
self.menu_by_but = dict()
self.but_by_menu = dict()
for i in range(self.num()):
but = self.menu_but[i]
menu = self.menu_pos[i]
self.menu_by_but[menu] = but
self.but_by_menu[but] = menu
menu_block_content = QtWidgets.QWidget()
menu_block_content.setObjectName(u"menu_block_content")
menu_layout.addWidget(menu_block_content) ######
#------menu_content_layout------
menu_content_layout = QtWidgets.QHBoxLayout(menu_block_content)
menu_content_layout.setObjectName(u"menu_content_layout")
#------menu_label------
menu_label = QtWidgets.QLabel()
menu_label.setText('text, text text, text')
menu_content_layout.addWidget(menu_label)
self.num = 0
self.menu_pos_ter = []
def menu_animation(self):
self.num =self.num+1
self.toggle_animations.clear()
num = int(self.sender().objectName())
self.menu_pos_ter.append(self.menu_pos[num])
# Хитрая сортировка, что сначала вернет элемент с _expand = True
for menu in sorted(self.menu_pos_ter, key=lambda x: x._expand):
pos1 = QPoint(self.menu_block_but.x() - menu.width(), menu.y())
pos2 = QPoint(self.menu_block_but.x() +self.menu_block_but.width(), menu.y())
but = self.menu_by_but[menu]
menu.raise_()
self.menu_block_but.raise_()
if but.isChecked():
start_pos = pos1
end_pos = pos2
else:
start_pos = menu.pos()
end_pos = pos1
anim = QPropertyAnimation(menu, b"pos")
anim.setDuration(1000)
anim.setStartValue(start_pos)
anim.setEndValue(end_pos)
self.toggle_animations.addAnimation(anim)
if (self.num == 1) or (self.num == 3):
self.toggle_animations.start()
self.menu_pos_ter.clear()
if self.num == 3 :
self.num = 1
print("--x--")
StyleSheet = """
#centralwidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget{
background:#000;
color:#fff;
}
#centralwidget QWidget,
#centralwidget QWidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget,
#centralwidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget QWidget{
background:#fff;
color:#000;
}
#click_me{
background:#000;
color:#fff;
}
"""
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
app.setStyleSheet(StyleSheet)
w = MainWindow()
w.resize(640, 570) #Size window
w.show()
sys.exit(app.exec_())
I want the widget to look like this html template.
$(".menu-btn input").change(function() {
$('.menu_1').removeClass('menu_1_active');
$('.menu_2').removeClass('menu_2_active'); $('.menu_3').removeClass('menu_3_active');
$('.sidebar_menu_1').removeClass('sidebar_menu_1_active');
$('.frame_menu_1').removeClass('frame_menu_1_active');
$('.sidebar_menu_2').removeClass('sidebar_menu_2_active');
$('.frame_menu_2').removeClass('frame_menu_2_active');
$('.sidebar_menu_3').removeClass('sidebar_menu_3_active');
$('.frame_menu_3').removeClass('frame_menu_3_active');
var name = $(this).val();
setTimeout(function(){
$('.menu_'+name).toggleClass('menu_'+name+'_active');
$('.sidebar_menu_'+name).toggleClass('sidebar_menu_'+name+'_active');
$('.frame_menu_'+name).toggleClass('frame_menu_'+name+'_active');
}, 1000);
});
/*return*/
$("#block_blur").append('<div class="frame_menu_1" ><div class="full sidebar_menu_1"></div></div>');
$("#block_blur").append('<div class="frame_menu_2" ><div class="full sidebar_menu_2"></div></div>');
$("#block_blur").append('<div class="frame_menu_3" ><div class="full sidebar_menu_3"></div></div>');
/*copy menu */
$('.copy').clone().appendTo('.full');
.content > h3{
padding:10px;
margin:2px;
}
.title_1{
background:red;
}
.title_2{
background:blue;
}
.title_3{
background:green;
}
.title_4{
background:url('https://i.ytimg.com/vi/slZdLNewXrE/maxresdefault.jpg');
}
.title_5{
background:yellow;
}
.menu-btn {
display: flex;
flex-direction: column;
background-color: #333;
position: absolute;
left: 10px;
top: 10px;
z-index:110;
}
.menu-btn > input{
margin:2px;
}
.menu > div{
width: 200px;
height: 200px;
background-color:#18182178;
position: absolute;
left: 0px;
top: 0px;
text-align: center;
color:white;
transition: 1s;
transform: translateX(-100%);
z-index:100;
}
.menu .menu_1_active,
.menu .menu_2_active,
.menu .menu_3_active{
transform: translateX(0%);
}
/*blur*/
.frame_menu_1,
.frame_menu_2,
.frame_menu_3{
z-index: 10;
overflow: hidden;
position: absolute;
width: 200px !important;
height: 200px !important;
top: 200px !important;
left: 0px !important;
transition: 1s;
transform: translate(0%, -100%);
transform: translate(-100%, -100%);
}
.frame_menu_1_active,
.frame_menu_2_active,
.frame_menu_3_active{
transition: 1s;
transform: translate(-100%, -100%);
transform: translate(0%, -100%);
}
/*copy*/
.sidebar_menu_1,
.sidebar_menu_2,
.sidebar_menu_3{
width: 100% !important;
height: 100% !important;
position: absolute;
filter:blur(8px);
-webkit-filter:blur(8px);
top: -200px;
left: 0px;
transition: 1s;
transform: translate(0%, 100%);
transform: translate(100%, 100% );
}
/*active*/
.sidebar_menu_1_active,
.sidebar_menu_2_active,
.sidebar_menu_3_active{
transition: 1s;
transform: translate(100%, 100% );
transform: translate(0%, 100%);
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="copy">
<div class="menu-btn">
<input type="radio" id="rad_men" name="red" value="1"/>
<input type="radio" id="rad_men" name="red" value="2"/>
<input type="radio" id="rad_men" name="red" value="3"/>
</div>
<div class="menu">
<div class="menu_1">menu 1</div>
<div class="menu_2">menu 2</div>
<div class="menu_3">menu 3</div>
</div>
<div class="content">
<h3 class="title_1" >text text text</h3>
<h3 class="title_2" >text text text</h3>
<h3 class="title_3" >text text text</h3>
<h3 class="title_4" >text text text</h3>
<h3 class="title_5" >text text text</h3>
</div>
</div>
<div id="block_blur"></div>
I had to use JS to copy all the HTML code, frame overflow: hidden; and synchronize movements with buttons.
If possible, I would like to avoid this method, because it is the wildest horror.
Upvotes: 0
Views: 4476
Reputation: 1
You can find the answer here.
I have created graphical effects and animation that can be applied to any PyQt / PySide widget to display blurred content under widget. Also you can add many translucent backgrounds to widget (color or gradient)
Shine animation can be adjusted in angle, color, width and duration.
Move animation can be adjusted in offset and duration.
This effect only works with child widgets. If it is applied to the main widget, then it will not work. https://github.com/GvozdevLeonid/BackDrop-in-PyQt-PySide
Upvotes: 0
Reputation: 243965
The QGraphicsEffect affects the widget and the children of the widget therefore the QLabel is also affected. To avoid this, a possible solution is to use a QWidget where another QWidget is established through a layout, and to that last widget apply the effect, and add a QLabel to the initial QWidget so that the QLabel and the QWidget will effectively have the same parent , raise_() must also be used so that the QLabel is on top of all:
from PyQt5 import QtCore, QtGui, QtWidgets
class BlurLabel(QtWidgets.QWidget):
def __init__(self, text, parent=None):
super().__init__(parent)
self.setAttribute(QtCore.Qt.WA_StyledBackground)
widget = QtWidgets.QWidget()
widget.setStyleSheet("""QWidget{ background:#fff; color:#000;}""")
blur_effect = QtWidgets.QGraphicsBlurEffect(blurRadius=5)
widget.setGraphicsEffect(blur_effect)
self._label = QtWidgets.QLabel(
text=text, alignment=QtCore.Qt.AlignCenter, parent=self
)
self.label.setStyleSheet(""" background-color : transparent; color : black""")
self.label.setContentsMargins(10, 0, 10, 0)
lay = QtWidgets.QVBoxLayout(self)
lay.addWidget(widget)
@property
def label(self):
return self._label
def sizeHint(self):
return self._label.sizeHint()
def resizeEvent(self, event):
self._label.resize(self.size())
self._label.raise_()
return super().resizeEvent(event)
class ButtonWidget(QtWidgets.QWidget):
clicked = QtCore.pyqtSignal(int)
def __init__(self, parent=None):
super().__init__(parent)
self.setAttribute(QtCore.Qt.WA_StyledBackground)
self.setStyleSheet("""background:#fff;""")
vlay = QtWidgets.QVBoxLayout(self)
group = QtWidgets.QButtonGroup(self)
group.buttonClicked[int].connect(self.clicked)
for i in range(3):
radiobutton = QtWidgets.QRadioButton(str(i))
radiobutton.setStyleSheet("""background:#000; color:#fff;""")
group.addButton(radiobutton, i)
vlay.addWidget(radiobutton)
class LabelWidget(QtWidgets.QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.setAttribute(QtCore.Qt.WA_StyledBackground)
self.setStyleSheet("""background:#fff;""")
vlay = QtWidgets.QVBoxLayout(self)
label = QtWidgets.QLabel("text, text, text, text")
label.setStyleSheet("""background:#000; color:#fff;""")
vlay.addWidget(label)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
container = QtWidgets.QWidget()
container.setStyleSheet("""QWidget{ background:#000;}""")
hlay_menus = QtWidgets.QHBoxLayout()
hlay_menus.setContentsMargins(0, 6, 0, 6)
self.menus = []
for i in range(3):
menu = BlurLabel("menu-{}".format(i))
hlay_menus.addWidget(menu)
self.menus.append(menu)
self.button_widget = ButtonWidget()
self.button_widget.clicked.connect(self.onClicked)
self.label_widget = LabelWidget()
lay = QtWidgets.QHBoxLayout(container)
lay.addLayout(hlay_menus)
lay.addWidget(self.button_widget)
lay.addWidget(self.label_widget)
container.setFixedSize(container.sizeHint())
hlay = QtWidgets.QHBoxLayout()
hlay.addStretch(0)
hlay.addWidget(container)
hlay.addStretch(0)
central_widget = QtWidgets.QWidget()
self.setCentralWidget(central_widget)
vlay = QtWidgets.QVBoxLayout(central_widget)
vlay.addStretch(0)
vlay.addLayout(hlay)
vlay.addStretch(0)
self.last_id = -1
@QtCore.pyqtSlot(int)
def onClicked(self, id_):
menu = self.menus[id_]
if not hasattr(menu, "animation"):
animation = QtCore.QPropertyAnimation(menu, b"pos", duration=1000)
animation.setStartValue(menu.pos())
animation.setEndValue(
QtCore.QPoint(self.label_widget.pos().x() + 5, menu.pos().y())
)
animation.start()
menu.animation = animation
if self.last_id != -1:
last_menu = self.menus[self.last_id]
last_menu.animation.setDirection(QtCore.QAbstractAnimation.Backward)
last_menu.animation.start()
last_menu.raise_()
menu.animation.setDirection(QtCore.QAbstractAnimation.Forward)
menu.animation.start()
menu.raise_()
self.button_widget.raise_()
self.last_id = id_
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
Upvotes: 2