Issue
My intention is to make a Hover effect for multiple frames at a time. For Example, Below is my code, I have three frames. Two inner frames and one outer frame. If the mouse enters where ever, that is, either in an outer frame or in the inner frames, I need a hover effect for three frames, at a time.
import sys
from PyQt5.QtCore import *
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class Dynamic_Widgets(QWidget):
def __init__(self):
super().__init__()
self.setWindowTitle("Dynamic Widget")
self.lbl = QLabel("this is text")
self.btn = QPushButton("Button")
self.lbl_1 = QLabel("-----------")
self.lbl_r = QLabel("My text ")
self.btn_r = QPushButton("Button888888")
self.lbl_1r = QLabel(('\u2261' * 60))
my_font_1 = QFont("Arial", 10, QFont.Bold)
my_font_1.setLetterSpacing(QFont.AbsoluteSpacing, -6)
self.lbl_1r.setFont(my_font_1)
self.vbox = QHBoxLayout()
self.frame = QFrame()
self.frame_right = QFrame()
self.frame_all = QFrame()
self.frame.setObjectName("ob_frame")
self.frame_right.setObjectName("ob_frame_right")
self.frame_all.setObjectName("ob_frame_all")
self.frame.setProperty("type", "2")
self.frame_right.setProperty("type", "2")
self.frame_all.setProperty("type", "2")
self.framebox = QVBoxLayout(self.frame)
self.framebox_right = QVBoxLayout(self.frame_right)
self.framebox_all = QHBoxLayout(self.frame_all)
self.framebox_all.setContentsMargins(0, 0, 0, 0)
self.framebox_all.setSpacing(0)
self.framebox_all.addWidget(self.frame)
self.framebox_all.addWidget(self.frame_right)
self.vbox.addWidget(self.frame_all)
self.setLayout(self.vbox)
self.frame.setFixedSize(100, 100)
self.frame_right.setFixedSize(100, 100)
self.frame_all.setFixedSize(220, 120)
self.frame.setStyleSheet(f"QFrame#ob_frame{{background-color: lightgreen;}}")
self.frame_right.setStyleSheet(f"QFrame#ob_frame_right{{background-color: lightgreen;}}")
self.frame_all.setStyleSheet(f"QFrame#ob_frame_all{{background-color: green;}}")
#self.frame_all.setStyleSheet('QFrame:hover { background: yellow; }')
self.framebox.addWidget(self.lbl)
self.framebox.addWidget(self.btn)
self.framebox.addWidget(self.lbl_1)
self.framebox_right.addWidget(self.lbl_r)
self.framebox_right.addWidget(self.btn_r)
self.framebox_right.addWidget(self.lbl_1r)
def main():
app = QApplication(sys.argv)
ex = Dynamic_Widgets()
ex.show()
sys.exit(app.exec_())
if __name__ == '__main__':
main()
Solution
Setting individual stylesheets can be useful for very specific and relatively static styling, but, in general, it's usually better to have a centralized QSS or, at least, different QSS set for common parents.
In normal situations, a single Class:hover
selector would suffice, but if the children have properties that need to be overridden by a change in the parent, it is necessary to install an event filter on the parent.
Considering that the event filter will match Enter
and Leave
events, the hover
selector doesn't make a lot of sense anymore: we can create a "default" style sheet stored as instance attribute and set/override it depending on those events:
class Dynamic_Widgets(QWidget):
def __init__(self):
# ...
self.frame_all_qss = '''
QFrame#ob_frame_all {
background-color: green;
}
QFrame#ob_frame {
background-color: lightgreen;
}
QFrame#ob_frame_right {
background-color: lightgreen;
}
'''
self.frame_all.setStyleSheet(self.frame_all_qss)
self.frame_all.installEventFilter(self)
def eventFilter(self, obj, event):
if obj == self.frame_all:
if event.type() == event.Enter:
res = obj.event(event)
self.frame_all.setStyleSheet(
'QFrame#ob_frame_all { background: yellow; }')
return res
elif event.type() == event.Leave:
res = obj.event(event)
self.frame_all.setStyleSheet(self.frame_all_qss)
return res
return super().eventFilter(obj, event)
Answered By - musicamante
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.