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

9
我可以想象,根据事件的不同,可能会有许多信号,但与此同时,我认为这可能是一种最好的调试方式,并且是一个有趣的课程。
为什么需要它?我正在使用基于QWidget的自定义类,当我从同一窗口中分离出一个基于QDockWidget的对象时,该类不会展开。知道在分离此dock小部件时发出哪些信号将帮助我选择需要覆盖的方法。
换句话说,我不想从文档中检查每个可能的信号,只想看到当我在应用程序中执行某些操作时发出了哪些信号。
5个回答

10

任何公共API都无法实现这一点。

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


7

您可能需要查看QSignalSpy类。不过,我认为您需要手动连接您想要监视的信号。


2

我认为使用Qt不可能实现这一点。您可以使用QMetaObject :: method和QMetaMethod :: methodType列出类的所有信号;

  • 将自己的一个槽附加到所有这些信号上;
  • 使用QObject :: sender检查谁调用了一个槽。

但是在此之后,我卡住了。我认为除了发送者之外,无法获取有关如何调用插槽的任何信息。


谢谢建议!我该怎么做?QMetaObject :: method需要一个参数。我不确定我需要传递什么。 - kayleeFrye_onDeck

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:

Original Answer翻译成:"最初的回答"

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()'

0

看看信号监听。可以获得有关QT库和信号/槽监听的一些很棒的见解。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接