Widget weird hover behavior
-
wrote on 25 Jun 2023, 01:29 last edited by
So I am trying to make a custom widget consisting of a label and a button. The button will be hidden by default and only showed when the user hovers over the widget. I also connect the button to a function for deleting the custom widget.
The problem arise when I add my custom widget to a container with QVBoxLayout applied. When I click the button, the custom widget will be deleted and the item inside the layout will be adjusted. Now the cursor is positioned over another widget.
The issue is the state of this another widget is not updated. The button is not showed, until i move the cursor.
At first i though it is because of my implementation using the enterEvent and leaveEvent, but it looks it have things to do with the qt itself, since the background-color style that I apply to the widget also not updated
Code
from PySide6.QtWidgets import * from PySide6.QtCore import * from PySide6.QtGui import * import sys class Item(QWidget): def __init__(self, text: str): super(Item, self).__init__() # Widget configuration self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True) self.setObjectName("Item") self.setStyleSheet(""" #Item:hover { background: #bbb } #Item QPushButton:hover { background: red } """) # Layout self.setLayout(QHBoxLayout()) # Button button_size_policy = QSizePolicy() button_size_policy.setRetainSizeWhenHidden(True) self.button = QPushButton("X") self.button.setFixedSize(28, 28) self.button.setSizePolicy(button_size_policy) self.button.clicked.connect(lambda: self.setParent(None)) self.layout().addWidget(self.button) self.button.hide() # Label label = QLabel(f"Item {text}") self.layout().addWidget(label) def enterEvent(self, event: QEnterEvent): self.button.show() def leaveEvent(self, event: QEvent): self.button.hide() class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # Container container = QFrame() container.setLayout(QVBoxLayout()) container.layout().setAlignment(Qt.AlignmentFlag.AlignTop) # Populate container for i in range(4): item = Item(str(i)) container.layout().addWidget(item) # Attach container self.setCentralWidget(container) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())
-
So I am trying to make a custom widget consisting of a label and a button. The button will be hidden by default and only showed when the user hovers over the widget. I also connect the button to a function for deleting the custom widget.
The problem arise when I add my custom widget to a container with QVBoxLayout applied. When I click the button, the custom widget will be deleted and the item inside the layout will be adjusted. Now the cursor is positioned over another widget.
The issue is the state of this another widget is not updated. The button is not showed, until i move the cursor.
At first i though it is because of my implementation using the enterEvent and leaveEvent, but it looks it have things to do with the qt itself, since the background-color style that I apply to the widget also not updated
Issue
Code
from PySide6.QtWidgets import * from PySide6.QtCore import * from PySide6.QtGui import * import sys class Item(QWidget): def __init__(self, text: str): super(Item, self).__init__() # Widget configuration self.setAttribute(Qt.WidgetAttribute.WA_StyledBackground, True) self.setObjectName("Item") self.setStyleSheet(""" #Item:hover { background: #bbb } #Item QPushButton:hover { background: red } """) # Layout self.setLayout(QHBoxLayout()) # Button button_size_policy = QSizePolicy() button_size_policy.setRetainSizeWhenHidden(True) self.button = QPushButton("X") self.button.setFixedSize(28, 28) self.button.setSizePolicy(button_size_policy) self.button.clicked.connect(lambda: self.setParent(None)) self.layout().addWidget(self.button) self.button.hide() # Label label = QLabel(f"Item {text}") self.layout().addWidget(label) def enterEvent(self, event: QEnterEvent): self.button.show() def leaveEvent(self, event: QEvent): self.button.hide() class MainWindow(QMainWindow): def __init__(self): super(MainWindow, self).__init__() # Container container = QFrame() container.setLayout(QVBoxLayout()) container.layout().setAlignment(Qt.AlignmentFlag.AlignTop) # Populate container for i in range(4): item = Item(str(i)) container.layout().addWidget(item) # Attach container self.setCentralWidget(container) if __name__ == "__main__": app = QApplication(sys.argv) window = MainWindow() window.show() sys.exit(app.exec())
wrote on 25 Jun 2023, 03:18 last edited by@Dimas-Atmaja said in Widget weird hover behavior:
def enterEvent(self, event: QEnterEvent): self.button.show() def leaveEvent(self, event: QEvent): self.button.hide()
Since the mouse does not actively enter the widget, I think it's not weird, that the event is not received.
You could check/update it yourself as soon as one widget is removed
Mouse events occur when a mouse cursor is moved into, out of, or within a widget, and if the widget has the Qt::WA_Hover attribute.
-
@Dimas-Atmaja said in Widget weird hover behavior:
def enterEvent(self, event: QEnterEvent): self.button.show() def leaveEvent(self, event: QEvent): self.button.hide()
Since the mouse does not actively enter the widget, I think it's not weird, that the event is not received.
You could check/update it yourself as soon as one widget is removed
Mouse events occur when a mouse cursor is moved into, out of, or within a widget, and if the widget has the Qt::WA_Hover attribute.
wrote on 25 Jun 2023, 10:58 last edited by Dimas Atmaja@Pl45m4 Well, I can certainly fix the show and hide issue by listening to moveEvent and updating the widget manually. But how to fix the stylesheet one? Let's say I have a stylesheet like this:
#CustomWidget:hover { background: red; }
As you can see in the gif, the hover style is not applied until I move the cursor. Is there a way to tell the widget to apply this hover style? I am doing self.update() but it's doesn't work.
I am aware that I can do something like this, but I think it is kinda unintuitive.
def enterEvent(self, e) { self.setStyleSheet("hover style") } def leaveEvent(self, e) { self.setStyleSheet("normal style") }
Is there any better solution?
1/3