Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

PySide6 - Funtion on enterEvent or hovering on child widget.



  • I was trying to run a function/animation on hovering over a widget. The following code shows an example of what I was trying to do.

    import os
    import sys
    
    from PySide6.QtCore import *
    from PySide6.QtGui import *
    from PySide6.QtWidgets import *
    
    
    
    class MainWindow(QWidget):
        def __init__(self):
            super(MainWindow, self).__init__()
    
            self.lay = QHBoxLayout()
            self.sidebar = QWidget()
            self.sidebar_layout = QHBoxLayout()
            self.button_container = QWidget()
            self.b1 = QPushButton("Button1")
            self.b2 = QPushButton("Button2")
            self.button_container_layout = QVBoxLayout()
    
            self.popup = QWidget()
    
            self.anim_popup = QPropertyAnimation(self.popup, b"geometry")
    
            self.InitUI()
    
        def InitUI(self):
            self.resize(500, 400)
    
            self.popup.setStyleSheet("background: red;")
            self.popup.setGeometry(-100, -100, 0, 0)
            self.popup.setParent(self)
    
            self.button_container_layout.addWidget(self.b1)
            self.button_container_layout.addWidget(self.b2)
            self.button_container.setStyleSheet("background: rgb(80, 80, 80);")
            self.button_container.setFixedHeight(100)
            self.button_container.setMouseTracking(True)
            self.button_container.setLayout(self.button_container_layout)
    
            self.sidebar_layout.addWidget(self.button_container)
            self.sidebar.setFixedWidth(100)
            self.sidebar.setStyleSheet("background: rgb(40, 40, 40);")
            self.sidebar.setLayout(self.sidebar_layout)
    
            self.lay.addWidget(self.sidebar)
            self.setLayout(self.lay)
    
        def AnimPopup(self):
            self.anim_popup.setStartValue(QRect(-100, -100, 0, 0))
            self.anim_popup.setEndValue(QRect(100, 100, 100, 100))
            self.anim_popup.setDuration(1000)
            self.anim_popup.start()
    
        def enterEvent(self, event):
            if self.button_container.rect().contains(event.pos()):
                print("under mouse")
                self.AnimPopup()
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        mw = MainWindow()
        mw.show()
        sys.exit(app.exec_())
    

    The I tried the following code;

        def enterEvent(self, event):
            if self.button_container.underMouse():
                print("under mouse")
                self.AnimPopup()
    

    It doesn't work as intended, animate self.popup when mouse is over self.button_container and works when I remove the condition for mouse over self.button_container, ie, enterEvent for just the main window works. I'm obviously missing out on something important and can't figure out what. Any help much appreciated.
    Thank you.


  • Lifetime Qt Champion

    Hi,

    When you hover the button, you are not inside QMainWindow anymore for that mouse related event.

    If you to handle everything through your main window, you should check event filtering.



  • @tIk90wT
    Indeed, because you are overriding the enterEvent of MainWindow. But you want to detect entering self.button_container.

    Either subclass that so that you can override its enterEvent, or (more likely I think, to keep the code in MainWindow) look at [virtual]bool QObject::eventFilter(QObject *watched, QEvent *event) and use that in MainWindow to watch for entering self.button_container. The example in that topic shows the approach.



  • Answer

    import os
    import sys
    from PySide6.QtCore import *
    from PySide6.QtGui import *
    from PySide6.QtWidgets import *
    
    
    class MainWindow(QWidget):
        def __init__(self):
            super(MainWindow, self).__init__()
    
            self.lay = QHBoxLayout()
            self.sidebar = QWidget()
            self.sidebar_layout = QHBoxLayout()
            self.button_container = QWidget()
            self.b1 = QPushButton("Button1")
            self.b2 = QPushButton("Button2")
            self.button_container_layout = QVBoxLayout()
    
            self.popup = QWidget()
    
            self.anim_popup = QPropertyAnimation(self.popup, b"geometry")
    
            self.InitUI()
    
        def InitUI(self):
            self.resize(500, 400)
    
            self.button_container.installEventFilter(self)
    
            self.popup.setStyleSheet("background: red;")
            self.popup.setGeometry(-100, -100, 0, 0)
            self.popup.setParent(self)
    
            self.button_container_layout.addWidget(self.b1)
            self.button_container_layout.addWidget(self.b2)
            self.button_container.setStyleSheet("background: rgb(80, 80, 80);")
            self.button_container.setFixedHeight(100)
            self.button_container.setMouseTracking(True)
            self.button_container.setLayout(self.button_container_layout)
    
            self.sidebar_layout.addWidget(self.button_container)
            self.sidebar.setFixedWidth(100)
            self.sidebar.setMouseTracking(True)
            self.sidebar.setStyleSheet("background: rgb(40, 40, 40);")
            self.sidebar.setLayout(self.sidebar_layout)
            self.lay.addWidget(self.sidebar)
            self.lay.setAlignment(self.sidebar, Qt.AlignLeft)
            self.setLayout(self.lay)
    
        def AnimPopup(self):
            self.anim_popup.setStartValue(QRect(-100, -100, 0, 0))
            self.anim_popup.setEndValue(QRect(100, 100, 100, 100))
            self.anim_popup.setDuration(1000)
            self.anim_popup.start()
    
        def eventFilter(self, obj, ev):
            if ev.type() == QEvent.Enter:
                print("Entered")
                self.AnimPopup()
    
            return False
    
    
    if __name__ == '__main__':
        app = QApplication(sys.argv)
        mw = MainWindow()
        mw.show()
        sys.exit(app.exec_())
    
    


  • Thanks to @JonB and @SGaist.


Log in to reply