如何重写Qt原生类QStatusBar的槽函数,让重写实现被其他方法调用?
clearMessage Isn't Called on Timeout The core issue here is that QStatusBar::clearMessage() is not a virtual function in Qt 5.12.6. When the C++ timer connected in showMessage() fires, it invokes the base class's clearMessage() directly via Qt's meta-object system (using the SLOT() macro), which bypasses your Python override. Python can only override C++ methods marked as virtual—non-virtual methods will always execute the C++ implementation when called from native Qt code.
Solution: Take Control of the Timer in Python
To ensure your custom clearMessage() is called in all scenarios (manual triggers and timeouts), reimplement showMessage() to manage the timer yourself in Python instead of relying on Qt's internal timer. This way, the timeout signal will directly call your overridden method.
Here's the fixed code:
from PySide2 import QtWidgets, QtCore class MyStatus(QtWidgets.QStatusBar): def __init__(self, parent=None): super().__init__(parent) self._timeout_timer = None def showMessage(self, message, timeout=0): # Cancel any existing timeout timer if self._timeout_timer: self._timeout_timer.stop() self._timeout_timer.deleteLater() self._timeout_timer = None # Call the base class's showMessage without timeout super().showMessage(message) # Start a new timer if a timeout is specified if timeout > 0: self._timeout_timer = QtCore.QTimer(self) self._timeout_timer.timeout.connect(self.clearMessage) self._timeout_timer.start(timeout) print('Showing message') def clearMessage(self): super().clearMessage() print('Clearing message') # Clean up the timer after it triggers if self._timeout_timer: self._timeout_timer.stop() self._timeout_timer.deleteLater() self._timeout_timer = None
How This Works:
- We replace Qt's internal timer with a Python-managed
QTimer, ensuring the timeout signal connects directly to your customclearMessage(). - Any existing timer is stopped and cleaned up when
showMessage()is called again, preventing stale timers from firing unexpectedly. - Manual calls to
clearMessage()still trigger your custom logic, as they invoke the Python override directly.
Handling Edge Cases:
- If you need to detect when the message is cleared by calling
showMessage(""), add a check in yourshowMessage()override:def showMessage(self, message, timeout=0): # ... existing code ... if not message: print('Clearing message (via empty showMessage)')
Content of the question originates from Stack Exchange, asked by Erwan Leroy

