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

发布于 2024-08-18 04:07:30 字数 257 浏览 6 评论 0原文

我可以想象,根据事件的不同,可能会有相当多的错误,但同时,我想这可能是最好的调试方法,也是一个有趣的教训。

我为什么需要它?我正在使用一些基于QWidget的自定义类,当我在同一窗口中取消附加QDockWidget时,该自定义类不会扩展。了解取消连接此停靠小部件时发出的信号将帮助我选择需要在自定义类中覆盖的方法。

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

I can imagine that there might be quite a few of them depending on the event, but at the same time, I guess this can be a best way to debug, and an interesting lesson.

Why would I need it? I'm using some custom class based on the QWidget, which does not expand when I de-attach a QDockWidget based in the same window. Knowing what signals are emitted when this dock widget is being de-attached would help me to chose which method I need to overwrite in my custom class.

In other words, I don't want to check every possible signal from the documentation, but just see which signals are emitted when I perform some action in my application.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

唐婉 2024-08-25 04:07:30

这对于任何公共 API 来说都是不可能的。

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

This isn't possible with any public API.

But, if you put your code into a QTestLib-based unit test, you can run the unit test with -vs to print out every emitted signal.

北斗星光 2024-08-25 04:07:30

您可能想查看 QSignalSpy 类。
我认为虽然你必须手动连接你想要监视的信号。

You may want to take a look at the QSignalSpy class.
I think though you have to connect manually the signal you want to spy.

一抹微笑 2024-08-25 04:07:30

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

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

但我被困在这之后。我认为,除了发送者之外,还无法获得有关插槽如何被调用的任何信息。

I don't think this is possible with Qt. You can

  • list all signals of a class using QMetaObject::method and QMetaMethod::methodType;
  • attach one of your own slots to all of those signals;
  • check who invoked a slot using QObject::sender.

But I'm stuck after this. I don't think that, besides the sender, any information can be obtained about how a slot got invoked.

﹎☆浅夏丿初晴 2024-08-25 04:07:30

如果您使用 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()'

If you're using PyQT5 instead of Qt5, you can use Python's introspection abilities to find all signals of any class and connect them to a dummy slot (of a dummy object).

#!/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)

The dummy slot now prints info about all signals emitted by an object.
For example, if you spy on a random QLineEdit like this:

some_line_edit = QLineEdit(self)
spy_on all_signals(some_line_edit)

A possible log of entering and exiting the line edit might look like this:

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()'
顾忌 2024-08-25 04:07:30

查看信号间谍。对 QT 库和监视信号/槽有了一些深入的了解。

Check out signal spying. Got some great insight of QT library and spying on signals/slots.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文