如何拦截Qt中给定事件发出的所有信号?

时间:2010-01-15 14:04:19

标签: qt debugging pyqt signals-slots

我可以想象,根据事件的不同,可能会有很多,但同时,我想这可能是一种最好的调试方式,也是一个有趣的课程。

为什么我需要它?我正在使用一些基于QWidget的自定义类,当我在同一窗口中取消QDockWidget时,它不会展开。知道在卸载此停靠窗口小部件时发出的信号将帮助我选择在自定义类中覆盖所需的方法。

换句话说,我不想检查文档中的每个可能信号,只是看看当我在我的应用程序中执行某些操作时会发出哪些信号。

5 个答案:

答案 0 :(得分:10)

任何公共API都无法做到这一点。

但是,如果您将代码放入基于QTestLib的单元测试中,则可以使用-vs运行单元测试以打印出每个发出的信号。

答案 1 :(得分:7)

您可能需要查看QSignalSpy课程。 我想虽然你必须手动连接你想窥探的信号。

答案 2 :(得分:2)

我不认为Qt可以做到这一点。你可以

  • 使用QMetaObject :: method和QMetaMethod :: methodType列出类的所有信号;
  • 将您自己的一个插槽连接到所有这些信号;
  • 使用QObject :: sender检查谁调用了一个插槽。

但是在此之后我被困住了。我不认为除了发件人之外,还可以获得有关如何调用插槽的任何信息。

答案 3 :(得分:2)

如果您使用的是PyQT5而不是Qt5,则可以使用Python的自省功能查找任何类的所有信号,并将它们连接到(虚拟对象的)虚拟插槽。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from typing import Iterable

from PyQt5.QtCore import pyqtBoundSignal
from PyQt5.QtCore import pyqtSlot
from PyQt5.QtCore import QObject


def list_all_signals(obj: QObject) -> Iterable[pyqtBoundSignal]:
    attr_names = dir(obj)
    attributes = (getattr(obj, attr_name) for attr_name in attr_names)
    connectable = filter(lambda l: hasattr(l, "connect"), attributes)

    return connectable


class SignalListener(QObject):
    @pyqtSlot()
    def universal_slot(self, *args, **kwargs):
        print("Signal caught" + 30 * "-")
        print("sender:", self.sender())
        meta_method = (
            self.sender().metaObject().method(self.senderSignalIndex())
        )
        print("signal:", meta_method.name())
        print("signal signature:", meta_method.methodSignature())


SIGNAL_LISTENER = SignalListener()


def spy_on_all_signals(
    obj: QObject, listener: SignalListener = SIGNAL_LISTENER
):
    for signal in list_all_signals(obj):
        signal.connect(SIGNAL_LISTENER.universal_slot)

虚拟插槽现在打印有关对象发出的所有信号的信息。 例如,如果您监视像这样的随机QLineEdit:

some_line_edit = QLineEdit(self)
spy_on all_signals(some_line_edit)

进入和退出行编辑的可能日志如下:

Signal caught ------------------------------
sender: <PyQt5.QtWidgets.QLineEdit object at 0x7f220f7a3370>
signal: b'cursorPositionChanged'
signal signature: b'cursorPositionChanged(int,int)'
Signal caught ------------------------------
sender: <PyQt5.QtWidgets.QLineEdit object at 0x7f220f7a3370>
signal: b'selectionChanged'
signal signature: b'selectionChanged()'
Signal caught ------------------------------
sender: <PyQt5.QtWidgets.QLineEdit object at 0x7f220f7a3370>
signal: b'selectionChanged'
signal signature: b'selectionChanged()'
Signal caught ------------------------------
sender: <PyQt5.QtWidgets.QLineEdit object at 0x7f220f7a3370>
signal: b'editingFinished'
signal signature: b'editingFinished()'

答案 4 :(得分:0)

结帐signal spying。对QT库有很深入的了解,并监视信号/插槽。