如何监控QT信号?

8
在调试过程中,我想看看我的程序事件循环等待什么。它可能被淹没了,我想知道是哪些信号引起的,而不必(手动)添加特定的日志消息到每个Q_EMIT。可能的解决方案是观察一些包含事件队列的内部Qt数据结构(是否有这样的东西?如何实现?),或者为每个发射的信号编写日志消息(是否可行?)。还有其他的想法吗?(QT 4.8 在 Windows 上,使用 Visual Studio 2012)

你想要监视信号还是事件? - vahancho
我想要监控信号。 - Ronen
1
也许这个可以帮助你:http://doc.qt.io/qt-5/qsignalspy.html? - vahancho
谢谢!但是如果我理解正确的话,QSignalSpy是特定于对象(和信号)的。我有很多对象发出很多信号,我会讨厌手动处理它们。 - Ronen
你可以使用QEventLoop来运行自己的事件循环,而不是应用程序的事件循环,并且可以进行调试! - Dmitry Sazonov
1
@Ronen,你可能想要研究一下这种方法:http://levelfour.googlecode.com/svn/branches/dev/vd2/GCF/source/menustrip/GenericSignalSpy.cpp - vahancho
3个回答

5

信号和事件是两个完全不相关的事情。

我想看看我的程序事件循环中等待什么。它可能被淹没了。

首先,让我们搞清楚术语:

  • 事件队列是存储事件直到传递的地方;
  • 事件循环是排空事件队列并将事件传递给QObjects的东西,
  • 事件洪水发生在每个事件传递期间平均有多个事件被添加到队列。

只有两个原因可能导致事件队列被淹没:

  1. 处理某些事件需要太长时间(例如,当您的代码被阻塞时):由于时间问题,队列的排出速率低于填充速率。
  2. 每个事件传递时添加了一个以上的事件(平均值):由于事件乘法,队列的填充速率高于排出速率 - 这与任何时间无关。它的合适名称是事件风暴

如果要检测代码块是否过长,您可以使用我为另一个答案编写的工具

要知道任何给定线程正在等待多少事件,请使用未记录的qGlobalPostedEventsCount()。将其添加到上面链接的工具的代码中。


1

我不确定这对你是否足够,但你可以尝试在实现eventFilter()的QObjects之间安装event filters来达到目的。

class MyWidget : public QWidget
{
    QGraphicsView myView;
    MyWidget()
    {
        myView->installEventFilter(this);
        // incoming events to myView are shown on the standard output
    }
};

你可以通过阅读文档来更加创造性地使用它。

谢谢,但我不想只针对特定的对象。我想看到所有的信号,但手动操作太繁琐了。 - Ronen
1
如果您在QCoreApplication或QApplication对象上安装事件过滤器,而不是像这里所示的QGraphicsView上安装,您可以获取所有事件。 - nos

1
Qt文档中事件和过滤器部分说明:
也可以在QApplicationQCoreApplication对象上安装事件过滤器,以过滤整个应用程序的所有事件。这种全局事件过滤器会在特定于对象的过滤器之前被调用。它非常强大,但也会减慢整个应用程序中每个单独事件的传递速度。
因此,您可以在QApplication或QCoreApplication上创建一个事件过滤器,并监视所有事件,检查它们的type
另外,QCoreApplication使用虚拟notify函数将事件传递给对象。重写QCoreApplication将允许您查看事件和最初*将传递给的QObject。
*请注意,如果接收对象忽略事件,则事件将传播到父对象。
如果您选择使用notify,请注意此函数的未来方向:

未来方向:在Qt 6中,不会为生存在主线程之外的对象调用此函数。需要该功能的应用程序应在此期间寻找其他解决方案以满足其事件检查需求。该更改可能会扩展到主线程,导致此函数被弃用。


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