LeaveEvent of a QTableWidget, not of a QTableWidgetItem



  • Hi everybody :)

    My fisrt topic here !

    I use the mouseMoveEvent of my QTableWidget for view a dialog with a QPixmap from my QPixmapCache.
    With indexAt, I know what item is highlighted and I move my dialog at the QCursor position.
    I doesn't use the tooltip with image because is too long to load many images... With this system is instant.
    To show my dialog, no problem.

    But I need to know when the cursor leave my wydget to hide my dialog.

    So I have tryed to use leaveEvent, but it's called when the cursor leave a QTableWidgetItem...
    I have tryed to watch the HoverLeave event with eventFilter in the QTableWidget's viewport or tryed to use leaveEvent of the parent and send signal. That works if I don't use the mouseMoveEvent of my QTableWidget, if I use this event, the signal is sended and the event is emit when the cursor leave the QTableWidgetItem...

    After many try, I succeeded with the leaveEvent of the parent who test if the QCursor is in or out itself :

    def leaveEvent(self, event):
           widgetRect = self.geometry()
           widgetRect.moveTopLeft(self.parentWidget().mapToGlobal(widgetRect.topLeft()))
    
           if not widgetRect.contains(QCursor.pos()):
               self.mouseLeaveEvent.emit()
    
           event.accept()
    

    In your opinion, is there any simpler?

    I'm a little programmer, so I don't understant all situation :)

    I program in pyqt5 and sorry for my english !!

    Have a nice day !


  • Lifetime Qt Champion

    Hi,

    Where are you implementing that leaveEvent method ?



  • Hi :)
    In the parent QFrame.
    I have tried with the viewport but it doesn't work everytime...

    My code :

    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    class ItemTableWidgetFrameCustom(QFrame):
        mouseLeaveEvent = pyqtSignal()
     
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
        def leaveEvent(self, event):
            widgetRect = self.geometry()
            widgetRect.moveTopLeft(self.parentWidget().mapToGlobal(widgetRect.topLeft()))
     
            if not widgetRect.contains(QCursor.pos()):
                self.mouseLeaveEvent.emit()
     
            event.accept()
      
    
    #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    class ItemTableWidgetCustom(QTableWidget):
        def __init__(self, papa, Parent=None):
            super(ItemTableWidgetCustom, self).__init__(Parent)
     
            ### ............
            self.setMouseTracking(True)
     
            self.BigPapa = Parent
     
            self.papa = papa
            self.papa.mouseLeaveEvent.connect(lambda: self.ToolTipCustom.hide())
     
     
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
        def CreateCacheDialog(self, PixmapCache):
            self.ToolTipCustom = ToolTipCustom(self.BigPapa)
     
            self.PixmapCache = PixmapCache
     
            self.LastIndex = None
     
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
        def mouseMoveEvent(self, event):
            if not self.PixmapCache: return
     
            if self.LastIndex == self.indexAt(event.pos()): return
    
            try:
                Row = self.indexAt(event.pos()).row()
                Column = self.indexAt(event.pos()).column()
                Cell = self.item(Row, Column)
                AlbumId = Cell.data(Qt.UserRole)[0]
     
            except:
                if self.ToolTipCustom.isVisible(): self.ToolTipCustom.hide()
                return
     
            self.LastIndex = self.indexAt(event.pos())
     
            PixmapImage = self.PixmapCache.find(AlbumId)
     
            if PixmapImage:
                self.ToolTipCustom.setPixmap(PixmapImage)
     
                x = QCursor.pos().x() - self.BigPapa.geometry().x() + 10
                y = QCursor.pos().y() - self.BigPapa.geometry().y() + 10
     
                if self.BigPapa.geometry().width() - x - 200 < 0 : x = QCursor.pos().x() - self.BigPapa.geometry().x() - 210
     
                if self.BigPapa.geometry().height() - y - 200 < 0 : y = QCursor.pos().y() - self.BigPapa.geometry().y() - 210
     
               self.ToolTipCustom.move(x, y)
                if not self.ToolTipCustom.isVisible(): self.ToolTipCustom.show()
     
     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
    class ToolTipCustom(QLabel):
        def __init__(self, Parent=None):
            super(ToolTipCustom, self).__init__(Parent)
            self.resize(200, 200) 
            self.setScaledContents(True)
    
      #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~#
        def enterEvent(self, event):
            self.hide()
    

    and I use :

    self.ui.ItemTableWidgetFrame.__class__ = ItemTableWidgetFrameCustom
     
    self.ui.ItemTableWidget = ItemTableWidgetCustom(self.ui.ItemTableWidgetFrame, self)
     
    self.ui.ItemTableWidgetLayout.addWidget(self.ui.ItemTableWidget)
    

    That works as I want but it can improve, I guess.


  • Lifetime Qt Champion

    Why not use an event filter or directly subclass QTableWidget ?



  • What signal with the eventFiltrer ?
    Because the QEvent::HoverLeave and QEvent::Leave are emit when I leave a QTableWidgetItem, not when I leave the QTableWidget.

    If I subclass the leaveEvent of the QTableWidget, same result.
    But you're right, I can use this event and the geometry test. One widget removed :)


  • Lifetime Qt Champion

    Don't mix signals/slots and events. While they might be related in multithreading context, they are different aspects of Qt.


Log in to reply