pyqtpyqt5

Run function when leaving QTabWidget tab


I have multiple tabs that a user can switch between. I need a widget on a given tab to run an exit function when that tab is no longer selected. For example, if the user currently has tab_1 selected, when they switch to tab_2, tab_1 should run some exit function. Is there an event that gets called when a tab looses focus?

I can run functions when a tab is selected using QTabWidget.currentChanged. I could use a variable to keep track of the previously selected tab and select the required exit function using this but that feels clunky.


Solution

  • Keeping track of the "previous" tab index is the only way.

    In fact, that's exactly what QTabWidget (or, to be precise, its QTabBar) does: it maintains an internal "current index" property and eventually changes it if the requested one is different, then emits the currentChanged signal.

    Since there is no way to access the previous index right before the new one is actually changed, you then need to store it on your own.

    One possibility could involve a custom signal that emits the previous index, which you can then connect to a function that eventually calls the required function.

    class CustomTabWidget(QTabWidget):
        _prevIndex = -1
        previousIndexChanged = pyqtSignal(int)
        def __init__(self, *args, **kwargs):
            super().__init__(*args, **kwargs)
            self.currentIndexChanged.connect(self.emitPrevIndex)
    
        def emitPrevIndex(self, index):
            if self._prevIndex != index:
                old = self._prevIndex
                self._prevIndex = index
                self.previousIndexChanged.emit(old)
    
    
    def callExitFunction(index):
        widget = tabWidget.widget(index)
        if widget is not None:
            # call the exit function related to that widget
    
    tabWidget.previousIndexChanged.connect(callExitFunction)
    

    You need to be careful and aware about some important aspects, though; specifically:

    For all of the above, the _prevIndex attribute may probably become inappropriate or even unused, unless you take proper precautions considering what follows:

    If you really need runtime/dynamic tab movement/deletion/insertion, you should consider further precautions, possibly adding proper updates to the _prevIndex attribute, and verifying widget existence/index.